diff options
| author | Lorenzo Colitti <lorenzo@google.com> | 2016-12-16 18:45:03 +0900 |
|---|---|---|
| committer | Lorenzo Colitti <lorenzo@google.com> | 2016-12-19 14:28:05 +0900 |
| commit | 2b078678aafceeefea6a70e96ab8ddefe515d027 (patch) | |
| tree | bb9338f5dc2945ed6dd5779f05182bca00f4f771 /server/RouteController.cpp | |
| parent | 3889ab680bb8c115f7f179be02675d7adf5017d8 (diff) | |
Set both legacy and new UID routing attributes.
This should work on kernels that support either, as long as they
are older than 4.8.
Test: netd_integration_test passes with updated iproute and kernel
Test: netd_integration_test passes with existing iproute and kernel
Test: ConnectivityManagerTest and HostsideVpnTests pass on existing kernel
Test: ConnectivityManagerTest and HostsideVpnTests pass on updated kernel
Bug: 16355602
Change-Id: I9a2ef08ba2782587f43ea7d0609f5f07f6c3adb0
Diffstat (limited to 'server/RouteController.cpp')
| -rw-r--r-- | server/RouteController.cpp | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/server/RouteController.cpp b/server/RouteController.cpp index d85bde47..48c609d6 100644 --- a/server/RouteController.cpp +++ b/server/RouteController.cpp @@ -74,15 +74,19 @@ const char* const ROUTE_TABLE_NAME_LEGACY_SYSTEM = "legacy_system"; const char* const ROUTE_TABLE_NAME_LOCAL = "local"; const char* const ROUTE_TABLE_NAME_MAIN = "main"; -// TODO: These values aren't defined by the Linux kernel, because our UID routing changes are not -// upstream (yet?), so we can't just pick them up from kernel headers. When (if?) the changes make -// it upstream, we'll remove this and rely on the kernel header values. For now, add a static assert -// that will warn us if upstream has given these values some other meaning. +// TODO: These values aren't defined by the Linux kernel, because legacy UID routing (as used in N +// and below) was not upstreamed. Now that the UID routing code is upstream, we should remove these +// and rely on the kernel header values. const uint16_t FRA_UID_START = 18; const uint16_t FRA_UID_END = 19; -static_assert(FRA_UID_START > FRA_MAX, - "Android-specific FRA_UID_{START,END} values also assigned in Linux uapi. " - "Check that these values match what the kernel does and then update this assertion."); + +// These values are upstream, but not yet in our headers. +// TODO: delete these definitions when updating the headers. +const uint16_t FRA_UID_RANGE = 20; +struct fib_rule_uid_range { + __u32 start; + __u32 end; +}; 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; @@ -114,15 +118,16 @@ constexpr uint16_t U16_RTA_LENGTH(uint16_t x) { // These are practically const, but can't be declared so, because they are used to initialize // non-const pointers ("void* iov_base") in iovec arrays. -rtattr FRATTR_PRIORITY = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY }; -rtattr FRATTR_TABLE = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_TABLE }; -rtattr FRATTR_FWMARK = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_FWMARK }; -rtattr FRATTR_FWMASK = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_FWMASK }; -rtattr FRATTR_UID_START = { U16_RTA_LENGTH(sizeof(uid_t)), FRA_UID_START }; -rtattr FRATTR_UID_END = { U16_RTA_LENGTH(sizeof(uid_t)), FRA_UID_END }; +rtattr FRATTR_PRIORITY = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY }; +rtattr FRATTR_TABLE = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_TABLE }; +rtattr FRATTR_FWMARK = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_FWMARK }; +rtattr FRATTR_FWMASK = { U16_RTA_LENGTH(sizeof(uint32_t)), FRA_FWMASK }; +rtattr FRATTR_UID_START = { U16_RTA_LENGTH(sizeof(uid_t)), FRA_UID_START }; +rtattr FRATTR_UID_END = { U16_RTA_LENGTH(sizeof(uid_t)), FRA_UID_END }; +rtattr FRATTR_UID_RANGE = { U16_RTA_LENGTH(sizeof(fib_rule_uid_range)), FRA_UID_RANGE }; -rtattr RTATTR_TABLE = { U16_RTA_LENGTH(sizeof(uint32_t)), RTA_TABLE }; -rtattr RTATTR_OIF = { U16_RTA_LENGTH(sizeof(uint32_t)), RTA_OIF }; +rtattr RTATTR_TABLE = { U16_RTA_LENGTH(sizeof(uint32_t)), RTA_TABLE }; +rtattr RTATTR_OIF = { U16_RTA_LENGTH(sizeof(uint32_t)), RTA_OIF }; uint8_t PADDING_BUFFER[RTA_ALIGNTO] = {0, 0, 0, 0}; @@ -309,6 +314,7 @@ WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint8_t rtattr fraIifName = { U16_RTA_LENGTH(iifLength), FRA_IIFNAME }; rtattr fraOifName = { U16_RTA_LENGTH(oifLength), FRA_OIFNAME }; + struct fib_rule_uid_range uidRange = { uidStart, uidEnd }; iovec iov[] = { { NULL, 0 }, @@ -321,10 +327,20 @@ WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint8_t { &fwmark, mask ? sizeof(fwmark) : 0 }, { &FRATTR_FWMASK, mask ? sizeof(FRATTR_FWMASK) : 0 }, { &mask, mask ? sizeof(mask) : 0 }, + // Rules that contain both legacy and new UID routing attributes will work on old kernels, + // which will simply ignore the FRA_UID_RANGE attribute since it is larger than their + // FRA_MAX. They will also work on kernels that are not too new: + // - FRA_UID_START clashes with FRA_PAD in 4.7, but that shouldn't be a problem because + // FRA_PAD has no validation. + // - FRA_UID_END clashes with FRA_L3MDEV in 4.8 and above, and will cause an error because + // FRA_L3MDEV has a maximum length of 1. + // TODO: delete the legacy UID routing code before running it on 4.8 or above. { &FRATTR_UID_START, isUidRule ? sizeof(FRATTR_UID_START) : 0 }, { &uidStart, isUidRule ? sizeof(uidStart) : 0 }, { &FRATTR_UID_END, isUidRule ? sizeof(FRATTR_UID_END) : 0 }, { &uidEnd, isUidRule ? sizeof(uidEnd) : 0 }, + { &FRATTR_UID_RANGE, isUidRule ? sizeof(FRATTR_UID_RANGE) : 0 }, + { &uidRange, isUidRule ? sizeof(uidRange) : 0 }, { &fraIifName, iif != IIF_NONE ? sizeof(fraIifName) : 0 }, { iifName, iifLength }, { PADDING_BUFFER, iifPadding }, |
