diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/NetlinkCommands.h | 8 | ||||
-rw-r--r-- | server/RouteController.cpp | 5 |
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", |