From fcfcc8469e312388e51d8ec84325552a493f2f77 Mon Sep 17 00:00:00 2001 From: roger2015 Date: Fri, 13 Jun 2025 17:18:49 +0800 Subject: [PATCH 1/3] fix netd --- .../netd/server/BandwidthController.cpp | 1 - aosp/system/netd/server/Controllers.cpp | 4 - aosp/system/netd/server/FwmarkServer.cpp | 2 - .../netd/server/InterfaceController.cpp | 1 + .../netd/server/IptablesRestoreController.cpp | 9 +- aosp/system/netd/server/NetlinkManager.cpp | 1 - aosp/system/netd/server/RouteController.cpp | 20 +- aosp/system/netd/server/RouteController.h | 259 ++++++++++++++++++ 8 files changed, 276 insertions(+), 21 deletions(-) create mode 100644 aosp/system/netd/server/RouteController.h diff --git a/aosp/system/netd/server/BandwidthController.cpp b/aosp/system/netd/server/BandwidthController.cpp index a75b2bb2a..438dbb8d2 100644 --- a/aosp/system/netd/server/BandwidthController.cpp +++ b/aosp/system/netd/server/BandwidthController.cpp @@ -541,7 +541,6 @@ int BandwidthController::updateQuota(const std::string& quotaName, int64_t bytes if (!isOk(file)) { int res = errno; ALOGE("Updating quota %s failed (%s)", quotaName.c_str(), toString(file).c_str()); - res = 0; return -res; } // TODO: should we propagate this error? diff --git a/aosp/system/netd/server/Controllers.cpp b/aosp/system/netd/server/Controllers.cpp index 9595c1fae..b29064fb4 100644 --- a/aosp/system/netd/server/Controllers.cpp +++ b/aosp/system/netd/server/Controllers.cpp @@ -267,10 +267,6 @@ static void setupConnmarkIptablesHooks() { } void Controllers::initIptablesRules() { - if (true) { - return; - } - Stopwatch s; initChildChains(); gLog.info("Creating child chains: %" PRId64 "us", s.getTimeAndResetUs()); diff --git a/aosp/system/netd/server/FwmarkServer.cpp b/aosp/system/netd/server/FwmarkServer.cpp index 5a664db24..48ac33d53 100644 --- a/aosp/system/netd/server/FwmarkServer.cpp +++ b/aosp/system/netd/server/FwmarkServer.cpp @@ -308,12 +308,10 @@ int FwmarkServer::processClient(SocketClient* client, int* socketFd) { fwmark.permission = permission; -#if 0 if (setsockopt(*socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue, sizeof(fwmark.intValue)) == -1) { return -errno; } -#endif return 0; } diff --git a/aosp/system/netd/server/InterfaceController.cpp b/aosp/system/netd/server/InterfaceController.cpp index a79daf5fe..7d0dcbf18 100644 --- a/aosp/system/netd/server/InterfaceController.cpp +++ b/aosp/system/netd/server/InterfaceController.cpp @@ -188,6 +188,7 @@ Status setProperty(const std::string& key, const std::string& val) { : statusFromErrno(EREMOTEIO, "SetProperty failed, see libc logs"); }; + } // namespace namespace android { diff --git a/aosp/system/netd/server/IptablesRestoreController.cpp b/aosp/system/netd/server/IptablesRestoreController.cpp index 5cfa86cfb..9965aabdf 100644 --- a/aosp/system/netd/server/IptablesRestoreController.cpp +++ b/aosp/system/netd/server/IptablesRestoreController.cpp @@ -111,8 +111,8 @@ void IptablesRestoreController::Init() { // use by the other child process. see https://android-review.googlesource.com/469559 for what // breaks. This does not cause a latency hit, because the parent only has to wait for // forkAndExec, which is sub-millisecond, and the child processes then call exec() in parallel. - // mIpRestore.reset(forkAndExec(IPTABLES_PROCESS)); - // mIp6Restore.reset(forkAndExec(IP6TABLES_PROCESS)); + mIpRestore.reset(forkAndExec(IPTABLES_PROCESS)); + mIp6Restore.reset(forkAndExec(IP6TABLES_PROCESS)); } /* static */ @@ -190,10 +190,6 @@ IptablesProcess* IptablesRestoreController::forkAndExec(const IptablesProcessTyp int IptablesRestoreController::sendCommand(const IptablesProcessType type, const std::string& command, std::string *output) { - (void) type; - (void) command; - (void) output; -#if 0 std::unique_ptr *process = (type == IPTABLES_PROCESS) ? &mIpRestore : &mIp6Restore; @@ -236,7 +232,6 @@ int IptablesRestoreController::sendCommand(const IptablesProcessType type, // drainAndWaitForAck has already logged an error. return -1; } -#endif return 0; } diff --git a/aosp/system/netd/server/NetlinkManager.cpp b/aosp/system/netd/server/NetlinkManager.cpp index cae9110ed..9883bbee1 100644 --- a/aosp/system/netd/server/NetlinkManager.cpp +++ b/aosp/system/netd/server/NetlinkManager.cpp @@ -85,7 +85,6 @@ NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily, // When running in a net/user namespace, SO_RCVBUFFORCE will fail because // it will check for the CAP_NET_ADMIN capability in the root namespace. // Try using SO_RCVBUF if that fails. - // if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 && if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0) { ALOGE("Unable to set uevent socket SO_RCVBUF option: %s", strerror(errno)); close(*sock); diff --git a/aosp/system/netd/server/RouteController.cpp b/aosp/system/netd/server/RouteController.cpp index 8c2fd6c0c..1cef053e5 100644 --- a/aosp/system/netd/server/RouteController.cpp +++ b/aosp/system/netd/server/RouteController.cpp @@ -831,7 +831,7 @@ int RouteController::configureDummyNetwork() { fwmark.netId = NETID_UNSET; mask.netId = FWMARK_NET_ID_MASK; - return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_IMPLICIT_NETWORK, RT_TABLE_MAIN, + return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_DIRECTLY_CONNECTED, RT_TABLE_MAIN, fwmark.intValue, mask.intValue); } @@ -1154,7 +1154,7 @@ void modifyInnerNetworkRules(uint16_t action, const char* interface) { return; } char from_ip[PROPERTY_VALUE_MAX]; - property_get("ru.from.ip", from_ip, "10.237.0.0/16"); + property_get("ru.from.ip", from_ip, "\0"); if (strlen(from_ip) > 0) { const char* argv[] = { "/system/bin/ip", "-4", "rule", action == RTM_NEWRULE ? "add" : "del", @@ -1168,7 +1168,7 @@ void modifyInnerNetworkRules(uint16_t action, const char* interface) { } char to_ip[PROPERTY_VALUE_MAX]; - property_get("ru.to.ip", to_ip, "100.125.0.0/16,100.64.0.0/16"); + property_get("ru.to.ip", to_ip, "\0"); if (strlen(to_ip) > 0) { const char delim[2] = ","; char *p; @@ -1190,15 +1190,23 @@ void modifyInnerNetworkRules(uint16_t action, const char* interface) { int RouteController::modifyDefaultNetwork(uint16_t action, const char* interface, Permission permission) { - (void)permission; uint32_t table = getRouteTableForInterface(interface, false /* local */); if (table == RT_TABLE_UNSPEC) { return -ESRCH; } + Fwmark fwmark; + Fwmark mask; + + fwmark.netId = NETID_UNSET; + mask.netId = FWMARK_NET_ID_MASK; + + fwmark.permission = permission; + mask.permission = permission; + modifyInnerNetworkRules(action, interface); - return modifyIpRule(action, RULE_PRIORITY_DEFAULT_NETWORK, table, FWMARK_NONE, - MASK_NONE); + return modifyIpRule(action, RULE_PRIORITY_DEFAULT_NETWORK, table, fwmark.intValue, + mask.intValue); } int RouteController::modifyTetheredNetwork(uint16_t action, const char* inputInterface, diff --git a/aosp/system/netd/server/RouteController.h b/aosp/system/netd/server/RouteController.h new file mode 100644 index 000000000..a56d4e05d --- /dev/null +++ b/aosp/system/netd/server/RouteController.h @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2014 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. + */ + +#pragma once + +#include "InterfaceController.h" // getParameter +#include "NetdConstants.h" // IptablesTarget +#include "Network.h" // UidRangeMap +#include "Permission.h" + +#include + +#include +#include +#include +#include + +namespace android::net { + +// clang-format off +constexpr int32_t RULE_PRIORITY_VPN_OVERRIDE_SYSTEM = 10000; +constexpr int32_t RULE_PRIORITY_VPN_OVERRIDE_OIF = 11000; +constexpr int32_t RULE_PRIORITY_VPN_OUTPUT_TO_LOCAL = 12000; +constexpr int32_t RULE_PRIORITY_SECURE_VPN = 13000; +constexpr int32_t RULE_PRIORITY_PROHIBIT_NON_VPN = 14000; +// Rules used when applications explicitly select a network that they have permission to use only +// because they are in the list of UID ranges for that network. +// +// Sockets from these UIDs will not match RULE_PRIORITY_EXPLICIT_NETWORK rules because they will +// not have the necessary permission bits in the fwmark. We cannot just give any socket on any of +// these networks the permission bits, because if the UID that created the socket loses access to +// the network, then the socket must not match any rule that selects that network. +constexpr int32_t RULE_PRIORITY_UID_EXPLICIT_NETWORK = 15000; +constexpr int32_t RULE_PRIORITY_EXPLICIT_NETWORK = 16000; +constexpr int32_t RULE_PRIORITY_OUTPUT_INTERFACE = 17000; +constexpr int32_t RULE_PRIORITY_LEGACY_SYSTEM = 18000; +constexpr int32_t RULE_PRIORITY_LEGACY_NETWORK = 19000; +constexpr int32_t RULE_PRIORITY_LOCAL_NETWORK = 20000; +constexpr int32_t RULE_PRIORITY_TETHERING = 21000; +// Implicit rules for sockets that connected on a given network because the network was the default +// network for the UID. +constexpr int32_t RULE_PRIORITY_UID_IMPLICIT_NETWORK = 22000; +constexpr int32_t RULE_PRIORITY_IMPLICIT_NETWORK = 23000; +constexpr int32_t RULE_PRIORITY_BYPASSABLE_VPN_NO_LOCAL_EXCLUSION = 24000; +// Sets of rules used for excluding local routes from the VPN. Look up tables +// that contain directly-connected local routes taken from the default network. +// The first set is used for apps that have a per-UID default network. The rule +// UID ranges match those of the per-UID default network rule for that network. +// The second set has no UID ranges and is used for apps whose default network +// is the system default network network. +constexpr int32_t RULE_PRIORITY_UID_LOCAL_ROUTES = 25000; +constexpr int32_t RULE_PRIORITY_LOCAL_ROUTES = 26000; +constexpr int32_t RULE_PRIORITY_BYPASSABLE_VPN_LOCAL_EXCLUSION = 27000; +constexpr int32_t RULE_PRIORITY_VPN_FALLTHROUGH = 28000; +constexpr int32_t RULE_PRIORITY_UID_DEFAULT_NETWORK = 29000; +// Rule used when framework wants to disable default network from specified applications. There will +// be a small interval the same uid range exists in both UID_DEFAULT_UNREACHABLE and +// UID_DEFAULT_NETWORK when framework is switching user preferences. +// +// framework --> netd +// step 1: set uid to unreachable network +// step 2: remove uid from OEM-paid network list +// or +// step 1: add uid to OEM-paid network list +// step 2: remove uid from unreachable network +// +// The priority is lower than UID_DEFAULT_NETWORK. Otherwise, the app will be told by +// ConnectivityService that it has a network in step 1 of the second case. But if it tries to use +// the network, it will not work. That will potentially cause a user-visible error. +constexpr int32_t RULE_PRIORITY_UID_DEFAULT_UNREACHABLE = 30000; +constexpr int32_t RULE_PRIORITY_DEFAULT_NETWORK = 31000; +constexpr int32_t RULE_PRIORITY_UNREACHABLE = 32000; +// clang-format on + +class UidRanges; + +class RouteController { +public: + // How the routing table number is determined for route modification requests. + enum TableType { + INTERFACE, // Compute the table number based on the interface index. + LOCAL_NETWORK, // A fixed table used for routes to directly-connected clients/peers. + LEGACY_NETWORK, // Use a fixed table that's used to override the default network. + LEGACY_SYSTEM, // A fixed table, only modifiable by system apps; overrides VPNs too. + }; + + static const int ROUTE_TABLE_OFFSET_FROM_INDEX = 1000; + // Offset for the table of virtual local network created from the physical interface. + static const int ROUTE_TABLE_OFFSET_FROM_INDEX_FOR_LOCAL = 1000000000; + + static constexpr const char* INTERFACE_LOCAL_SUFFIX = "_local"; + static constexpr const char* RT_TABLES_PATH = "/data/misc/net/rt_tables"; + static const char* const LOCAL_MANGLE_INPUT; + + [[nodiscard]] static int Init(unsigned localNetId); + + // Returns an ifindex given the interface name, by looking up in sInterfaceToTable. + // This is currently only used by NetworkController::addInterfaceToNetwork + // and should probabaly be changed to passing the ifindex into RouteController instead. + // We do this instead of calling if_nametoindex because the same interface name can + // correspond to different interface indices over time. This way, even if the interface + // index has changed, we can still free any map entries indexed by the ifindex that was + // used to add them. + static uint32_t getIfIndex(const char* interface) EXCLUDES(sInterfaceToTableLock); + + [[nodiscard]] static int addInterfaceToLocalNetwork(unsigned netId, const char* interface); + [[nodiscard]] static int removeInterfaceFromLocalNetwork(unsigned netId, const char* interface); + + [[nodiscard]] static int addInterfaceToPhysicalNetwork(unsigned netId, const char* interface, + Permission permission, + const UidRangeMap& uidRangeMap, + bool local); + [[nodiscard]] static int removeInterfaceFromPhysicalNetwork(unsigned netId, + const char* interface, + Permission permission, + const UidRangeMap& uidRangeMap, + bool local); + + [[nodiscard]] static int addInterfaceToVirtualNetwork(unsigned netId, const char* interface, + bool secure, + const UidRangeMap& uidRangeMap, + bool excludeLocalRoutes); + [[nodiscard]] static int removeInterfaceFromVirtualNetwork(unsigned netId, + const char* interface, bool secure, + const UidRangeMap& uidRangeMap, + bool excludeLocalRoutes); + + [[nodiscard]] static int modifyPhysicalNetworkPermission(unsigned netId, const char* interface, + Permission oldPermission, + Permission newPermission, bool local); + + [[nodiscard]] static int addUsersToVirtualNetwork(unsigned netId, const char* interface, + bool secure, const UidRangeMap& uidRangeMap, + bool excludeLocalRoutes); + [[nodiscard]] static int removeUsersFromVirtualNetwork(unsigned netId, const char* interface, + bool secure, + const UidRangeMap& uidRangeMap, + bool excludeLocalRoutes); + + [[nodiscard]] static int addUsersToRejectNonSecureNetworkRule(const UidRanges& uidRanges); + [[nodiscard]] static int removeUsersFromRejectNonSecureNetworkRule(const UidRanges& uidRanges); + + [[nodiscard]] static int addInterfaceToDefaultNetwork(const char* interface, + Permission permission); + [[nodiscard]] static int removeInterfaceFromDefaultNetwork(const char* interface, + Permission permission); + + // |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. + [[nodiscard]] static int addRoute(const char* interface, const char* destination, + const char* nexthop, TableType tableType, int mtu, + int priority); + [[nodiscard]] static int removeRoute(const char* interface, const char* destination, + const char* nexthop, TableType tableType, int priority); + [[nodiscard]] static int updateRoute(const char* interface, const char* destination, + const char* nexthop, TableType tableType, int mtu); + + [[nodiscard]] static int enableTethering(const char* inputInterface, + const char* outputInterface); + [[nodiscard]] static int disableTethering(const char* inputInterface, + const char* outputInterface); + + [[nodiscard]] static int addVirtualNetworkFallthrough(unsigned vpnNetId, + const char* physicalInterface, + Permission permission); + [[nodiscard]] static int removeVirtualNetworkFallthrough(unsigned vpnNetId, + const char* physicalInterface, + Permission permission); + + [[nodiscard]] static int addUsersToPhysicalNetwork(unsigned netId, const char* interface, + const UidRangeMap& uidRangeMap, bool local); + + [[nodiscard]] static int removeUsersFromPhysicalNetwork(unsigned netId, const char* interface, + const UidRangeMap& uidRangeMap, + bool local); + + [[nodiscard]] static int addUsersToUnreachableNetwork(unsigned netId, + const UidRangeMap& uidRangeMap); + + [[nodiscard]] static int removeUsersFromUnreachableNetwork(unsigned netId, + const UidRangeMap& uidRangeMap); + + // For testing. + static int (*iptablesRestoreCommandFunction)(IptablesTarget, const std::string&, + const std::string&, std::string *); + static uint32_t (*ifNameToIndexFunction)(const char*); + + private: + friend class RouteControllerTest; + + // An expandable array for fixed local prefix though it's only one element now. + static constexpr const char* V4_FIXED_LOCAL_PREFIXES[] = { + // The multicast range is 224.0.0.0/4 but only limit it to 224.0.0.0/24 since the IPv4 + // definitions are not as precise as for IPv6, it is the only range that the standards + // (RFC 2365 and RFC 5771) specify is link-local and must not be forwarded. + "224.0.0.0/24" // Link-local multicast; non-internet routable + }; + + static std::mutex sInterfaceToTableLock; + static std::map sInterfaceToTable GUARDED_BY(sInterfaceToTableLock); + + static int configureDummyNetwork(); + [[nodiscard]] static int flushRoutes(const char* interface) EXCLUDES(sInterfaceToTableLock); + [[nodiscard]] static int flushRoutes(const char* interface, bool local) + EXCLUDES(sInterfaceToTableLock); + [[nodiscard]] static int flushRoutes(uint32_t table); + static uint32_t getRouteTableForInterfaceLocked(const char* interface, bool local) + REQUIRES(sInterfaceToTableLock); + static uint32_t getRouteTableForInterface(const char* interface, bool local) + EXCLUDES(sInterfaceToTableLock); + static int modifyDefaultNetwork(uint16_t action, const char* interface, Permission permission); + static int modifyPhysicalNetwork(unsigned netId, const char* interface, + const UidRangeMap& uidRangeMap, Permission permission, + bool add, bool modifyNonUidBasedRules, bool local); + 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, int priority, bool isLocal); + static int modifyTetheredNetwork(uint16_t action, const char* inputInterface, + const char* outputInterface); + static int modifyVpnFallthroughRule(uint16_t action, unsigned vpnNetId, + const char* physicalInterface, Permission permission); + static int modifyVirtualNetwork(unsigned netId, const char* interface, + const UidRangeMap& uidRangeMap, bool secure, bool add, + bool modifyNonUidBasedRules, bool excludeLocalRoutes); + static void updateTableNamesFile() EXCLUDES(sInterfaceToTableLock); + static int modifyVpnLocalExclusionRule(bool add, const char* physicalInterface); + + static int modifyUidLocalNetworkRule(const char* interface, uid_t uidStart, uid_t uidEnd, + bool add); + static bool isLocalRoute(TableType tableType, const char* destination, const char* nexthop); + static bool isWithinIpv4LocalPrefix(const char* addrstr); + static int addFixedLocalRoutes(const char* interface); +}; + +// Public because they are called by by RouteControllerTest.cpp. +// TODO: come up with a scheme of unit testing this code that does not rely on making all its +// functions public. +[[nodiscard]] int modifyIpRoute(uint16_t action, uint16_t flags, uint32_t table, + const char* interface, const char* destination, const char* nexthop, + uint32_t mtu, uint32_t priority); +uint32_t getRulePriority(const nlmsghdr *nlh); +[[nodiscard]] int modifyIncomingPacketMark(unsigned netId, const char* interface, + Permission permission, bool add); + +} // namespace android::net -- Gitee From 5d2addf03dc79c5c41b941fe5650eb6d9db0d781 Mon Sep 17 00:00:00 2001 From: roger2015 Date: Fri, 13 Jun 2025 17:20:35 +0800 Subject: [PATCH 2/3] add RULE_PRIORITY_DIRECTLY_CONNECTED --- aosp/system/netd/server/RouteController.h | 1 + 1 file changed, 1 insertion(+) diff --git a/aosp/system/netd/server/RouteController.h b/aosp/system/netd/server/RouteController.h index a56d4e05d..22d64801c 100644 --- a/aosp/system/netd/server/RouteController.h +++ b/aosp/system/netd/server/RouteController.h @@ -82,6 +82,7 @@ constexpr int32_t RULE_PRIORITY_UID_DEFAULT_NETWORK = 29000; // the network, it will not work. That will potentially cause a user-visible error. constexpr int32_t RULE_PRIORITY_UID_DEFAULT_UNREACHABLE = 30000; constexpr int32_t RULE_PRIORITY_DEFAULT_NETWORK = 31000; +constexpr int32_t RULE_PRIORITY_DIRECTLY_CONNECTED = 31500; constexpr int32_t RULE_PRIORITY_UNREACHABLE = 32000; // clang-format on -- Gitee From 83cfbf770a0aa1e92861b26938765d8b29061fa5 Mon Sep 17 00:00:00 2001 From: roger2015 Date: Tue, 17 Jun 2025 19:25:44 +0800 Subject: [PATCH 3/3] fix netd --- aosp/system/netd/server/IptablesRestoreController.cpp | 1 - aosp/system/netd/server/netd.rc | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/aosp/system/netd/server/IptablesRestoreController.cpp b/aosp/system/netd/server/IptablesRestoreController.cpp index 9965aabdf..ada9af4d5 100644 --- a/aosp/system/netd/server/IptablesRestoreController.cpp +++ b/aosp/system/netd/server/IptablesRestoreController.cpp @@ -351,7 +351,6 @@ int IptablesRestoreController::execute(const IptablesTarget target, const std::s res = 0; } } - res = 0; return res; } diff --git a/aosp/system/netd/server/netd.rc b/aosp/system/netd/server/netd.rc index 1eab7bf30..672ef0cdd 100644 --- a/aosp/system/netd/server/netd.rc +++ b/aosp/system/netd/server/netd.rc @@ -6,6 +6,8 @@ service netd /system/bin/netd socket dnsproxyd stream 0660 root inet socket mdns stream 0660 root system socket fwmarkd stream 0660 root inet + onrestart restart zygote + onrestart restart zygote_secondary # b/121354779: netd itself is not updatable, but on startup it dlopen()s the resolver library # from the DNS resolver APEX. Mark it as updatable so init won't start it until all APEX # packages are ready. -- Gitee