diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2021-08-12 12:03:24 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2021-08-12 22:34:55 +0000 |
commit | f237df3092cb6d8316a49e9abccdf8c94ae7cb46 (patch) | |
tree | 389d5f648f0e28282ce9b077d1c0ff513f88b78c | |
parent | 2d4975f0c055ed9ee6ef9050c03fb19214d648b5 (diff) | |
parent | 99f5d10a0267a330e3aabeb9503c8bb9531f612c (diff) | |
download | netd-f237df3092cb6d8316a49e9abccdf8c94ae7cb46.tar.gz |
Merge ab/7633965
Bug: 169893837
Merged-In: I14e544285d4096c404e33b79bc877836210523db
Change-Id: I5129e704a57d5ba0aa21be90ad81f2af79839dcd
37 files changed, 1458 insertions, 218 deletions
diff --git a/server/Android.bp b/server/Android.bp index cf0a29c5..9c89041a 100644 --- a/server/Android.bp +++ b/server/Android.bp @@ -12,7 +12,7 @@ java_library { sdk_version: "system_current", min_sdk_version: "29", static_libs: [ - "netd_aidl_interface-V6-java", + "netd_aidl_interface-V7-java", ], apex_available: [ "//apex_available:platform", // used from services.net @@ -36,7 +36,7 @@ cc_library_static { cc_library_static { name: "netd_aidl_interface-lateststable-ndk_platform", whole_static_libs: [ - "netd_aidl_interface-V6-ndk_platform", + "netd_aidl_interface-V7-ndk_platform", ], apex_available: [ "com.android.resolv", @@ -47,7 +47,7 @@ cc_library_static { cc_library_static { name: "netd_aidl_interface-lateststable-cpp", whole_static_libs: [ - "netd_aidl_interface-V6-cpp", + "netd_aidl_interface-V7-cpp", ], } @@ -68,6 +68,8 @@ aidl_interface { "binder/android/net/TetherOffloadRuleParcel.aidl", "binder/android/net/TetherStatsParcel.aidl", "binder/android/net/UidRangeParcel.aidl", + // Add new AIDL classes in android.net.netd.aidl to consist with other network modules. + "binder/android/net/netd/aidl/**/*.aidl", ], backend: { cpp: { @@ -101,6 +103,7 @@ aidl_interface { "4", "5", "6", + "7", ], } @@ -219,7 +222,7 @@ cc_library_static { "libqtaguid", "libssl", "libsysutils", - "netd_aidl_interface-V6-cpp", + "netd_aidl_interface-V7-cpp", "netd_event_listener_interface-V1-cpp", ], aidl: { @@ -262,7 +265,7 @@ cc_binary { "libselinux", "libsysutils", "libutils", - "netd_aidl_interface-V6-cpp", + "netd_aidl_interface-V7-cpp", "netd_event_listener_interface-V1-cpp", "oemnetd_aidl_interface-cpp", ], @@ -360,7 +363,7 @@ cc_test { "libnetd_server", "libnetd_test_tun_interface", "libqtaguid", - "netd_aidl_interface-V6-cpp", + "netd_aidl_interface-V7-cpp", "netd_event_listener_interface-V1-cpp", ], shared_libs: [ diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp index 05c515d3..1f5dc976 100644 --- a/server/NetdNativeService.cpp +++ b/server/NetdNativeService.cpp @@ -56,6 +56,7 @@ using android::net::NativeNetworkType; using android::net::TetherOffloadRuleParcel; using android::net::TetherStatsParcel; using android::net::UidRangeParcel; +using android::net::netd::aidl::NativeUidRangeConfig; using android::netdutils::DumpWriter; using android::netdutils::ScopedIndent; using android::os::ParcelFileDescriptor; @@ -400,7 +401,8 @@ binder::Status NetdNativeService::networkAddUidRanges( int32_t netId, const std::vector<UidRangeParcel>& uidRangeArray) { // NetworkController::addUsersToNetwork is thread-safe. ENFORCE_NETWORK_STACK_PERMISSIONS(); - int ret = gCtls->netCtrl.addUsersToNetwork(netId, UidRanges(uidRangeArray)); + int ret = gCtls->netCtrl.addUsersToNetwork(netId, UidRanges(uidRangeArray), + UidRanges::DEFAULT_SUB_PRIORITY); return statusFromErrcode(ret); } @@ -408,7 +410,22 @@ binder::Status NetdNativeService::networkRemoveUidRanges( int32_t netId, const std::vector<UidRangeParcel>& uidRangeArray) { // NetworkController::removeUsersFromNetwork is thread-safe. ENFORCE_NETWORK_STACK_PERMISSIONS(); - int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, UidRanges(uidRangeArray)); + int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, UidRanges(uidRangeArray), + UidRanges::DEFAULT_SUB_PRIORITY); + return statusFromErrcode(ret); +} + +binder::Status NetdNativeService::networkAddUidRangesParcel(const NativeUidRangeConfig& config) { + ENFORCE_NETWORK_STACK_PERMISSIONS(); + int ret = gCtls->netCtrl.addUsersToNetwork(config.netId, UidRanges(config.uidRanges), + config.subPriority); + return statusFromErrcode(ret); +} + +binder::Status NetdNativeService::networkRemoveUidRangesParcel(const NativeUidRangeConfig& config) { + ENFORCE_NETWORK_STACK_PERMISSIONS(); + int ret = gCtls->netCtrl.removeUsersFromNetwork(config.netId, UidRanges(config.uidRanges), + config.subPriority); return statusFromErrcode(ret); } diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h index 1e995ef2..9779f368 100644 --- a/server/NetdNativeService.h +++ b/server/NetdNativeService.h @@ -74,6 +74,10 @@ class NetdNativeService : public BinderService<NetdNativeService>, public BnNetd const std::vector<UidRangeParcel>& uids) override; binder::Status networkRemoveUidRanges(int32_t netId, const std::vector<UidRangeParcel>& uids) override; + binder::Status networkAddUidRangesParcel( + const netd::aidl::NativeUidRangeConfig& uidRangesConfig) override; + binder::Status networkRemoveUidRangesParcel( + const netd::aidl::NativeUidRangeConfig& uidRangesConfig) override; binder::Status networkRejectNonSecureVpn(bool enable, const std::vector<UidRangeParcel>& uids) override; binder::Status networkAddRouteParcel(int32_t netId, const RouteInfoParcel& route) override; diff --git a/server/Network.cpp b/server/Network.cpp index cba9edf5..72a15454 100644 --- a/server/Network.cpp +++ b/server/Network.cpp @@ -70,22 +70,66 @@ std::string Network::toString() const { return repr.str(); } -bool Network::appliesToUser(uid_t uid) const { - return mUidRanges.hasUid(uid); +std::string Network::uidRangesToString() const { + if (mUidRangeMap.empty()) { + return ""; + } + + std::ostringstream result; + for (auto it = mUidRangeMap.begin(); it != mUidRangeMap.end(); ++it) { + result << "prio " << it->first << " " << it->second.toString(); + if (std::next(it) != mUidRangeMap.end()) result << "; "; + } + return result.str(); +} + +// Check if the user has been added to this network. If yes, the highest priority of matching +// setting is returned by subPriority. Thus caller can make choice among several matching +// networks. +bool Network::appliesToUser(uid_t uid, uint32_t* subPriority) const { + for (const auto& [priority, uidRanges] : mUidRangeMap) { + if (uidRanges.hasUid(uid)) { + *subPriority = priority; + return true; + } + } + return false; } -bool Network::hasInvalidUidRanges(const UidRanges& uidRanges) const { +void Network::addToUidRangeMap(const UidRanges& uidRanges, uint32_t subPriority) { + auto iter = mUidRangeMap.find(subPriority); + if (iter != mUidRangeMap.end()) { + iter->second.add(uidRanges); + } else { + mUidRangeMap[subPriority] = uidRanges; + } +} + +void Network::removeFromUidRangeMap(const UidRanges& uidRanges, uint32_t subPriority) { + auto iter = mUidRangeMap.find(subPriority); + if (iter != mUidRangeMap.end()) { + iter->second.remove(uidRanges); + if (iter->second.empty()) { + mUidRangeMap.erase(subPriority); + } + } else { + ALOGW("uidRanges with priority %u not found", subPriority); + } +} + +bool Network::canAddUidRanges(const UidRanges& uidRanges, uint32_t subPriority) const { if (uidRanges.overlapsSelf()) { ALOGE("uid range %s overlaps self", uidRanges.toString().c_str()); - return true; + return false; } - if (uidRanges.overlaps(mUidRanges)) { - ALOGE("uid range %s overlaps %s", uidRanges.toString().c_str(), - mUidRanges.toString().c_str()); - return true; + auto iter = mUidRangeMap.find(subPriority); + if (iter != mUidRangeMap.end() && uidRanges.overlaps(iter->second)) { + ALOGE("uid range %s overlaps priority %u %s", uidRanges.toString().c_str(), subPriority, + iter->second.toString().c_str()); + return false; } - return false; + return true; } bool Network::isSecure() const { diff --git a/server/Network.h b/server/Network.h index d5110d02..aa1b21a1 100644 --- a/server/Network.h +++ b/server/Network.h @@ -24,6 +24,8 @@ namespace android::net { +typedef std::map<uint32_t, UidRanges> UidRangeMap; + // A Network represents a collection of interfaces participating as a single administrative unit. class Network { public: @@ -44,22 +46,31 @@ public: [[nodiscard]] int clearInterfaces(); std::string toString() const; - bool appliesToUser(uid_t uid) const; - [[nodiscard]] virtual int addUsers(const UidRanges&) { return -EINVAL; }; - [[nodiscard]] virtual int removeUsers(const UidRanges&) { return -EINVAL; }; + std::string uidRangesToString() const; + bool appliesToUser(uid_t uid, uint32_t* subPriority) const; + [[nodiscard]] virtual int addUsers(const UidRanges&, uint32_t /*subPriority*/) { + return -EINVAL; + }; + [[nodiscard]] virtual int removeUsers(const UidRanges&, uint32_t /*subPriority*/) { + return -EINVAL; + }; bool isSecure() const; virtual bool isPhysical() { return false; } virtual bool isUnreachable() { return false; } virtual bool isVirtual() { return false; } virtual bool canAddUsers() { return false; } + virtual bool isValidSubPriority(uint32_t /*priority*/) { return false; } + virtual void addToUidRangeMap(const UidRanges& uidRanges, uint32_t subPriority); + virtual void removeFromUidRangeMap(const UidRanges& uidRanges, uint32_t subPriority); protected: explicit Network(unsigned netId, bool mSecure = false); - bool hasInvalidUidRanges(const UidRanges& uidRanges) const; + bool canAddUidRanges(const UidRanges& uidRanges, uint32_t subPriority) const; const unsigned mNetId; std::set<std::string> mInterfaces; - UidRanges mUidRanges; + // Each subsidiary priority maps to a set of UID ranges of a feature. + std::map<uint32_t, UidRanges> mUidRangeMap; const bool mSecure; private: diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp index ff52db5b..602639cb 100644 --- a/server/NetworkController.cpp +++ b/server/NetworkController.cpp @@ -616,22 +616,24 @@ int isWrongNetworkForUidRanges(unsigned netId, Network* network) { } // namespace -int NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges) { +int NetworkController::addUsersToNetwork(unsigned netId, const UidRanges& uidRanges, + uint32_t subPriority) { ScopedWLock lock(mRWLock); Network* network = getNetworkLocked(netId); if (int ret = isWrongNetworkForUidRanges(netId, network)) { return ret; } - return network->addUsers(uidRanges); + return network->addUsers(uidRanges, subPriority); } -int NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges) { +int NetworkController::removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges, + uint32_t subPriority) { ScopedWLock lock(mRWLock); Network* network = getNetworkLocked(netId); if (int ret = isWrongNetworkForUidRanges(netId, network)) { return ret; } - return network->removeUsers(uidRanges); + return network->removeUsers(uidRanges, subPriority); } int NetworkController::addRoute(unsigned netId, const char* interface, const char* destination, @@ -740,6 +742,11 @@ void NetworkController::dump(DumpWriter& dw) { dw.println("Required permission: %s", permissionToName(permission)); dw.decIndent(); } + if (const auto& str = network->uidRangesToString(); !str.empty()) { + dw.incIndent(); + dw.println(str); + dw.decIndent(); + } dw.blankline(); } dw.decIndent(); @@ -776,30 +783,32 @@ Network* NetworkController::getNetworkLocked(unsigned netId) const { } VirtualNetwork* NetworkController::getVirtualNetworkForUserLocked(uid_t uid) const { + uint32_t subPriority; for (const auto& [_, network] : mNetworks) { - if (network->isVirtual() && network->appliesToUser(uid)) { + if (network->isVirtual() && network->appliesToUser(uid, &subPriority)) { return static_cast<VirtualNetwork*>(network); } } return nullptr; } +// Returns a network with the highest subsidiary priority among physical and unreachable networks +// that applies to uid. For a single subsidiary priority, an uid should belong to only one network. +// If the uid apply to different network with the same priority at the same time, the behavior is +// undefined. That is a configuration error. Network* NetworkController::getPhysicalOrUnreachableNetworkForUserLocked(uid_t uid) const { - // OEM-paid network take precedence over the unreachable network. - for (const auto& [_, network] : mNetworks) { - if (network->isPhysical() && network->appliesToUser(uid)) { - // Return the first physical network that matches UID. - // If there is more than one such network, the behaviour is undefined. - // This is a configuration error. - return network; + Network* bestNetwork = nullptr; + unsigned bestSubPriority = UidRanges::LOWEST_SUB_PRIORITY + 1; + for (const auto& [netId, network] : mNetworks) { + uint32_t subPriority; + if (!network->isPhysical() && !network->isUnreachable()) continue; + if (!network->appliesToUser(uid, &subPriority)) continue; + if (subPriority < bestSubPriority) { + bestNetwork = network; + bestSubPriority = subPriority; } } - - auto iter = mNetworks.find(UNREACHABLE_NET_ID); - if (iter != mNetworks.end() && iter->second->appliesToUser(uid)) { - return iter->second; - } - return nullptr; + return bestNetwork; } Permission NetworkController::getPermissionForUserLocked(uid_t uid) const { @@ -827,8 +836,9 @@ int NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) c return 0; } // If the UID wants to use a VPN, it can do so if and only if the VPN applies to the UID. + uint32_t subPriority; if (network->isVirtual()) { - return network->appliesToUser(uid) ? 0 : -EPERM; + return network->appliesToUser(uid, &subPriority) ? 0 : -EPERM; } // If a VPN applies to the UID, and the VPN is secure (i.e., not bypassable), then the UID can // only select a different network if it has the ability to protect its sockets. @@ -839,12 +849,12 @@ int NetworkController::checkUserNetworkAccessLocked(uid_t uid, unsigned netId) c } // If the UID wants to use a physical network and it has a UID range that includes the UID, the // UID has permission to use it regardless of whether the permission bits match. - if (network->isPhysical() && network->appliesToUser(uid)) { + if (network->isPhysical() && network->appliesToUser(uid, &subPriority)) { return 0; } // Only apps that are configured as "no default network" can use the unreachable network. if (network->isUnreachable()) { - return network->appliesToUser(uid) ? 0 : -EPERM; + return network->appliesToUser(uid, &subPriority) ? 0 : -EPERM; } // Check whether the UID's permission bits are sufficient to use the network. // Because the permission of the system default network is PERMISSION_NONE(0x0), apps can always diff --git a/server/NetworkController.h b/server/NetworkController.h index 46302252..a61ac39f 100644 --- a/server/NetworkController.h +++ b/server/NetworkController.h @@ -119,8 +119,10 @@ public: [[nodiscard]] int setPermissionForNetworks(Permission permission, const std::vector<unsigned>& netIds); - [[nodiscard]] int addUsersToNetwork(unsigned netId, const UidRanges& uidRanges); - [[nodiscard]] int removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges); + [[nodiscard]] int addUsersToNetwork(unsigned netId, const UidRanges& uidRanges, + uint32_t subPriority); + [[nodiscard]] int removeUsersFromNetwork(unsigned netId, const UidRanges& uidRanges, + uint32_t subPriority); // |nexthop| can be NULL (to indicate a directly-connected route), "unreachable" (to indicate a // route that's blocked), "throw" (to indicate the lack of a match), or a regular IP address. diff --git a/server/PhysicalNetwork.cpp b/server/PhysicalNetwork.cpp index 894d56ab..7b9a19a1 100644 --- a/server/PhysicalNetwork.cpp +++ b/server/PhysicalNetwork.cpp @@ -158,32 +158,35 @@ int PhysicalNetwork::removeAsDefault() { return 0; } -int PhysicalNetwork::addUsers(const UidRanges& uidRanges) { - if (hasInvalidUidRanges(uidRanges)) { +int PhysicalNetwork::addUsers(const UidRanges& uidRanges, uint32_t subPriority) { + if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges, subPriority)) { return -EINVAL; } for (const std::string& interface : mInterfaces) { - int ret = RouteController::addUsersToPhysicalNetwork(mNetId, interface.c_str(), uidRanges); + int ret = RouteController::addUsersToPhysicalNetwork(mNetId, interface.c_str(), + {{subPriority, uidRanges}}); if (ret) { ALOGE("failed to add users on interface %s of netId %u", interface.c_str(), mNetId); return ret; } } - mUidRanges.add(uidRanges); + addToUidRangeMap(uidRanges, subPriority); return 0; } -int PhysicalNetwork::removeUsers(const UidRanges& uidRanges) { +int PhysicalNetwork::removeUsers(const UidRanges& uidRanges, uint32_t subPriority) { + if (!isValidSubPriority(subPriority)) return -EINVAL; + for (const std::string& interface : mInterfaces) { int ret = RouteController::removeUsersFromPhysicalNetwork(mNetId, interface.c_str(), - uidRanges); + {{subPriority, uidRanges}}); if (ret) { ALOGE("failed to remove users on interface %s of netId %u", interface.c_str(), mNetId); return ret; } } - mUidRanges.remove(uidRanges); + removeFromUidRangeMap(uidRanges, subPriority); return 0; } @@ -192,7 +195,7 @@ int PhysicalNetwork::addInterface(const std::string& interface) { return 0; } if (int ret = RouteController::addInterfaceToPhysicalNetwork(mNetId, interface.c_str(), - mPermission, mUidRanges)) { + mPermission, mUidRangeMap)) { ALOGE("failed to add interface %s to netId %u", interface.c_str(), mNetId); return ret; } @@ -219,7 +222,7 @@ int PhysicalNetwork::removeInterface(const std::string& interface) { // to find the interface index in the cache in cases where the interface is already gone // (e.g. bt-pan). if (int ret = RouteController::removeInterfaceFromPhysicalNetwork(mNetId, interface.c_str(), - mPermission, mUidRanges)) { + mPermission, mUidRangeMap)) { ALOGE("failed to remove interface %s from netId %u", interface.c_str(), mNetId); return ret; } @@ -227,4 +230,9 @@ int PhysicalNetwork::removeInterface(const std::string& interface) { return 0; } +bool PhysicalNetwork::isValidSubPriority(uint32_t priority) { + return priority >= UidRanges::DEFAULT_SUB_PRIORITY && + priority <= UidRanges::LOWEST_SUB_PRIORITY; +} + } // namespace android::net diff --git a/server/PhysicalNetwork.h b/server/PhysicalNetwork.h index df2bd225..d9461b2e 100644 --- a/server/PhysicalNetwork.h +++ b/server/PhysicalNetwork.h @@ -42,8 +42,8 @@ class PhysicalNetwork : public Network { [[nodiscard]] int addAsDefault(); [[nodiscard]] int removeAsDefault(); - [[nodiscard]] int addUsers(const UidRanges& uidRanges) override; - [[nodiscard]] int removeUsers(const UidRanges& uidRanges) override; + [[nodiscard]] int addUsers(const UidRanges& uidRanges, uint32_t subPriority) override; + [[nodiscard]] int removeUsers(const UidRanges& uidRanges, uint32_t subPriority) override; bool isPhysical() override { return true; } bool canAddUsers() override { return true; } @@ -53,6 +53,7 @@ class PhysicalNetwork : public Network { [[nodiscard]] int removeInterface(const std::string& interface) override; int destroySocketsLackingPermission(Permission permission); void invalidateRouteCache(const std::string& interface); + bool isValidSubPriority(uint32_t priority) override; Delegate* const mDelegate; Permission mPermission; diff --git a/server/RouteController.cpp b/server/RouteController.cpp index 666a88a7..ba305e69 100644 --- a/server/RouteController.cpp +++ b/server/RouteController.cpp @@ -27,14 +27,11 @@ #include <map> -#define LOG_TAG "Netd" - #include "DummyNetwork.h" #include "Fwmark.h" #include "NetdConstants.h" #include "NetlinkCommands.h" #include "OffloadUtils.h" -#include "UidRanges.h" #include <android-base/file.h> #include <android-base/stringprintf.h> @@ -495,7 +492,7 @@ int modifyIncomingPacketMark(unsigned netId, const char* interface, Permission p // have, if they are subject to this VPN, their traffic has to go through it. Allows the traffic to // bypass the VPN if the protectedFromVpn bit is set. [[nodiscard]] static int modifyVpnUidRangeRule(uint32_t table, uid_t uidStart, uid_t uidEnd, - bool secure, bool add) { + uint32_t subPriority, bool secure, bool add) { Fwmark fwmark; Fwmark mask; @@ -513,8 +510,8 @@ int modifyIncomingPacketMark(unsigned netId, const char* interface, Permission p mask.explicitlySelected = true; } - return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, priority, table, fwmark.intValue, - mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, priority + subPriority, table, + fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); } // A rule to allow system apps to send traffic over this VPN even if they are not part of the target @@ -548,7 +545,7 @@ int modifyIncomingPacketMark(unsigned netId, const char* interface, Permission p // modifyNetworkPermission(). [[nodiscard]] static int modifyExplicitNetworkRule(unsigned netId, uint32_t table, Permission permission, uid_t uidStart, - uid_t uidEnd, bool add) { + uid_t uidEnd, uint32_t subPriority, bool add) { Fwmark fwmark; Fwmark mask; @@ -561,8 +558,9 @@ int modifyIncomingPacketMark(unsigned netId, const char* interface, Permission p fwmark.permission = permission; mask.permission = permission; - return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_EXPLICIT_NETWORK, table, - fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, + RULE_PRIORITY_EXPLICIT_NETWORK + subPriority, table, fwmark.intValue, + mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); } // A rule to route traffic based on a chosen outgoing interface. @@ -571,7 +569,7 @@ int modifyIncomingPacketMark(unsigned netId, const char* interface, Permission p // the outgoing interface (typically for link-local communications). [[nodiscard]] static int modifyOutputInterfaceRules(const char* interface, uint32_t table, Permission permission, uid_t uidStart, - uid_t uidEnd, bool add) { + uid_t uidEnd, uint32_t subPriority, bool add) { Fwmark fwmark; Fwmark mask; @@ -589,8 +587,9 @@ int modifyIncomingPacketMark(unsigned netId, const char* interface, Permission p } } - return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_OUTPUT_INTERFACE, table, - fwmark.intValue, mask.intValue, IIF_LOOPBACK, interface, uidStart, uidEnd); + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, + RULE_PRIORITY_OUTPUT_INTERFACE + subPriority, table, fwmark.intValue, + mask.intValue, IIF_LOOPBACK, interface, uidStart, uidEnd); } // A rule to route traffic based on the chosen network. @@ -670,7 +669,8 @@ int RouteController::modifyVpnFallthroughRule(uint16_t action, unsigned vpnNetId // Add rules to lookup the local network when specified explicitly or otherwise. [[nodiscard]] static int addLocalNetworkRules(unsigned localNetId) { if (int ret = modifyExplicitNetworkRule(localNetId, ROUTE_TABLE_LOCAL_NETWORK, PERMISSION_NONE, - INVALID_UID, INVALID_UID, ACTION_ADD)) { + INVALID_UID, INVALID_UID, + UidRanges::DEFAULT_SUB_PRIORITY, ACTION_ADD)) { return ret; } @@ -701,8 +701,9 @@ int RouteController::configureDummyNetwork() { return -errno; } - if ((ret = modifyOutputInterfaceRules(interface, table, PERMISSION_NONE, - INVALID_UID, INVALID_UID, ACTION_ADD))) { + if ((ret = modifyOutputInterfaceRules(interface, table, PERMISSION_NONE, INVALID_UID, + INVALID_UID, UidRanges::DEFAULT_SUB_PRIORITY, + ACTION_ADD))) { ALOGE("Can't create oif rules for %s: %s", interface, strerror(-ret)); return ret; } @@ -735,11 +736,13 @@ int RouteController::configureDummyNetwork() { } maybeModifyQdiscClsact(interface, add); return modifyOutputInterfaceRules(interface, ROUTE_TABLE_LOCAL_NETWORK, PERMISSION_NONE, - INVALID_UID, INVALID_UID, add); + INVALID_UID, INVALID_UID, UidRanges::DEFAULT_SUB_PRIORITY, + add); } [[nodiscard]] static int modifyUidNetworkRule(unsigned netId, uint32_t table, uid_t uidStart, - uid_t uidEnd, bool add, bool explicitSelect) { + uid_t uidEnd, uint32_t subPriority, bool add, + bool explicitSelect) { if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { ALOGE("modifyUidNetworkRule, invalid UIDs (%u, %u)", uidStart, uidEnd); return -EUSERS; @@ -759,14 +762,14 @@ int RouteController::configureDummyNetwork() { mask.permission = PERMISSION_NONE; return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, - explicitSelect ? RULE_PRIORITY_UID_EXPLICIT_NETWORK - : RULE_PRIORITY_UID_IMPLICIT_NETWORK, + explicitSelect ? (RULE_PRIORITY_UID_EXPLICIT_NETWORK + subPriority) + : (RULE_PRIORITY_UID_IMPLICIT_NETWORK + subPriority), 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) { + uint32_t subPriority, bool add) { if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { ALOGE("modifyUidDefaultNetworkRule, invalid UIDs (%u, %u)", uidStart, uidEnd); return -EUSERS; @@ -782,28 +785,34 @@ int RouteController::configureDummyNetwork() { 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); + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, + RULE_PRIORITY_UID_DEFAULT_NETWORK + subPriority, table, fwmark.intValue, + mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); } /* static */ int RouteController::modifyPhysicalNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges, Permission permission, + const UidRangeMap& uidRangeMap, 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 = modifyUidNetworkRule(netId, table, range.start, range.stop, add, EXPLICIT)) { - return ret; - } - if (int ret = modifyUidNetworkRule(netId, table, range.start, range.stop, add, IMPLICIT)) { - return ret; - } - if (int ret = modifyUidDefaultNetworkRule(table, range.start, range.stop, add)) { - return ret; + for (const auto& [subPriority, uidRanges] : uidRangeMap) { + for (const UidRangeParcel& range : uidRanges.getRanges()) { + if (int ret = modifyUidNetworkRule(netId, table, range.start, range.stop, subPriority, + add, EXPLICIT)) { + return ret; + } + if (int ret = modifyUidNetworkRule(netId, table, range.start, range.stop, subPriority, + add, IMPLICIT)) { + return ret; + } + if (int ret = modifyUidDefaultNetworkRule(table, range.start, range.stop, subPriority, + add)) { + return ret; + } } } @@ -816,11 +825,11 @@ int RouteController::modifyPhysicalNetwork(unsigned netId, const char* interface return ret; } if (int ret = modifyExplicitNetworkRule(netId, table, permission, INVALID_UID, INVALID_UID, - add)) { + UidRanges::DEFAULT_SUB_PRIORITY, add)) { return ret; } if (int ret = modifyOutputInterfaceRules(interface, table, permission, INVALID_UID, INVALID_UID, - add)) { + UidRanges::DEFAULT_SUB_PRIORITY, add)) { return ret; } @@ -851,7 +860,8 @@ int RouteController::modifyPhysicalNetwork(unsigned netId, const char* interface } [[nodiscard]] static int modifyUidUnreachableRule(unsigned netId, uid_t uidStart, uid_t uidEnd, - bool add, bool explicitSelect) { + uint32_t subPriority, bool add, + bool explicitSelect) { if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { ALOGE("modifyUidUnreachableRule, invalid UIDs (%u, %u)", uidStart, uidEnd); return -EUSERS; @@ -871,15 +881,16 @@ int RouteController::modifyPhysicalNetwork(unsigned netId, const char* interface mask.permission = PERMISSION_NONE; return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, - explicitSelect ? RULE_PRIORITY_UID_EXPLICIT_NETWORK - : RULE_PRIORITY_UID_IMPLICIT_NETWORK, + explicitSelect ? (RULE_PRIORITY_UID_EXPLICIT_NETWORK + subPriority) + : (RULE_PRIORITY_UID_IMPLICIT_NETWORK + subPriority), FR_ACT_UNREACHABLE, RT_TABLE_UNSPEC, fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); } -[[nodiscard]] static int modifyUidDefaultUnreachableRule(uid_t uidStart, uid_t uidEnd, bool add) { +[[nodiscard]] static int modifyUidDefaultUnreachableRule(uid_t uidStart, uid_t uidEnd, + uint32_t subPriority, bool add) { if ((uidStart == INVALID_UID) || (uidEnd == INVALID_UID)) { - ALOGE("modifyUidDefaultNetworkRule, invalid UIDs (%u, %u)", uidStart, uidEnd); + ALOGE("modifyUidDefaultUnreachableRule, invalid UIDs (%u, %u)", uidStart, uidEnd); return -EUSERS; } @@ -893,22 +904,28 @@ int RouteController::modifyPhysicalNetwork(unsigned netId, const char* interface fwmark.permission = PERMISSION_NONE; mask.permission = PERMISSION_NONE; - return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, RULE_PRIORITY_UID_DEFAULT_UNREACHABLE, - FR_ACT_UNREACHABLE, RT_TABLE_UNSPEC, fwmark.intValue, mask.intValue, - IIF_LOOPBACK, OIF_NONE, uidStart, uidEnd); + return modifyIpRule(add ? RTM_NEWRULE : RTM_DELRULE, + RULE_PRIORITY_UID_DEFAULT_UNREACHABLE + subPriority, FR_ACT_UNREACHABLE, + RT_TABLE_UNSPEC, fwmark.intValue, mask.intValue, IIF_LOOPBACK, OIF_NONE, + uidStart, uidEnd); } -int RouteController::modifyUnreachableNetwork(unsigned netId, const UidRanges& uidRanges, +int RouteController::modifyUnreachableNetwork(unsigned netId, const UidRangeMap& uidRangeMap, bool add) { - for (const UidRangeParcel& range : uidRanges.getRanges()) { - if (int ret = modifyUidUnreachableRule(netId, range.start, range.stop, add, EXPLICIT)) { - return ret; - } - if (int ret = modifyUidUnreachableRule(netId, range.start, range.stop, add, IMPLICIT)) { - return ret; - } - if (int ret = modifyUidDefaultUnreachableRule(range.start, range.stop, add)) { - return ret; + for (const auto& [subPriority, uidRanges] : uidRangeMap) { + for (const UidRangeParcel& range : uidRanges.getRanges()) { + if (int ret = modifyUidUnreachableRule(netId, range.start, range.stop, subPriority, add, + EXPLICIT)) { + return ret; + } + if (int ret = modifyUidUnreachableRule(netId, range.start, range.stop, subPriority, add, + IMPLICIT)) { + return ret; + } + if (int ret = modifyUidDefaultUnreachableRule(range.start, range.stop, subPriority, + add)) { + return ret; + } } } @@ -933,24 +950,27 @@ int RouteController::modifyUnreachableNetwork(unsigned netId, const UidRanges& u } int RouteController::modifyVirtualNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges, bool secure, bool add, + const UidRangeMap& uidRangeMap, bool secure, 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 = modifyVpnUidRangeRule(table, range.start, range.stop, secure, add)) { - return ret; - } - if (int ret = modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, range.start, - range.stop, add)) { - return ret; - } - if (int ret = modifyOutputInterfaceRules(interface, table, PERMISSION_NONE, range.start, - range.stop, add)) { - return ret; + for (const auto& [subPriority, uidRanges] : uidRangeMap) { + for (const UidRangeParcel& range : uidRanges.getRanges()) { + if (int ret = modifyVpnUidRangeRule(table, range.start, range.stop, subPriority, secure, + add)) { + return ret; + } + if (int ret = modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, range.start, + range.stop, subPriority, add)) { + return ret; + } + if (int ret = modifyOutputInterfaceRules(interface, table, PERMISSION_NONE, range.start, + range.stop, subPriority, add)) { + return ret; + } } } @@ -964,7 +984,8 @@ int RouteController::modifyVirtualNetwork(unsigned netId, const char* interface, if (int ret = modifyVpnSystemPermissionRule(netId, table, secure, add)) { return ret; } - return modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, UID_ROOT, UID_ROOT, add); + return modifyExplicitNetworkRule(netId, table, PERMISSION_NONE, UID_ROOT, UID_ROOT, + UidRanges::DEFAULT_SUB_PRIORITY, add); } return 0; @@ -1166,8 +1187,8 @@ int RouteController::removeInterfaceFromLocalNetwork(unsigned netId, const char* int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* interface, Permission permission, - const UidRanges& uidRanges) { - if (int ret = modifyPhysicalNetwork(netId, interface, uidRanges, permission, ACTION_ADD, + const UidRangeMap& uidRangeMap) { + if (int ret = modifyPhysicalNetwork(netId, interface, uidRangeMap, permission, ACTION_ADD, MODIFY_NON_UID_BASED_RULES)) { return ret; } @@ -1178,8 +1199,8 @@ int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* i int RouteController::removeInterfaceFromPhysicalNetwork(unsigned netId, const char* interface, Permission permission, - const UidRanges& uidRanges) { - if (int ret = modifyPhysicalNetwork(netId, interface, uidRanges, permission, ACTION_DEL, + const UidRangeMap& uidRangeMap) { + if (int ret = modifyPhysicalNetwork(netId, interface, uidRangeMap, permission, ACTION_DEL, MODIFY_NON_UID_BASED_RULES)) { return ret; } @@ -1195,8 +1216,8 @@ int RouteController::removeInterfaceFromPhysicalNetwork(unsigned netId, const ch } int RouteController::addInterfaceToVirtualNetwork(unsigned netId, const char* interface, - bool secure, const UidRanges& uidRanges) { - if (int ret = modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_ADD, + bool secure, const UidRangeMap& uidRangeMap) { + if (int ret = modifyVirtualNetwork(netId, interface, uidRangeMap, secure, ACTION_ADD, MODIFY_NON_UID_BASED_RULES)) { return ret; } @@ -1205,8 +1226,9 @@ int RouteController::addInterfaceToVirtualNetwork(unsigned netId, const char* in } int RouteController::removeInterfaceFromVirtualNetwork(unsigned netId, const char* interface, - bool secure, const UidRanges& uidRanges) { - if (int ret = modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_DEL, + bool secure, + const UidRangeMap& uidRangeMap) { + if (int ret = modifyVirtualNetwork(netId, interface, uidRangeMap, secure, ACTION_DEL, MODIFY_NON_UID_BASED_RULES)) { return ret; } @@ -1220,13 +1242,15 @@ int RouteController::removeInterfaceFromVirtualNetwork(unsigned netId, const cha int RouteController::modifyPhysicalNetworkPermission(unsigned netId, const char* interface, Permission oldPermission, Permission newPermission) { - UidRanges noUidRanges; + // Physical network rules either use permission bits or UIDs, but not both. + // So permission changes don't affect any UID-based rules. + UidRangeMap emptyUidRangeMap; // Add the new rules before deleting the old ones, to avoid race conditions. - if (int ret = modifyPhysicalNetwork(netId, interface, noUidRanges, newPermission, ACTION_ADD, - MODIFY_NON_UID_BASED_RULES)) { + if (int ret = modifyPhysicalNetwork(netId, interface, emptyUidRangeMap, newPermission, + ACTION_ADD, MODIFY_NON_UID_BASED_RULES)) { return ret; } - return modifyPhysicalNetwork(netId, interface, noUidRanges, oldPermission, ACTION_DEL, + return modifyPhysicalNetwork(netId, interface, emptyUidRangeMap, oldPermission, ACTION_DEL, MODIFY_NON_UID_BASED_RULES); } @@ -1239,14 +1263,14 @@ int RouteController::removeUsersFromRejectNonSecureNetworkRule(const UidRanges& } int RouteController::addUsersToVirtualNetwork(unsigned netId, const char* interface, bool secure, - const UidRanges& uidRanges) { - return modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_ADD, + const UidRangeMap& uidRangeMap) { + return modifyVirtualNetwork(netId, interface, uidRangeMap, secure, ACTION_ADD, !MODIFY_NON_UID_BASED_RULES); } int RouteController::removeUsersFromVirtualNetwork(unsigned netId, const char* interface, - bool secure, const UidRanges& uidRanges) { - return modifyVirtualNetwork(netId, interface, uidRanges, secure, ACTION_DEL, + bool secure, const UidRangeMap& uidRangeMap) { + return modifyVirtualNetwork(netId, interface, uidRangeMap, secure, ACTION_DEL, !MODIFY_NON_UID_BASED_RULES); } @@ -1297,23 +1321,24 @@ int RouteController::removeVirtualNetworkFallthrough(unsigned vpnNetId, } int RouteController::addUsersToPhysicalNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges) { - return modifyPhysicalNetwork(netId, interface, uidRanges, PERMISSION_NONE, ACTION_ADD, + const UidRangeMap& uidRangeMap) { + return modifyPhysicalNetwork(netId, interface, uidRangeMap, 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, + const UidRangeMap& uidRangeMap) { + return modifyPhysicalNetwork(netId, interface, uidRangeMap, PERMISSION_NONE, ACTION_DEL, !MODIFY_NON_UID_BASED_RULES); } -int RouteController::addUsersToUnreachableNetwork(unsigned netId, const UidRanges& uidRanges) { - return modifyUnreachableNetwork(netId, uidRanges, ACTION_ADD); +int RouteController::addUsersToUnreachableNetwork(unsigned netId, const UidRangeMap& uidRangeMap) { + return modifyUnreachableNetwork(netId, uidRangeMap, ACTION_ADD); } -int RouteController::removeUsersFromUnreachableNetwork(unsigned netId, const UidRanges& uidRanges) { - return modifyUnreachableNetwork(netId, uidRanges, ACTION_DEL); +int RouteController::removeUsersFromUnreachableNetwork(unsigned netId, + const UidRangeMap& uidRangeMap) { + return modifyUnreachableNetwork(netId, uidRangeMap, ACTION_DEL); } // Protects sInterfaceToTable. diff --git a/server/RouteController.h b/server/RouteController.h index 7f1f960f..38d2d621 100644 --- a/server/RouteController.h +++ b/server/RouteController.h @@ -17,6 +17,7 @@ #pragma once #include "NetdConstants.h" // IptablesTarget +#include "Network.h" // UidRangeMap #include "Permission.h" #include <android-base/thread_annotations.h> @@ -107,26 +108,28 @@ public: [[nodiscard]] static int addInterfaceToPhysicalNetwork(unsigned netId, const char* interface, Permission permission, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); [[nodiscard]] static int removeInterfaceFromPhysicalNetwork(unsigned netId, const char* interface, Permission permission, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); [[nodiscard]] static int addInterfaceToVirtualNetwork(unsigned netId, const char* interface, - bool secure, const UidRanges& uidRanges); + bool secure, + const UidRangeMap& uidRangeMap); [[nodiscard]] static int removeInterfaceFromVirtualNetwork(unsigned netId, const char* interface, bool secure, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); [[nodiscard]] static int modifyPhysicalNetworkPermission(unsigned netId, const char* interface, Permission oldPermission, Permission newPermission); [[nodiscard]] static int addUsersToVirtualNetwork(unsigned netId, const char* interface, - bool secure, const UidRanges& uidRanges); + bool secure, const UidRangeMap& uidRangeMap); [[nodiscard]] static int removeUsersFromVirtualNetwork(unsigned netId, const char* interface, - bool secure, const UidRanges& uidRanges); + bool secure, + const UidRangeMap& uidRangeMap); [[nodiscard]] static int addUsersToRejectNonSecureNetworkRule(const UidRanges& uidRanges); [[nodiscard]] static int removeUsersFromRejectNonSecureNetworkRule(const UidRanges& uidRanges); @@ -158,16 +161,16 @@ public: Permission permission); [[nodiscard]] static int addUsersToPhysicalNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); [[nodiscard]] static int removeUsersFromPhysicalNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); [[nodiscard]] static int addUsersToUnreachableNetwork(unsigned netId, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); [[nodiscard]] static int removeUsersFromUnreachableNetwork(unsigned netId, - const UidRanges& uidRanges); + const UidRangeMap& uidRangeMap); // For testing. static int (*iptablesRestoreCommandFunction)(IptablesTarget, const std::string&, @@ -187,9 +190,9 @@ private: static uint32_t getRouteTableForInterface(const char *interface) EXCLUDES(sInterfaceToTableLock); static int modifyDefaultNetwork(uint16_t action, const char* interface, Permission permission); static int modifyPhysicalNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges, Permission permission, bool add, - bool modifyNonUidBasedRules); - static int modifyUnreachableNetwork(unsigned netId, const UidRanges& uidRanges, bool add); + const UidRangeMap& uidRangeMap, Permission permission, + bool add, bool modifyNonUidBasedRules); + static int modifyUnreachableNetwork(unsigned netId, const UidRangeMap& uidRangeMap, bool add); static int modifyRoute(uint16_t action, uint16_t flags, const char* interface, const char* destination, const char* nexthop, TableType tableType, int mtu); @@ -198,7 +201,7 @@ private: static int modifyVpnFallthroughRule(uint16_t action, unsigned vpnNetId, const char* physicalInterface, Permission permission); static int modifyVirtualNetwork(unsigned netId, const char* interface, - const UidRanges& uidRanges, bool secure, bool add, + const UidRangeMap& uidRangeMap, bool secure, bool add, bool modifyNonUidBasedRules); static void updateTableNamesFile() EXCLUDES(sInterfaceToTableLock); }; diff --git a/server/UidRanges.cpp b/server/UidRanges.cpp index 5b4f59ff..093a1e27 100644 --- a/server/UidRanges.cpp +++ b/server/UidRanges.cpp @@ -155,7 +155,7 @@ bool UidRanges::overlaps(const UidRanges& other) const { } std::string UidRanges::toString() const { - std::string s("UidRanges{ "); + std::string s("uids{ "); for (const auto &range : mRanges) { if (length(range) == 0) { StringAppendF(&s, "<BAD: %u-%u> ", range.start, range.stop); diff --git a/server/UidRanges.h b/server/UidRanges.h index f3223905..99e7a99d 100644 --- a/server/UidRanges.h +++ b/server/UidRanges.h @@ -28,6 +28,9 @@ namespace net { class UidRanges { public: + static constexpr int DEFAULT_SUB_PRIORITY = 0; + static constexpr int LOWEST_SUB_PRIORITY = 999; + UidRanges() {} UidRanges(const std::vector<android::net::UidRangeParcel>& ranges); @@ -44,6 +47,7 @@ public: bool overlapsSelf() const; // check if this object has uid overlap with the input object. bool overlaps(const UidRanges& other) const; + bool empty() const { return mRanges.empty(); } private: // a utility to check if two UidRangeParcels have uid overlap. diff --git a/server/UnreachableNetwork.cpp b/server/UnreachableNetwork.cpp index b17c9981..2f801f0c 100644 --- a/server/UnreachableNetwork.cpp +++ b/server/UnreachableNetwork.cpp @@ -26,29 +26,37 @@ namespace net { // The unreachable network is used to reject traffic. It is used for system purposes only. UnreachableNetwork::UnreachableNetwork(unsigned netId) : Network(netId) {} -int UnreachableNetwork::addUsers(const UidRanges& uidRanges) { - if (hasInvalidUidRanges(uidRanges)) { +int UnreachableNetwork::addUsers(const UidRanges& uidRanges, uint32_t subPriority) { + if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges, subPriority)) { return -EINVAL; } - int ret = RouteController::addUsersToUnreachableNetwork(mNetId, uidRanges); + int ret = RouteController::addUsersToUnreachableNetwork(mNetId, {{subPriority, uidRanges}}); if (ret) { ALOGE("failed to add users to unreachable network"); return ret; } - mUidRanges.add(uidRanges); + addToUidRangeMap(uidRanges, subPriority); return 0; } -int UnreachableNetwork::removeUsers(const UidRanges& uidRanges) { - int ret = RouteController::removeUsersFromUnreachableNetwork(mNetId, uidRanges); +int UnreachableNetwork::removeUsers(const UidRanges& uidRanges, uint32_t subPriority) { + if (!isValidSubPriority(subPriority)) return -EINVAL; + + int ret = + RouteController::removeUsersFromUnreachableNetwork(mNetId, {{subPriority, uidRanges}}); if (ret) { ALOGE("failed to remove users from unreachable network"); return ret; } - mUidRanges.remove(uidRanges); + removeFromUidRangeMap(uidRanges, subPriority); return 0; } +bool UnreachableNetwork::isValidSubPriority(uint32_t priority) { + return priority >= UidRanges::DEFAULT_SUB_PRIORITY && + priority <= UidRanges::LOWEST_SUB_PRIORITY; +} + } // namespace net } // namespace android diff --git a/server/UnreachableNetwork.h b/server/UnreachableNetwork.h index a80f3f39..f1547d60 100644 --- a/server/UnreachableNetwork.h +++ b/server/UnreachableNetwork.h @@ -23,13 +23,14 @@ namespace android::net { class UnreachableNetwork : public Network { public: explicit UnreachableNetwork(unsigned netId); - [[nodiscard]] int addUsers(const UidRanges& uidRanges) override; - [[nodiscard]] int removeUsers(const UidRanges& uidRanges) override; + [[nodiscard]] int addUsers(const UidRanges& uidRanges, uint32_t subPriority) override; + [[nodiscard]] int removeUsers(const UidRanges& uidRanges, uint32_t subPriority) override; bool isUnreachable() override { return true; } bool canAddUsers() override { return true; } private: std::string getTypeString() const override { return "UNREACHABLE"; }; + bool isValidSubPriority(uint32_t priority) override; }; } // namespace android::net
\ No newline at end of file diff --git a/server/VirtualNetwork.cpp b/server/VirtualNetwork.cpp index 93f4c3e8..1906e208 100644 --- a/server/VirtualNetwork.cpp +++ b/server/VirtualNetwork.cpp @@ -31,33 +31,35 @@ VirtualNetwork::VirtualNetwork(unsigned netId, bool secure) : Network(netId, sec VirtualNetwork::~VirtualNetwork() {} -int VirtualNetwork::addUsers(const UidRanges& uidRanges) { - if (hasInvalidUidRanges(uidRanges)) { +int VirtualNetwork::addUsers(const UidRanges& uidRanges, uint32_t subPriority) { + if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges, subPriority)) { return -EINVAL; } for (const std::string& interface : mInterfaces) { int ret = RouteController::addUsersToVirtualNetwork(mNetId, interface.c_str(), mSecure, - uidRanges); + {{subPriority, uidRanges}}); if (ret) { ALOGE("failed to add users on interface %s of netId %u", interface.c_str(), mNetId); return ret; } } - mUidRanges.add(uidRanges); + addToUidRangeMap(uidRanges, subPriority); return 0; } -int VirtualNetwork::removeUsers(const UidRanges& uidRanges) { +int VirtualNetwork::removeUsers(const UidRanges& uidRanges, uint32_t subPriority) { + if (!isValidSubPriority(subPriority)) return -EINVAL; + for (const std::string& interface : mInterfaces) { int ret = RouteController::removeUsersFromVirtualNetwork(mNetId, interface.c_str(), mSecure, - uidRanges); + {{subPriority, uidRanges}}); if (ret) { ALOGE("failed to remove users on interface %s of netId %u", interface.c_str(), mNetId); return ret; } } - mUidRanges.remove(uidRanges); + removeFromUidRangeMap(uidRanges, subPriority); return 0; } @@ -66,7 +68,7 @@ int VirtualNetwork::addInterface(const std::string& interface) { return 0; } if (int ret = RouteController::addInterfaceToVirtualNetwork(mNetId, interface.c_str(), mSecure, - mUidRanges)) { + mUidRangeMap)) { ALOGE("failed to add interface %s to VPN netId %u", interface.c_str(), mNetId); return ret; } @@ -79,7 +81,7 @@ int VirtualNetwork::removeInterface(const std::string& interface) { return 0; } if (int ret = RouteController::removeInterfaceFromVirtualNetwork(mNetId, interface.c_str(), - mSecure, mUidRanges)) { + mSecure, mUidRangeMap)) { ALOGE("failed to remove interface %s from VPN netId %u", interface.c_str(), mNetId); return ret; } @@ -87,5 +89,10 @@ int VirtualNetwork::removeInterface(const std::string& interface) { return 0; } +bool VirtualNetwork::isValidSubPriority(uint32_t priority) { + // Only supports default subsidiary permissions. + return priority == UidRanges::DEFAULT_SUB_PRIORITY; +} + } // namespace net } // namespace android diff --git a/server/VirtualNetwork.h b/server/VirtualNetwork.h index ebda7da5..20c9e2c2 100644 --- a/server/VirtualNetwork.h +++ b/server/VirtualNetwork.h @@ -33,8 +33,8 @@ class VirtualNetwork : public Network { public: VirtualNetwork(unsigned netId, bool secure); virtual ~VirtualNetwork(); - [[nodiscard]] int addUsers(const UidRanges& uidRanges) override; - [[nodiscard]] int removeUsers(const UidRanges& uidRanges) override; + [[nodiscard]] int addUsers(const UidRanges& uidRanges, uint32_t subPriority) override; + [[nodiscard]] int removeUsers(const UidRanges& uidRanges, uint32_t subPriority) override; bool isVirtual() override { return true; } bool canAddUsers() override { return true; } @@ -42,6 +42,7 @@ public: std::string getTypeString() const override { return "VIRTUAL"; }; [[nodiscard]] int addInterface(const std::string& interface) override; [[nodiscard]] int removeInterface(const std::string& interface) override; + bool isValidSubPriority(uint32_t priority) override; }; } // namespace android::net diff --git a/server/aidl_api/netd_aidl_interface/7/.hash b/server/aidl_api/netd_aidl_interface/7/.hash new file mode 100644 index 00000000..cad59dfd --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/.hash @@ -0,0 +1 @@ +850353de5d19a0dd718f8fd20791f0532e6a34c7 diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/INetd.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/INetd.aidl new file mode 100644 index 00000000..ec03d86b --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/INetd.aidl @@ -0,0 +1,200 @@ +/** + * Copyright (c) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +interface INetd { + boolean isAlive(); + boolean firewallReplaceUidChain(in @utf8InCpp String chainName, boolean isAllowlist, in int[] uids); + boolean bandwidthEnableDataSaver(boolean enable); + /** + * @deprecated use networkCreate() instead. + */ + void networkCreatePhysical(int netId, int permission); + /** + * @deprecated use networkCreate() instead. + */ + void networkCreateVpn(int netId, boolean secure); + void networkDestroy(int netId); + void networkAddInterface(int netId, in @utf8InCpp String iface); + void networkRemoveInterface(int netId, in @utf8InCpp String iface); + void networkAddUidRanges(int netId, in android.net.UidRangeParcel[] uidRanges); + void networkRemoveUidRanges(int netId, in android.net.UidRangeParcel[] uidRanges); + void networkRejectNonSecureVpn(boolean add, in android.net.UidRangeParcel[] uidRanges); + void socketDestroy(in android.net.UidRangeParcel[] uidRanges, in int[] exemptUids); + boolean tetherApplyDnsInterfaces(); + android.net.TetherStatsParcel[] tetherGetStats(); + void interfaceAddAddress(in @utf8InCpp String ifName, in @utf8InCpp String addrString, int prefixLength); + void interfaceDelAddress(in @utf8InCpp String ifName, in @utf8InCpp String addrString, int prefixLength); + @utf8InCpp String getProcSysNet(int ipversion, int which, in @utf8InCpp String ifname, in @utf8InCpp String parameter); + void setProcSysNet(int ipversion, int which, in @utf8InCpp String ifname, in @utf8InCpp String parameter, in @utf8InCpp String value); + void ipSecSetEncapSocketOwner(in ParcelFileDescriptor socket, int newUid); + int ipSecAllocateSpi(int transformId, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int spi); + void ipSecAddSecurityAssociation(int transformId, int mode, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int underlyingNetId, int spi, int markValue, int markMask, in @utf8InCpp String authAlgo, in byte[] authKey, in int authTruncBits, in @utf8InCpp String cryptAlgo, in byte[] cryptKey, in int cryptTruncBits, in @utf8InCpp String aeadAlgo, in byte[] aeadKey, in int aeadIcvBits, int encapType, int encapLocalPort, int encapRemotePort, int interfaceId); + void ipSecDeleteSecurityAssociation(int transformId, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int spi, int markValue, int markMask, int interfaceId); + void ipSecApplyTransportModeTransform(in ParcelFileDescriptor socket, int transformId, int direction, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int spi); + void ipSecRemoveTransportModeTransform(in ParcelFileDescriptor socket); + void ipSecAddSecurityPolicy(int transformId, int selAddrFamily, int direction, in @utf8InCpp String tmplSrcAddress, in @utf8InCpp String tmplDstAddress, int spi, int markValue, int markMask, int interfaceId); + void ipSecUpdateSecurityPolicy(int transformId, int selAddrFamily, int direction, in @utf8InCpp String tmplSrcAddress, in @utf8InCpp String tmplDstAddress, int spi, int markValue, int markMask, int interfaceId); + void ipSecDeleteSecurityPolicy(int transformId, int selAddrFamily, int direction, int markValue, int markMask, int interfaceId); + void ipSecAddTunnelInterface(in @utf8InCpp String deviceName, in @utf8InCpp String localAddress, in @utf8InCpp String remoteAddress, int iKey, int oKey, int interfaceId); + void ipSecUpdateTunnelInterface(in @utf8InCpp String deviceName, in @utf8InCpp String localAddress, in @utf8InCpp String remoteAddress, int iKey, int oKey, int interfaceId); + void ipSecRemoveTunnelInterface(in @utf8InCpp String deviceName); + void wakeupAddInterface(in @utf8InCpp String ifName, in @utf8InCpp String prefix, int mark, int mask); + void wakeupDelInterface(in @utf8InCpp String ifName, in @utf8InCpp String prefix, int mark, int mask); + void setIPv6AddrGenMode(in @utf8InCpp String ifName, int mode); + void idletimerAddInterface(in @utf8InCpp String ifName, int timeout, in @utf8InCpp String classLabel); + void idletimerRemoveInterface(in @utf8InCpp String ifName, int timeout, in @utf8InCpp String classLabel); + void strictUidCleartextPenalty(int uid, int policyPenalty); + @utf8InCpp String clatdStart(in @utf8InCpp String ifName, in @utf8InCpp String nat64Prefix); + void clatdStop(in @utf8InCpp String ifName); + boolean ipfwdEnabled(); + @utf8InCpp String[] ipfwdGetRequesterList(); + void ipfwdEnableForwarding(in @utf8InCpp String requester); + void ipfwdDisableForwarding(in @utf8InCpp String requester); + void ipfwdAddInterfaceForward(in @utf8InCpp String fromIface, in @utf8InCpp String toIface); + void ipfwdRemoveInterfaceForward(in @utf8InCpp String fromIface, in @utf8InCpp String toIface); + void bandwidthSetInterfaceQuota(in @utf8InCpp String ifName, long bytes); + void bandwidthRemoveInterfaceQuota(in @utf8InCpp String ifName); + void bandwidthSetInterfaceAlert(in @utf8InCpp String ifName, long bytes); + void bandwidthRemoveInterfaceAlert(in @utf8InCpp String ifName); + void bandwidthSetGlobalAlert(long bytes); + void bandwidthAddNaughtyApp(int uid); + void bandwidthRemoveNaughtyApp(int uid); + void bandwidthAddNiceApp(int uid); + void bandwidthRemoveNiceApp(int uid); + void tetherStart(in @utf8InCpp String[] dhcpRanges); + void tetherStop(); + boolean tetherIsEnabled(); + void tetherInterfaceAdd(in @utf8InCpp String ifName); + void tetherInterfaceRemove(in @utf8InCpp String ifName); + @utf8InCpp String[] tetherInterfaceList(); + void tetherDnsSet(int netId, in @utf8InCpp String[] dnsAddrs); + @utf8InCpp String[] tetherDnsList(); + void networkAddRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop); + void networkRemoveRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop); + void networkAddLegacyRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop, int uid); + void networkRemoveLegacyRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop, int uid); + int networkGetDefault(); + void networkSetDefault(int netId); + void networkClearDefault(); + void networkSetPermissionForNetwork(int netId, int permission); + void networkSetPermissionForUser(int permission, in int[] uids); + void networkClearPermissionForUser(in int[] uids); + void trafficSetNetPermForUids(int permission, in int[] uids); + void networkSetProtectAllow(int uid); + void networkSetProtectDeny(int uid); + boolean networkCanProtect(int uid); + void firewallSetFirewallType(int firewalltype); + void firewallSetInterfaceRule(in @utf8InCpp String ifName, int firewallRule); + void firewallSetUidRule(int childChain, int uid, int firewallRule); + void firewallEnableChildChain(int childChain, boolean enable); + @utf8InCpp String[] interfaceGetList(); + android.net.InterfaceConfigurationParcel interfaceGetCfg(in @utf8InCpp String ifName); + void interfaceSetCfg(in android.net.InterfaceConfigurationParcel cfg); + void interfaceSetIPv6PrivacyExtensions(in @utf8InCpp String ifName, boolean enable); + void interfaceClearAddrs(in @utf8InCpp String ifName); + void interfaceSetEnableIPv6(in @utf8InCpp String ifName, boolean enable); + void interfaceSetMtu(in @utf8InCpp String ifName, int mtu); + void tetherAddForward(in @utf8InCpp String intIface, in @utf8InCpp String extIface); + void tetherRemoveForward(in @utf8InCpp String intIface, in @utf8InCpp String extIface); + void setTcpRWmemorySize(in @utf8InCpp String rmemValues, in @utf8InCpp String wmemValues); + void registerUnsolicitedEventListener(android.net.INetdUnsolicitedEventListener listener); + void firewallAddUidInterfaceRules(in @utf8InCpp String ifName, in int[] uids); + void firewallRemoveUidInterfaceRules(in int[] uids); + void trafficSwapActiveStatsMap(); + IBinder getOemNetd(); + void tetherStartWithConfiguration(in android.net.TetherConfigParcel config); + android.net.MarkMaskParcel getFwmarkForNetwork(int netId); + void networkAddRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo); + void networkUpdateRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo); + void networkRemoveRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo); + void tetherOffloadRuleAdd(in android.net.TetherOffloadRuleParcel rule); + void tetherOffloadRuleRemove(in android.net.TetherOffloadRuleParcel rule); + android.net.TetherStatsParcel[] tetherOffloadGetStats(); + void tetherOffloadSetInterfaceQuota(int ifIndex, long quotaBytes); + android.net.TetherStatsParcel tetherOffloadGetAndClearStats(int ifIndex); + void networkCreate(in android.net.NativeNetworkConfig config); + void networkAddUidRangesParcel(in android.net.netd.aidl.NativeUidRangeConfig uidRangesConfig); + void networkRemoveUidRangesParcel(in android.net.netd.aidl.NativeUidRangeConfig uidRangesConfig); + const int IPV4 = 4; + const int IPV6 = 6; + const int CONF = 1; + const int NEIGH = 2; + const String IPSEC_INTERFACE_PREFIX = "ipsec"; + const int IPV6_ADDR_GEN_MODE_EUI64 = 0; + const int IPV6_ADDR_GEN_MODE_NONE = 1; + const int IPV6_ADDR_GEN_MODE_STABLE_PRIVACY = 2; + const int IPV6_ADDR_GEN_MODE_RANDOM = 3; + const int IPV6_ADDR_GEN_MODE_DEFAULT = 0; + const int PENALTY_POLICY_ACCEPT = 1; + const int PENALTY_POLICY_LOG = 2; + const int PENALTY_POLICY_REJECT = 3; + const int LOCAL_NET_ID = 99; + const int DUMMY_NET_ID = 51; + const int UNREACHABLE_NET_ID = 52; + const String NEXTHOP_NONE = ""; + const String NEXTHOP_UNREACHABLE = "unreachable"; + const String NEXTHOP_THROW = "throw"; + const int PERMISSION_NONE = 0; + const int PERMISSION_NETWORK = 1; + const int PERMISSION_SYSTEM = 2; + const int NO_PERMISSIONS = 0; + const int PERMISSION_INTERNET = 4; + const int PERMISSION_UPDATE_DEVICE_STATS = 8; + const int PERMISSION_UNINSTALLED = -1; + /** + * @deprecated use FIREWALL_ALLOWLIST. + */ + const int FIREWALL_WHITELIST = 0; + const int FIREWALL_ALLOWLIST = 0; + /** + * @deprecated use FIREWALL_DENYLIST. + */ + const int FIREWALL_BLACKLIST = 1; + const int FIREWALL_DENYLIST = 1; + const int FIREWALL_RULE_ALLOW = 1; + const int FIREWALL_RULE_DENY = 2; + const int FIREWALL_CHAIN_NONE = 0; + const int FIREWALL_CHAIN_DOZABLE = 1; + const int FIREWALL_CHAIN_STANDBY = 2; + const int FIREWALL_CHAIN_POWERSAVE = 3; + const int FIREWALL_CHAIN_RESTRICTED = 4; + const String IF_STATE_UP = "up"; + const String IF_STATE_DOWN = "down"; + const String IF_FLAG_BROADCAST = "broadcast"; + const String IF_FLAG_LOOPBACK = "loopback"; + const String IF_FLAG_POINTOPOINT = "point-to-point"; + const String IF_FLAG_RUNNING = "running"; + const String IF_FLAG_MULTICAST = "multicast"; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/INetdUnsolicitedEventListener.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/INetdUnsolicitedEventListener.aidl new file mode 100644 index 00000000..31775dfd --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/INetdUnsolicitedEventListener.aidl @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +interface INetdUnsolicitedEventListener { + oneway void onInterfaceClassActivityChanged(boolean isActive, int timerLabel, long timestampNs, int uid); + oneway void onQuotaLimitReached(@utf8InCpp String alertName, @utf8InCpp String ifName); + oneway void onInterfaceDnsServerInfo(@utf8InCpp String ifName, long lifetimeS, in @utf8InCpp String[] servers); + oneway void onInterfaceAddressUpdated(@utf8InCpp String addr, @utf8InCpp String ifName, int flags, int scope); + oneway void onInterfaceAddressRemoved(@utf8InCpp String addr, @utf8InCpp String ifName, int flags, int scope); + oneway void onInterfaceAdded(@utf8InCpp String ifName); + oneway void onInterfaceRemoved(@utf8InCpp String ifName); + oneway void onInterfaceChanged(@utf8InCpp String ifName, boolean up); + oneway void onInterfaceLinkStateChanged(@utf8InCpp String ifName, boolean up); + oneway void onRouteChanged(boolean updated, @utf8InCpp String route, @utf8InCpp String gateway, @utf8InCpp String ifName); + oneway void onStrictCleartextDetected(int uid, @utf8InCpp String hex); +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/InterfaceConfigurationParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/InterfaceConfigurationParcel.aidl new file mode 100644 index 00000000..1869d8d4 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/InterfaceConfigurationParcel.aidl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +parcelable InterfaceConfigurationParcel { + @utf8InCpp String ifName; + @utf8InCpp String hwAddr; + @utf8InCpp String ipv4Addr; + int prefixLength; + @utf8InCpp String[] flags; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/MarkMaskParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/MarkMaskParcel.aidl new file mode 100644 index 00000000..8ea20d11 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/MarkMaskParcel.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +parcelable MarkMaskParcel { + int mark; + int mask; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/NativeNetworkConfig.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/NativeNetworkConfig.aidl new file mode 100644 index 00000000..76562b29 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/NativeNetworkConfig.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable +parcelable NativeNetworkConfig { + int netId; + android.net.NativeNetworkType networkType = android.net.NativeNetworkType.PHYSICAL; + int permission; + boolean secure; + android.net.NativeVpnType vpnType = android.net.NativeVpnType.PLATFORM; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/NativeNetworkType.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/NativeNetworkType.aidl new file mode 100644 index 00000000..06c8979d --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/NativeNetworkType.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@Backing(type="int") +enum NativeNetworkType { + PHYSICAL = 0, + VIRTUAL = 1, +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/NativeVpnType.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/NativeVpnType.aidl new file mode 100644 index 00000000..8a8be839 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/NativeVpnType.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +@Backing(type="int") +enum NativeVpnType { + SERVICE = 1, + PLATFORM = 2, + LEGACY = 3, + OEM = 4, +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/RouteInfoParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/RouteInfoParcel.aidl new file mode 100644 index 00000000..5ef95e67 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/RouteInfoParcel.aidl @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +parcelable RouteInfoParcel { + @utf8InCpp String destination; + @utf8InCpp String ifName; + @utf8InCpp String nextHop; + int mtu; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/TetherConfigParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/TetherConfigParcel.aidl new file mode 100644 index 00000000..7b39c22e --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/TetherConfigParcel.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +parcelable TetherConfigParcel { + boolean usingLegacyDnsProxy; + @utf8InCpp String[] dhcpRanges; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/TetherOffloadRuleParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/TetherOffloadRuleParcel.aidl new file mode 100644 index 00000000..983e9860 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/TetherOffloadRuleParcel.aidl @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +parcelable TetherOffloadRuleParcel { + int inputInterfaceIndex; + int outputInterfaceIndex; + byte[] destination; + int prefixLength; + byte[] srcL2Address; + byte[] dstL2Address; + int pmtu = 1500; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/TetherStatsParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/TetherStatsParcel.aidl new file mode 100644 index 00000000..5f1b7226 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/TetherStatsParcel.aidl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +parcelable TetherStatsParcel { + @utf8InCpp String iface; + long rxBytes; + long rxPackets; + long txBytes; + long txPackets; + int ifIndex = 0; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/UidRangeParcel.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/UidRangeParcel.aidl new file mode 100644 index 00000000..72e987a2 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/UidRangeParcel.aidl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net; +/* @hide */ +@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable +parcelable UidRangeParcel { + int start; + int stop; +} diff --git a/server/aidl_api/netd_aidl_interface/7/android/net/netd/aidl/NativeUidRangeConfig.aidl b/server/aidl_api/netd_aidl_interface/7/android/net/netd/aidl/NativeUidRangeConfig.aidl new file mode 100644 index 00000000..9bb679f1 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/7/android/net/netd/aidl/NativeUidRangeConfig.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.netd.aidl; +/* @hide */ +@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable +parcelable NativeUidRangeConfig { + int netId; + android.net.UidRangeParcel[] uidRanges; + int subPriority; +} diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl index a7952f28..ec03d86b 100644 --- a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl +++ b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl @@ -145,6 +145,8 @@ interface INetd { void tetherOffloadSetInterfaceQuota(int ifIndex, long quotaBytes); android.net.TetherStatsParcel tetherOffloadGetAndClearStats(int ifIndex); void networkCreate(in android.net.NativeNetworkConfig config); + void networkAddUidRangesParcel(in android.net.netd.aidl.NativeUidRangeConfig uidRangesConfig); + void networkRemoveUidRangesParcel(in android.net.netd.aidl.NativeUidRangeConfig uidRangesConfig); const int IPV4 = 4; const int IPV6 = 6; const int CONF = 1; diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/netd/aidl/NativeUidRangeConfig.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/netd/aidl/NativeUidRangeConfig.aidl new file mode 100644 index 00000000..9bb679f1 --- /dev/null +++ b/server/aidl_api/netd_aidl_interface/current/android/net/netd/aidl/NativeUidRangeConfig.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m <name>-update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.net.netd.aidl; +/* @hide */ +@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable +parcelable NativeUidRangeConfig { + int netId; + android.net.UidRangeParcel[] uidRanges; + int subPriority; +} diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl index 8a028314..d6398c12 100644 --- a/server/binder/android/net/INetd.aidl +++ b/server/binder/android/net/INetd.aidl @@ -25,6 +25,7 @@ import android.net.TetherConfigParcel; import android.net.TetherOffloadRuleParcel; import android.net.TetherStatsParcel; import android.net.UidRangeParcel; +import android.net.netd.aidl.NativeUidRangeConfig; /** {@hide} */ interface INetd { @@ -1349,4 +1350,31 @@ interface INetd { * unix errno. */ void networkCreate(in NativeNetworkConfig config); + + /** + * Adds the specified UID ranges to the specified network. The network can be physical or + * virtual. Traffic from the UID ranges will be routed to the network by default. The possible + * value of subsidiary priority for physical and unreachable networks is 0-999. 0 is the highest + * priority. 0 is also the default value. Virtual network supports only the default value. + * + * @param NativeUidRangeConfig a parcel contains netId, UID ranges, subsidiary priority, etc. + * + * @throws ServiceSpecificException in case of failure, with an error code corresponding to the + * unix errno. + */ + void networkAddUidRangesParcel(in NativeUidRangeConfig uidRangesConfig); + + /** + * Removes the specified UID ranges from the specified network. The network can be physical or + * virtual. Traffic from the UID ranges will no longer be routed to the network by default. The + * possible value of subsidiary priority for physical and unreachable networks is 0-999. 0 is + * the highest priority. 0 is also the default value. Virtual network supports only the default + * value. + * + * @param NativeUidRangeConfig a parcel contains netId, UID ranges, subsidiary priority, etc. + * + * @throws ServiceSpecificException in case of failure, with an error code corresponding to the + * unix errno. + */ + void networkRemoveUidRangesParcel(in NativeUidRangeConfig uidRangesConfig); } diff --git a/server/binder/android/net/netd/aidl/NativeUidRangeConfig.aidl b/server/binder/android/net/netd/aidl/NativeUidRangeConfig.aidl new file mode 100644 index 00000000..99497a86 --- /dev/null +++ b/server/binder/android/net/netd/aidl/NativeUidRangeConfig.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netd.aidl; + +import android.net.UidRangeParcel; + +/** + * The configuration to add or remove UID ranges. + * + * {@hide} + */ +@JavaDerive(toString=true, equals=true) +@JavaOnlyImmutable +parcelable NativeUidRangeConfig { + /** The network ID of the network to add/remove the ranges to/from. */ + int netId; + + /** A set of non-overlapping ranges of UIDs. */ + UidRangeParcel[] uidRanges; + + /** + * The priority of this UID range config. 0 is the highest priority; 999 is the lowest priority. + * The function of this parameter is to adjust the priority when the same UID is set to + * different networks for different features. + */ + int subPriority; +}
\ No newline at end of file diff --git a/tests/Android.bp b/tests/Android.bp index 6ae752b8..c5d9bb53 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -52,7 +52,7 @@ cc_test_library { "libnetutils", "libsysutils", "libutils", - "netd_aidl_interface-V6-cpp", + "netd_aidl_interface-V7-cpp", ], } @@ -107,7 +107,7 @@ cc_test { "libnetdbpf", "libnetdutils", "libqtaguid", - "netd_aidl_interface-V6-cpp", + "netd_aidl_interface-V7-cpp", "netd_event_listener_interface-V1-cpp", "oemnetd_aidl_interface-cpp", ], diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp index 69d1f9b5..22d1f226 100644 --- a/tests/binder_test.cpp +++ b/tests/binder_test.cpp @@ -43,7 +43,6 @@ #include <openssl/base64.h> #include <sys/socket.h> #include <sys/types.h> -#include <sys/utsname.h> #include <android-base/file.h> #include <android-base/format.h> @@ -109,8 +108,10 @@ using android::net::MarkMaskParcel; using android::net::NativeNetworkConfig; using android::net::NativeNetworkType; using android::net::NativeVpnType; +using android::net::RULE_PRIORITY_BYPASSABLE_VPN; using android::net::RULE_PRIORITY_DEFAULT_NETWORK; using android::net::RULE_PRIORITY_EXPLICIT_NETWORK; +using android::net::RULE_PRIORITY_OUTPUT_INTERFACE; using android::net::RULE_PRIORITY_PROHIBIT_NON_VPN; using android::net::RULE_PRIORITY_SECURE_VPN; using android::net::RULE_PRIORITY_TETHERING; @@ -124,6 +125,8 @@ using android::net::TetherOffloadRuleParcel; using android::net::TetherStatsParcel; using android::net::TunInterface; using android::net::UidRangeParcel; +using android::net::UidRanges; +using android::net::netd::aidl::NativeUidRangeConfig; using android::netdutils::IPAddress; using android::netdutils::ScopedAddrinfo; using android::netdutils::sSyscalls; @@ -134,6 +137,7 @@ static const char* IP_RULE_V6 = "-6"; static const int TEST_NETID1 = 65501; static const int TEST_NETID2 = 65502; static const int TEST_NETID3 = 65503; +static const int TEST_NETID4 = 65504; static const int TEST_DUMP_NETID = 65123; static const char* DNSMASQ = "dnsmasq"; @@ -142,6 +146,9 @@ static const char* DNSMASQ = "dnsmasq"; static const int TEST_UID1 = 99999; static const int TEST_UID2 = 99998; static const int TEST_UID3 = 99997; +static const int TEST_UID4 = 99996; +static const int TEST_UID5 = 99995; +static const int TEST_UID6 = 99994; constexpr int BASE_UID = AID_USER_OFFSET * 5; @@ -170,6 +177,7 @@ class NetdBinderTest : public ::testing::Test { mNetd->networkDestroy(TEST_NETID1); mNetd->networkDestroy(TEST_NETID2); mNetd->networkDestroy(TEST_NETID3); + mNetd->networkDestroy(TEST_NETID4); setNetworkForProcess(NETID_UNSET); // Restore default network if (mStoredDefaultNetwork >= 0) mNetd->networkSetDefault(mStoredDefaultNetwork); @@ -182,9 +190,11 @@ class NetdBinderTest : public ::testing::Test { ASSERT_EQ(0, sTun.init()); ASSERT_EQ(0, sTun2.init()); ASSERT_EQ(0, sTun3.init()); + ASSERT_EQ(0, sTun4.init()); ASSERT_LE(sTun.name().size(), static_cast<size_t>(IFNAMSIZ)); ASSERT_LE(sTun2.name().size(), static_cast<size_t>(IFNAMSIZ)); ASSERT_LE(sTun3.name().size(), static_cast<size_t>(IFNAMSIZ)); + ASSERT_LE(sTun4.name().size(), static_cast<size_t>(IFNAMSIZ)); } static void TearDownTestCase() { @@ -192,6 +202,7 @@ class NetdBinderTest : public ::testing::Test { sTun.destroy(); sTun2.destroy(); sTun3.destroy(); + sTun4.destroy(); } static void fakeRemoteSocketPair(unique_fd* clientSocket, unique_fd* serverSocket, @@ -224,11 +235,13 @@ class NetdBinderTest : public ::testing::Test { static TunInterface sTun; static TunInterface sTun2; static TunInterface sTun3; + static TunInterface sTun4; }; TunInterface NetdBinderTest::sTun; TunInterface NetdBinderTest::sTun2; TunInterface NetdBinderTest::sTun3; +TunInterface NetdBinderTest::sTun4; class TimedOperation : public Stopwatch { public: @@ -551,14 +564,22 @@ TEST_F(NetdBinderTest, BandwidthEnableDataSaver) { } static bool ipRuleExistsForRange(const uint32_t priority, const UidRangeParcel& range, - const std::string& action, const char* ipVersion) { + const std::string& action, const char* ipVersion, + const char* oif) { // Output looks like this: + // "<priority>:\tfrom all iif lo oif netdc0ca6 uidrange 500000-500000 lookup netdc0ca6" // "<priority>:\tfrom all fwmark 0x0/0x20000 iif lo uidrange 1000-2000 prohibit" std::vector<std::string> rules = listIpRules(ipVersion); std::string prefix = StringPrintf("%" PRIu32 ":", priority); - std::string suffix = - StringPrintf(" iif lo uidrange %d-%d %s\n", range.start, range.stop, action.c_str()); + std::string suffix; + if (oif) { + suffix = StringPrintf(" iif lo oif %s uidrange %d-%d %s\n", oif, range.start, range.stop, + action.c_str()); + } else { + suffix = StringPrintf(" iif lo uidrange %d-%d %s\n", range.start, range.stop, + action.c_str()); + } for (const auto& line : rules) { if (android::base::StartsWith(line, prefix) && android::base::EndsWith(line, suffix)) { return true; @@ -567,14 +588,20 @@ static bool ipRuleExistsForRange(const uint32_t priority, const UidRangeParcel& return false; } +// Overloads function with oif parameter for VPN rules compare. static bool ipRuleExistsForRange(const uint32_t priority, const UidRangeParcel& range, - const std::string& action) { - bool existsIp4 = ipRuleExistsForRange(priority, range, action, IP_RULE_V4); - bool existsIp6 = ipRuleExistsForRange(priority, range, action, IP_RULE_V6); + const std::string& action, const char* oif) { + bool existsIp4 = ipRuleExistsForRange(priority, range, action, IP_RULE_V4, oif); + bool existsIp6 = ipRuleExistsForRange(priority, range, action, IP_RULE_V6, oif); EXPECT_EQ(existsIp4, existsIp6); return existsIp4; } +static bool ipRuleExistsForRange(const uint32_t priority, const UidRangeParcel& range, + const std::string& action) { + return ipRuleExistsForRange(priority, range, action, nullptr); +} + namespace { UidRangeParcel makeUidRangeParcel(int start, int stop) { @@ -585,6 +612,17 @@ UidRangeParcel makeUidRangeParcel(int start, int stop) { return res; } +NativeUidRangeConfig makeNativeUidRangeConfig(unsigned netId, + std::vector<UidRangeParcel>&& uidRanges, + uint32_t subPriority) { + NativeUidRangeConfig res; + res.netId = netId; + res.uidRanges = uidRanges; + res.subPriority = subPriority; + + return res; +} + } // namespace TEST_F(NetdBinderTest, NetworkInterfaces) { @@ -1229,16 +1267,6 @@ void expectIdletimerInterfaceRuleNotExists(const std::string& ifname, int timeou } // namespace TEST_F(NetdBinderTest, IdletimerAddRemoveInterface) { - // TODO(b/175745224): Temporarily disable idletimer test on >5.10 kernels - utsname u; - if (!uname(&u)) { - unsigned long major, minor; - char *p; - major = strtoul(u.release, &p, 10); - minor = strtoul(++p, NULL, 10); - if (major > 5 || (major == 5 && minor >= 10)) return; - } - // TODO: We will get error in if expectIdletimerInterfaceRuleNotExists if there are the same // rule in the table. Because we only check the result after calling remove function. We might // check the actual rule which is removed by our function (maybe compare the results between @@ -3948,32 +3976,69 @@ namespace { #define VPN_NETID TEST_NETID3 void verifyAppUidRules(std::vector<bool>&& expectedResults, std::vector<UidRangeParcel>& uidRanges, - const std::string& iface) { + const std::string& iface, uint32_t subPriority) { ASSERT_EQ(expectedResults.size(), uidRanges.size()); if (iface.size()) { std::string action = StringPrintf("lookup %s ", iface.c_str()); for (unsigned long i = 0; i < uidRanges.size(); i++) { - EXPECT_EQ(expectedResults[i], ipRuleExistsForRange(RULE_PRIORITY_UID_EXPLICIT_NETWORK, - uidRanges[i], action)); - EXPECT_EQ(expectedResults[i], ipRuleExistsForRange(RULE_PRIORITY_UID_IMPLICIT_NETWORK, - uidRanges[i], action)); - EXPECT_EQ(expectedResults[i], ipRuleExistsForRange(RULE_PRIORITY_UID_DEFAULT_NETWORK, - uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_UID_EXPLICIT_NETWORK + subPriority, + uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_UID_IMPLICIT_NETWORK + subPriority, + uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_UID_DEFAULT_NETWORK + subPriority, + uidRanges[i], action)); } } else { std::string action = "unreachable"; for (unsigned long i = 0; i < uidRanges.size(); i++) { - EXPECT_EQ(expectedResults[i], ipRuleExistsForRange(RULE_PRIORITY_UID_EXPLICIT_NETWORK, - uidRanges[i], action)); - EXPECT_EQ(expectedResults[i], ipRuleExistsForRange(RULE_PRIORITY_UID_IMPLICIT_NETWORK, - uidRanges[i], action)); EXPECT_EQ(expectedResults[i], - ipRuleExistsForRange(RULE_PRIORITY_UID_DEFAULT_UNREACHABLE, uidRanges[i], - action)); + ipRuleExistsForRange(RULE_PRIORITY_UID_EXPLICIT_NETWORK + subPriority, + uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_UID_IMPLICIT_NETWORK + subPriority, + uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_UID_DEFAULT_UNREACHABLE + subPriority, + uidRanges[i], action)); } } } +void verifyAppUidRules(std::vector<bool>&& expectedResults, NativeUidRangeConfig& uidRangeConfig, + const std::string& iface) { + verifyAppUidRules(move(expectedResults), uidRangeConfig.uidRanges, iface, + uidRangeConfig.subPriority); +} + +void verifyVpnUidRules(std::vector<bool>&& expectedResults, NativeUidRangeConfig& uidRangeConfig, + const std::string& iface, bool secure) { + ASSERT_EQ(expectedResults.size(), uidRangeConfig.uidRanges.size()); + std::string action = StringPrintf("lookup %s ", iface.c_str()); + + uint32_t priority; + if (secure) { + priority = RULE_PRIORITY_SECURE_VPN; + } else { + priority = RULE_PRIORITY_BYPASSABLE_VPN; + } + for (unsigned long i = 0; i < uidRangeConfig.uidRanges.size(); i++) { + EXPECT_EQ(expectedResults[i], ipRuleExistsForRange(priority + uidRangeConfig.subPriority, + uidRangeConfig.uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_EXPLICIT_NETWORK + uidRangeConfig.subPriority, + uidRangeConfig.uidRanges[i], action)); + EXPECT_EQ(expectedResults[i], + ipRuleExistsForRange(RULE_PRIORITY_OUTPUT_INTERFACE + uidRangeConfig.subPriority, + uidRangeConfig.uidRanges[i], action, iface.c_str())); + } +} + +constexpr int SUB_PRIORITY_1 = UidRanges::DEFAULT_SUB_PRIORITY + 1; +constexpr int SUB_PRIORITY_2 = UidRanges::DEFAULT_SUB_PRIORITY + 2; + constexpr int IMPLICITLY_SELECT = 0; constexpr int EXPLICITLY_SELECT = 1; constexpr int UNCONNECTED_SOCKET = 2; @@ -4087,18 +4152,24 @@ TEST_F(NetdBinderTest, PerAppDefaultNetwork_VerifyIpRules) { makeUidRangeParcel(BASE_UID + 8090, BASE_UID + 8099)}; EXPECT_TRUE(mNetd->networkAddUidRanges(APP_DEFAULT_NETID, uidRanges).isOk()); - verifyAppUidRules({true, true} /*expectedResults*/, uidRanges, sTun.name()); + verifyAppUidRules({true, true} /*expectedResults*/, uidRanges, sTun.name(), + UidRanges::DEFAULT_SUB_PRIORITY); EXPECT_TRUE(mNetd->networkRemoveUidRanges(APP_DEFAULT_NETID, {uidRanges.at(0)}).isOk()); - verifyAppUidRules({false, true} /*expectedResults*/, uidRanges, sTun.name()); + verifyAppUidRules({false, true} /*expectedResults*/, uidRanges, sTun.name(), + UidRanges::DEFAULT_SUB_PRIORITY); EXPECT_TRUE(mNetd->networkRemoveUidRanges(APP_DEFAULT_NETID, {uidRanges.at(1)}).isOk()); - verifyAppUidRules({false, false} /*expectedResults*/, uidRanges, sTun.name()); + verifyAppUidRules({false, false} /*expectedResults*/, uidRanges, sTun.name(), + UidRanges::DEFAULT_SUB_PRIORITY); EXPECT_TRUE(mNetd->networkAddUidRanges(INetd::UNREACHABLE_NET_ID, uidRanges).isOk()); - verifyAppUidRules({true, true} /*expectedResults*/, uidRanges, ""); + verifyAppUidRules({true, true} /*expectedResults*/, uidRanges, "", + UidRanges::DEFAULT_SUB_PRIORITY); EXPECT_TRUE(mNetd->networkRemoveUidRanges(INetd::UNREACHABLE_NET_ID, {uidRanges.at(0)}).isOk()); - verifyAppUidRules({false, true} /*expectedResults*/, uidRanges, ""); + verifyAppUidRules({false, true} /*expectedResults*/, uidRanges, "", + UidRanges::DEFAULT_SUB_PRIORITY); EXPECT_TRUE(mNetd->networkRemoveUidRanges(INetd::UNREACHABLE_NET_ID, {uidRanges.at(1)}).isOk()); - verifyAppUidRules({false, false} /*expectedResults*/, uidRanges, ""); + verifyAppUidRules({false, false} /*expectedResults*/, uidRanges, "", + UidRanges::DEFAULT_SUB_PRIORITY); } // Verify whether packets go through the right network with and without per-app default network. @@ -4420,3 +4491,211 @@ TEST_F(NetdBinderTest, NetworkCreate) { wrongConfig.vpnType = static_cast<NativeVpnType>(-1); EXPECT_EQ(EINVAL, mNetd->networkCreate(wrongConfig).serviceSpecificErrorCode()); } + +// Verifies valid and invalid inputs on networkAddUidRangesParcel method. +TEST_F(NetdBinderTest, UidRangeSubPriority_ValidateInputs) { + createVpnAndOtherPhysicalNetwork(SYSTEM_DEFAULT_NETID, APP_DEFAULT_NETID, VPN_NETID, + /*isSecureVPN=*/true); + // Invalid priority -1 on a physical network. + NativeUidRangeConfig uidRangeConfig = + makeNativeUidRangeConfig(APP_DEFAULT_NETID, {makeUidRangeParcel(BASE_UID, BASE_UID)}, + UidRanges::DEFAULT_SUB_PRIORITY - 1); + binder::Status status = mNetd->networkAddUidRangesParcel(uidRangeConfig); + EXPECT_FALSE(status.isOk()); + EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); + + // Invalid priority 1000 on a physical network. + uidRangeConfig.subPriority = UidRanges::LOWEST_SUB_PRIORITY + 1; + status = mNetd->networkAddUidRangesParcel(uidRangeConfig); + EXPECT_FALSE(status.isOk()); + EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); + + // Virtual networks support only default priority. + uidRangeConfig.netId = VPN_NETID; + uidRangeConfig.subPriority = SUB_PRIORITY_1; + status = mNetd->networkAddUidRangesParcel(uidRangeConfig); + EXPECT_FALSE(status.isOk()); + EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); + + // For a single network, identical UID ranges with different priorities are allowed. + uidRangeConfig.netId = APP_DEFAULT_NETID; + uidRangeConfig.subPriority = SUB_PRIORITY_1; + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig).isOk()); + uidRangeConfig.subPriority = SUB_PRIORITY_2; + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig).isOk()); + + // For a single network, identical UID ranges with the same priority is invalid. + status = mNetd->networkAddUidRangesParcel(uidRangeConfig); + EXPECT_FALSE(status.isOk()); + EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); + + // Overlapping ranges is invalid. + uidRangeConfig.uidRanges = {makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1), + makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1)}; + status = mNetd->networkAddUidRangesParcel(uidRangeConfig); + EXPECT_FALSE(status.isOk()); + EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode()); +} + +// Examines whether IP rules for app default network with subsidiary priorities are correctly added +// and removed. +TEST_F(NetdBinderTest, UidRangeSubPriority_VerifyPhysicalNwIpRules) { + createPhysicalNetwork(TEST_NETID1, sTun.name()); + EXPECT_TRUE(mNetd->networkAddRoute(TEST_NETID1, sTun.name(), "::/0", "").isOk()); + createPhysicalNetwork(TEST_NETID2, sTun2.name()); + EXPECT_TRUE(mNetd->networkAddRoute(TEST_NETID2, sTun2.name(), "::/0", "").isOk()); + + // Adds priority 1 setting + NativeUidRangeConfig uidRangeConfig1 = makeNativeUidRangeConfig( + TEST_NETID1, {makeUidRangeParcel(BASE_UID, BASE_UID)}, SUB_PRIORITY_1); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig1).isOk()); + verifyAppUidRules({true}, uidRangeConfig1, sTun.name()); + // Adds priority 2 setting + NativeUidRangeConfig uidRangeConfig2 = makeNativeUidRangeConfig( + TEST_NETID2, {makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1)}, SUB_PRIORITY_2); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig2).isOk()); + verifyAppUidRules({true}, uidRangeConfig2, sTun2.name()); + // Adds another priority 2 setting + NativeUidRangeConfig uidRangeConfig3 = makeNativeUidRangeConfig( + INetd::UNREACHABLE_NET_ID, {makeUidRangeParcel(BASE_UID + 2, BASE_UID + 2)}, + SUB_PRIORITY_2); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig3).isOk()); + verifyAppUidRules({true}, uidRangeConfig3, ""); + + // Removes. + EXPECT_TRUE(mNetd->networkRemoveUidRangesParcel(uidRangeConfig1).isOk()); + verifyAppUidRules({false}, uidRangeConfig1, sTun.name()); + verifyAppUidRules({true}, uidRangeConfig2, sTun2.name()); + verifyAppUidRules({true}, uidRangeConfig3, ""); + EXPECT_TRUE(mNetd->networkRemoveUidRangesParcel(uidRangeConfig2).isOk()); + verifyAppUidRules({false}, uidRangeConfig1, sTun.name()); + verifyAppUidRules({false}, uidRangeConfig2, sTun2.name()); + verifyAppUidRules({true}, uidRangeConfig3, ""); + EXPECT_TRUE(mNetd->networkRemoveUidRangesParcel(uidRangeConfig3).isOk()); + verifyAppUidRules({false}, uidRangeConfig1, sTun.name()); + verifyAppUidRules({false}, uidRangeConfig2, sTun2.name()); + verifyAppUidRules({false}, uidRangeConfig3, ""); +} + +// Verify uid range rules on virtual network. +TEST_P(VpnParameterizedTest, UidRangeSubPriority_VerifyVpnIpRules) { + const bool isSecureVPN = GetParam(); + constexpr int VPN_NETID2 = TEST_NETID2; + + // Create 2 VPNs, using sTun and sTun2. + auto config = makeNativeNetworkConfig(VPN_NETID, NativeNetworkType::VIRTUAL, + INetd::PERMISSION_NONE, isSecureVPN); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + EXPECT_TRUE(mNetd->networkAddInterface(VPN_NETID, sTun.name()).isOk()); + + config = makeNativeNetworkConfig(VPN_NETID2, NativeNetworkType::VIRTUAL, INetd::PERMISSION_NONE, + isSecureVPN); + EXPECT_TRUE(mNetd->networkCreate(config).isOk()); + EXPECT_TRUE(mNetd->networkAddInterface(VPN_NETID2, sTun2.name()).isOk()); + + // Assign uid ranges to different VPNs. Check if rules match. + NativeUidRangeConfig uidRangeConfig1 = makeNativeUidRangeConfig( + VPN_NETID, {makeUidRangeParcel(BASE_UID, BASE_UID)}, UidRanges::DEFAULT_SUB_PRIORITY); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig1).isOk()); + verifyVpnUidRules({true}, uidRangeConfig1, sTun.name(), isSecureVPN); + + NativeUidRangeConfig uidRangeConfig2 = + makeNativeUidRangeConfig(VPN_NETID2, {makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1)}, + UidRanges::DEFAULT_SUB_PRIORITY); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig2).isOk()); + verifyVpnUidRules({true}, uidRangeConfig2, sTun2.name(), isSecureVPN); + + // Remove uid configs one-by-one. Check if rules match. + EXPECT_TRUE(mNetd->networkRemoveUidRangesParcel(uidRangeConfig1).isOk()); + verifyVpnUidRules({false}, uidRangeConfig1, sTun.name(), isSecureVPN); + verifyVpnUidRules({true}, uidRangeConfig2, sTun2.name(), isSecureVPN); + EXPECT_TRUE(mNetd->networkRemoveUidRangesParcel(uidRangeConfig2).isOk()); + verifyVpnUidRules({false}, uidRangeConfig1, sTun.name(), isSecureVPN); + verifyVpnUidRules({false}, uidRangeConfig2, sTun2.name(), isSecureVPN); +} + +// Verify if packets go through the right network when subsidiary priority and VPN works together. +// +// Test config: +// +----------+------------------------+-------------------------------------------+ +// | Priority | UID | Assigned Network | +// +----------+------------------------+-------------------------------------------+ +// | 0 | TEST_UID1 | VPN bypassable (VPN_NETID) | +// +----------+------------------------+-------------------------------------------+ +// | 1 | TEST_UID1, TEST_UID2, | Physical Network 1 (APP_DEFAULT_1_NETID) | +// | 1 | TEST_UID3 | Physical Network 2 (APP_DEFAULT_2_NETID) | +// | 1 | TEST_UID5 | Unreachable Network (UNREACHABLE_NET_ID) | +// +----------+------------------------+-------------------------------------------+ +// | 2 | TEST_UID3 | Physical Network 1 (APP_DEFAULT_1_NETID) | +// | 2 | TEST_UID4, TEST_UID5 | Physical Network 2 (APP_DEFAULT_2_NETID) | +// +----------+------------------------+-------------------------------------------+ +// +// Expected results: +// +-----------+------------------------+ +// | UID | Using Network | +// +-----------+------------------------+ +// | TEST_UID1 | VPN | +// | TEST_UID2 | Physical Network 1 | +// | TEST_UID3 | Physical Network 2 | +// | TEST_UID4 | Physical Network 2 | +// | TEST_UID5 | Unreachable Network | +// | TEST_UID6 | System Default Network | +// +-----------+------------------------+ +// +// SYSTEM_DEFAULT_NETID uses sTun. +// APP_DEFAULT_1_NETID uses sTun2. +// VPN_NETID uses sTun3. +// APP_DEFAULT_2_NETID uses sTun4. +// +TEST_F(NetdBinderTest, UidRangeSubPriority_ImplicitlySelectNetwork) { + constexpr int APP_DEFAULT_1_NETID = TEST_NETID2; + constexpr int APP_DEFAULT_2_NETID = TEST_NETID4; + + // Creates 4 networks. + createVpnAndOtherPhysicalNetwork(SYSTEM_DEFAULT_NETID, APP_DEFAULT_1_NETID, VPN_NETID, + /*isSecureVPN=*/false); + createPhysicalNetwork(APP_DEFAULT_2_NETID, sTun4.name()); + EXPECT_TRUE(mNetd->networkAddRoute(APP_DEFAULT_2_NETID, sTun4.name(), "::/0", "").isOk()); + + // Adds VPN setting. + NativeUidRangeConfig uidRangeConfigVpn = makeNativeUidRangeConfig( + VPN_NETID, {makeUidRangeParcel(TEST_UID1, TEST_UID1)}, UidRanges::DEFAULT_SUB_PRIORITY); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfigVpn).isOk()); + + // Adds uidRangeConfig1 setting. + NativeUidRangeConfig uidRangeConfig1 = makeNativeUidRangeConfig( + APP_DEFAULT_1_NETID, + {makeUidRangeParcel(TEST_UID1, TEST_UID1), makeUidRangeParcel(TEST_UID2, TEST_UID2)}, + SUB_PRIORITY_1); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig1).isOk()); + uidRangeConfig1.netId = APP_DEFAULT_2_NETID; + uidRangeConfig1.uidRanges = {makeUidRangeParcel(TEST_UID3, TEST_UID3)}; + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig1).isOk()); + uidRangeConfig1.netId = INetd::UNREACHABLE_NET_ID; + uidRangeConfig1.uidRanges = {makeUidRangeParcel(TEST_UID5, TEST_UID5)}; + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig1).isOk()); + + // Adds uidRangeConfig2 setting. + NativeUidRangeConfig uidRangeConfig2 = makeNativeUidRangeConfig( + APP_DEFAULT_1_NETID, {makeUidRangeParcel(TEST_UID3, TEST_UID3)}, SUB_PRIORITY_2); + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig2).isOk()); + uidRangeConfig2.netId = APP_DEFAULT_2_NETID; + uidRangeConfig2.uidRanges = {makeUidRangeParcel(TEST_UID4, TEST_UID4), + makeUidRangeParcel(TEST_UID5, TEST_UID5)}; + EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig2).isOk()); + + int systemDefaultFd = sTun.getFdForTesting(); + int appDefault_1_Fd = sTun2.getFdForTesting(); + int vpnFd = sTun3.getFdForTesting(); + int appDefault_2_Fd = sTun4.getFdForTesting(); + // Verify routings. + expectPacketSentOnNetId(TEST_UID1, VPN_NETID, vpnFd, IMPLICITLY_SELECT); + expectPacketSentOnNetId(TEST_UID2, APP_DEFAULT_1_NETID, appDefault_1_Fd, IMPLICITLY_SELECT); + expectPacketSentOnNetId(TEST_UID3, APP_DEFAULT_2_NETID, appDefault_2_Fd, IMPLICITLY_SELECT); + expectPacketSentOnNetId(TEST_UID4, APP_DEFAULT_2_NETID, appDefault_2_Fd, IMPLICITLY_SELECT); + expectUnreachableError(TEST_UID5, INetd::UNREACHABLE_NET_ID, IMPLICITLY_SELECT); + expectPacketSentOnNetId(TEST_UID6, SYSTEM_DEFAULT_NETID, systemDefaultFd, IMPLICITLY_SELECT); + + // Remove test rules from the unreachable network. + EXPECT_TRUE(mNetd->networkRemoveUidRangesParcel(uidRangeConfig1).isOk()); +}
\ No newline at end of file |