summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/NetlinkCommands.h8
-rw-r--r--server/RouteController.cpp5
2 files changed, 9 insertions, 4 deletions
diff --git a/server/NetlinkCommands.h b/server/NetlinkCommands.h
index 7c0d4a86..ef1ff48a 100644
--- a/server/NetlinkCommands.h
+++ b/server/NetlinkCommands.h
@@ -29,7 +29,13 @@ namespace net {
const sockaddr_nl KERNEL_NLADDR = {AF_NETLINK, 0, 0, 0};
const uint16_t NETLINK_REQUEST_FLAGS = NLM_F_REQUEST | NLM_F_ACK;
-const uint16_t NETLINK_CREATE_REQUEST_FLAGS = NETLINK_REQUEST_FLAGS | NLM_F_CREATE | NLM_F_EXCL;
+const uint16_t NETLINK_ROUTE_CREATE_FLAGS = NETLINK_REQUEST_FLAGS | NLM_F_CREATE | NLM_F_EXCL;
+// Don't create rules with NLM_F_EXCL, because operations such as changing network permissions rely
+// on make-before-break. The kernel did not complain about duplicate rules until ~4.9, at which
+// point it started returning EEXIST. See for example b/69607866 . We can't just ignore the EEXIST
+// because if we hit it, the rule was not created, but we will think it was, and we'll then trip up
+// trying to delete it.
+const uint16_t NETLINK_RULE_CREATE_FLAGS = NETLINK_REQUEST_FLAGS | NLM_F_CREATE;
const uint16_t NETLINK_DUMP_FLAGS = NLM_F_REQUEST | NLM_F_DUMP;
// Generic code for processing netlink dumps.
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index 27990759..198c8a82 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -283,7 +283,7 @@ WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint8_t
{ PADDING_BUFFER, oifPadding },
};
- uint16_t flags = (action == RTM_NEWRULE) ? NETLINK_CREATE_REQUEST_FLAGS : NETLINK_REQUEST_FLAGS;
+ uint16_t flags = (action == RTM_NEWRULE) ? NETLINK_RULE_CREATE_FLAGS : NETLINK_REQUEST_FLAGS;
for (size_t i = 0; i < ARRAY_SIZE(AF_FAMILIES); ++i) {
rule.family = AF_FAMILIES[i];
if (int ret = sendNetlinkRequest(action, flags, iov, ARRAY_SIZE(iov), nullptr)) {
@@ -400,8 +400,7 @@ WARN_UNUSED_RESULT int modifyIpRoute(uint16_t action, uint32_t table, const char
{ &PRIO_THROW, isDefaultThrowRoute ? sizeof(PRIO_THROW) : 0 },
};
- uint16_t flags = (action == RTM_NEWROUTE) ? NETLINK_CREATE_REQUEST_FLAGS :
- NETLINK_REQUEST_FLAGS;
+ uint16_t flags = (action == RTM_NEWROUTE) ? NETLINK_ROUTE_CREATE_FLAGS : NETLINK_REQUEST_FLAGS;
int ret = sendNetlinkRequest(action, flags, iov, ARRAY_SIZE(iov), nullptr);
if (ret) {
ALOGE("Error %s route %s -> %s %s to table %u: %s",