diff options
author | Ken Chen <cken@google.com> | 2020-11-24 11:38:54 +0800 |
---|---|---|
committer | Ken Chen <cken@google.com> | 2021-02-02 06:12:23 +0800 |
commit | 8738e1c449f444ac037af6b9878506bcc588ed0d (patch) | |
tree | bf79c16768f3eb42a413de933799ad620e20b8ba /server/RouteController.cpp | |
parent | 68e99cd08fad35deb758a087f0b274c2af710e6a (diff) | |
download | netd-8738e1c449f444ac037af6b9878506bcc588ed0d.tar.gz |
Configurable per application default network
Extend networkAddUidRanges and networkRemoveUidRanges from
virtual-network-only to physical network. With this change, the
ConnectivityService can replace the default physical network for
specified applications without changing applications' code.
Bug: 176507580
Test: cd system/netd; atest
Test: atest HostsideVpnTests
Test: atest FrameworksNetTests
Change-Id: I556043f4401746bcf844a0c15a7d92aec12faad3
Diffstat (limited to 'server/RouteController.cpp')
-rw-r--r-- | server/RouteController.cpp | 120 |
1 files changed, 113 insertions, 7 deletions
diff --git a/server/RouteController.cpp b/server/RouteController.cpp index 0daf54d2..3a09b5d7 100644 --- a/server/RouteController.cpp +++ b/server/RouteController.cpp @@ -735,14 +735,101 @@ int RouteController::configureDummyNetwork() { INVALID_UID, INVALID_UID, add); } +[[nodiscard]] static int modifyUidExplicitNetworkRule(unsigned netId, uint32_t table, + uid_t uidStart, uid_t uidEnd, bool add) { + if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { + ALOGE("modifyUidExplicitNetworkRule, invalid UIDs (%u, %u)", uidStart, uidEnd); + return -EUSERS; + } + + Fwmark fwmark; + Fwmark mask; + + fwmark.netId = netId; + mask.netId = FWMARK_NET_ID_MASK; + + fwmark.explicitlySelected = true; + mask.explicitlySelected = true; + + // Access to this network is controlled by UID rules, not permission bits. + fwmark.permission = PERMISSION_NONE; + mask.permission = PERMISSION_NONE; + + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_UID_EXPLICIT_NETWORK, table, + fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); +} + +[[nodiscard]] static int modifyUidImplicitNetworkRule(unsigned netId, uint32_t table, + uid_t uidStart, uid_t uidEnd, bool add) { + if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { + ALOGE("modifyUidImplicitNetworkRule, invalid UIDs (%u, %u)", uidStart, uidEnd); + return -EUSERS; + } + + Fwmark fwmark; + Fwmark mask; + + fwmark.netId = netId; + mask.netId = FWMARK_NET_ID_MASK; + + fwmark.explicitlySelected = false; + mask.explicitlySelected = true; + + // Access to this network is controlled by UID rules, not permission bits. + fwmark.permission = PERMISSION_NONE; + mask.permission = PERMISSION_NONE; + + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_UID_IMPLICIT_NETWORK, table, + fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); +} + +[[nodiscard]] static int modifyUidDefaultNetworkRule(uint32_t table, uid_t uidStart, uid_t uidEnd, + bool add) { + if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { + ALOGE("modifyUidDefaultNetworkRule, invalid UIDs (%u, %u)", uidStart, uidEnd); + return -EUSERS; + } + + Fwmark fwmark; + Fwmark mask; + + fwmark.netId = NETID_UNSET; + mask.netId = FWMARK_NET_ID_MASK; + + // Access to this network is controlled by UID rules, not permission bits. + fwmark.permission = PERMISSION_NONE; + mask.permission = PERMISSION_NONE; + + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_UID_DEFAULT_NETWORK, table, + fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); +} + /* static */ int RouteController::modifyPhysicalNetwork(unsigned netId, const char* interface, - Permission permission, bool add) { + const UidRanges& uidRanges, Permission permission, + bool add, bool modifyNonUidBasedRules) { uint32_t table = getRouteTableForInterface(interface); if (table == RT_TABLE_UNSPEC) { return -ESRCH; } + for (const UidRangeParcel& range : uidRanges.getRanges()) { + if (int ret = modifyUidExplicitNetworkRule(netId, table, range.start, range.stop, add)) { + return ret; + } + if (int ret = modifyUidImplicitNetworkRule(netId, table, range.start, range.stop, add)) { + return ret; + } + if (int ret = modifyUidDefaultNetworkRule(table, range.start, range.stop, add)) { + return ret; + } + } + + if (!modifyNonUidBasedRules) { + // we are done. + return 0; + } + if (int ret = modifyIncomingPacketMark(netId, interface, permission, add)) { return ret; } @@ -1033,8 +1120,10 @@ int RouteController::removeInterfaceFromLocalNetwork(unsigned netId, const char* } int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* interface, - Permission permission) { - if (int ret = modifyPhysicalNetwork(netId, interface, permission, ACTION_ADD)) { + Permission permission, + const UidRanges& uidRanges) { + if (int ret = modifyPhysicalNetwork(netId, interface, uidRanges, permission, ACTION_ADD, + MODIFY_NON_UID_BASED_RULES)) { return ret; } maybeModifyQdiscClsact(interface, ACTION_ADD); @@ -1043,8 +1132,10 @@ int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* i } int RouteController::removeInterfaceFromPhysicalNetwork(unsigned netId, const char* interface, - Permission permission) { - if (int ret = modifyPhysicalNetwork(netId, interface, permission, ACTION_DEL)) { + Permission permission, + const UidRanges& uidRanges) { + if (int ret = modifyPhysicalNetwork(netId, interface, uidRanges, permission, ACTION_DEL, + MODIFY_NON_UID_BASED_RULES)) { return ret; } if (int ret = flushRoutes(interface)) { @@ -1084,11 +1175,14 @@ int RouteController::removeInterfaceFromVirtualNetwork(unsigned netId, const cha int RouteController::modifyPhysicalNetworkPermission(unsigned netId, const char* interface, Permission oldPermission, Permission newPermission) { + UidRanges noUidRanges; // Add the new rules before deleting the old ones, to avoid race conditions. - if (int ret = modifyPhysicalNetwork(netId, interface, newPermission, ACTION_ADD)) { + if (int ret = modifyPhysicalNetwork(netId, interface, noUidRanges, newPermission, ACTION_ADD, + MODIFY_NON_UID_BASED_RULES)) { return ret; } - return modifyPhysicalNetwork(netId, interface, oldPermission, ACTION_DEL); + return modifyPhysicalNetwork(netId, interface, noUidRanges, oldPermission, ACTION_DEL, + MODIFY_NON_UID_BASED_RULES); } int RouteController::addUsersToRejectNonSecureNetworkRule(const UidRanges& uidRanges) { @@ -1157,6 +1251,18 @@ int RouteController::removeVirtualNetworkFallthrough(unsigned vpnNetId, return modifyVpnFallthroughRule(RTM_DELRULE, vpnNetId, physicalInterface, permission); } +int RouteController::addUsersToPhysicalNetwork(unsigned netId, const char* interface, + const UidRanges& uidRanges) { + return modifyPhysicalNetwork(netId, interface, uidRanges, PERMISSION_NONE, ACTION_ADD, + !MODIFY_NON_UID_BASED_RULES); +} + +int RouteController::removeUsersFromPhysicalNetwork(unsigned netId, const char* interface, + const UidRanges& uidRanges) { + return modifyPhysicalNetwork(netId, interface, uidRanges, PERMISSION_NONE, ACTION_DEL, + !MODIFY_NON_UID_BASED_RULES); +} + // Protects sInterfaceToTable. std::mutex RouteController::sInterfaceToTableLock; std::map<std::string, uint32_t> RouteController::sInterfaceToTable; |