diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2015-02-27 16:45:55 +0900 |
---|---|---|
committer | Lorenzo Colitti <lorenzo@google.com> | 2015-02-27 16:45:55 +0900 |
commit | 57947f02c00bb03651e3f9427c880211c689db7f (patch) | |
tree | 33b45eabd9dc617f8d3aa0bd3f0aa2f4116d536f | |
parent | 32d768792bcd5860512998543f6904d91da1a9b7 (diff) | |
download | netd-57947f02c00bb03651e3f9427c880211c689db7f.tar.gz |
Add oif rules that allow UID 0 to bypass the VPN.
This is needed for wifi calling so that the kernel (which does
not set marks) can tee packets towards the modem. It also fixes
things like not being able to reply to DHCP requests from
tethered clients when a VPN is up.
System apps can already bypass the VPN using explicit marks, so
allowing UID 0 to do so does not create additional bypass VPN
issues.
Bug: 19500693
Change-Id: Ie324026893637e9bd8e7aa65a37579569390e7b7
-rw-r--r-- | server/RouteController.cpp | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/server/RouteController.cpp b/server/RouteController.cpp index 6a6a470d..40734050 100644 --- a/server/RouteController.cpp +++ b/server/RouteController.cpp @@ -38,6 +38,7 @@ namespace { // BEGIN CONSTANTS -------------------------------------------------------------------------------- const uint32_t RULE_PRIORITY_VPN_OVERRIDE_SYSTEM = 10000; +const uint32_t RULE_PRIORITY_VPN_OVERRIDE_OIF = 10500; const uint32_t RULE_PRIORITY_VPN_OUTPUT_TO_LOCAL = 11000; const uint32_t RULE_PRIORITY_SECURE_VPN = 12000; const uint32_t RULE_PRIORITY_EXPLICIT_NETWORK = 13000; @@ -539,15 +540,25 @@ WARN_UNUSED_RESULT int modifyExplicitNetworkRule(unsigned netId, uint32_t table, // // Supports apps that use SO_BINDTODEVICE or IP_PKTINFO options and the kernel that already knows // the outgoing interface (typically for link-local communications). -WARN_UNUSED_RESULT int modifyOutputInterfaceRule(const char* interface, uint32_t table, - Permission permission, uid_t uidStart, - uid_t uidEnd, bool add) { +WARN_UNUSED_RESULT int modifyOutputInterfaceRules(const char* interface, uint32_t table, + Permission permission, uid_t uidStart, + uid_t uidEnd, bool add) { Fwmark fwmark; Fwmark mask; fwmark.permission = permission; mask.permission = permission; + // If this rule does not specify a UID range, then also add a corresponding high-priority rule + // for UID. This covers forwarded packets and system daemons such as the tethering DHCP server. + if (uidStart == INVALID_UID && uidEnd == INVALID_UID) { + if (int ret = modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_VPN_OVERRIDE_OIF, + table, fwmark.intValue, mask.intValue, IIF_NONE, interface, + UID_ROOT, UID_ROOT)) { + return ret; + } + } + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_OUTPUT_INTERFACE, table, fwmark.intValue, mask.intValue, IIF_NONE, interface, uidStart, uidEnd); } @@ -663,9 +674,9 @@ int configureDummyNetwork() { return -errno; } - if ((ret = modifyOutputInterfaceRule(interface, table, PERMISSION_NONE, - INVALID_UID, INVALID_UID, ACTION_ADD))) { - ALOGE("Can't create oif rule for %s: %s", interface, strerror(-ret)); + if ((ret = modifyOutputInterfaceRules(interface, table, PERMISSION_NONE, + INVALID_UID, INVALID_UID, ACTION_ADD))) { + ALOGE("Can't create oif rules for %s: %s", interface, strerror(-ret)); return ret; } @@ -711,8 +722,8 @@ WARN_UNUSED_RESULT int modifyLocalNetwork(unsigned netId, const char* interface, if (int ret = modifyIncomingPacketMark(netId, interface, PERMISSION_NONE, add)) { return ret; } - return modifyOutputInterfaceRule(interface, ROUTE_TABLE_LOCAL_NETWORK, PERMISSION_NONE, - INVALID_UID, INVALID_UID, add); + return modifyOutputInterfaceRules(interface, ROUTE_TABLE_LOCAL_NETWORK, PERMISSION_NONE, + INVALID_UID, INVALID_UID, add); } WARN_UNUSED_RESULT int modifyPhysicalNetwork(unsigned netId, const char* interface, @@ -729,7 +740,7 @@ WARN_UNUSED_RESULT int modifyPhysicalNetwork(unsigned netId, const char* interfa add)) { return ret; } - if (int ret = modifyOutputInterfaceRule(interface, table, permission, INVALID_UID, INVALID_UID, + if (int ret = modifyOutputInterfaceRules(interface, table, permission, INVALID_UID, INVALID_UID, add)) { return ret; } @@ -752,8 +763,8 @@ WARN_UNUSED_RESULT int modifyVirtualNetwork(unsigned netId, const char* interfac range.second, add)) { return ret; } - if (int ret = modifyOutputInterfaceRule(interface, table, PERMISSION_NONE, range.first, - range.second, add)) { + if (int ret = modifyOutputInterfaceRules(interface, table, PERMISSION_NONE, range.first, + range.second, add)) { return ret; } } |