Revert "Revert "Set both legacy and new UID routing attributes.""
This reverts commit 6cb2c6ba9d8a68ae05ed4b7acae2d9bb9bb2fbbc.
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index a6fa3a2..f48e958 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -80,15 +80,11 @@
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.");
// None of our regular routes specify priority, which causes them to have the default priority.
// For default throw routes, we use a fixed priority of 100000.
@@ -119,15 +115,16 @@
// 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 };
rtattr RTATTR_PRIO = { U16_RTA_LENGTH(sizeof(uint32_t)), RTA_PRIORITY };
uint8_t PADDING_BUFFER[RTA_ALIGNTO] = {0, 0, 0, 0};
@@ -287,6 +284,7 @@
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 },
@@ -299,10 +297,20 @@
{ &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 },