summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChiachang <chiachangwang@google.com>2022-05-04 07:45:37 +0000
committerCherrypicker Worker <android-build-cherrypicker-worker@google.com>2022-06-02 12:45:52 +0000
commit8a03faaefe4858b848102ccb596b906e0194ef96 (patch)
treebfabd61e9fca4b9967d1aa4934e4108e00f23bc2
parentf7267cfcfc7db62b8365fcff621403c0dadcfd67 (diff)
downloadnetd-8a03faaefe4858b848102ccb596b906e0194ef96.tar.gz
Add local rule only for default network
The existing flow would add local rules for each physical interface. The order of the rules in the routing table is depending on the order that interfaces were added. It may cause non-deterministic routing depending on the racing of registering networks. The rule should only be needed for default network, so update the flow to update rules with fall through rules updates while switching the default network. Bug: 184750836 Test: cd system/netd ; atest Change-Id: I632f249ead6b418df40fa9639104043a66726d23 (cherry picked from commit 2271c127ad8e8e99c675b38b1414ffa092726d25) Merged-In: I632f249ead6b418df40fa9639104043a66726d23
-rw-r--r--server/RouteController.cpp21
-rw-r--r--tests/binder_test.cpp24
2 files changed, 29 insertions, 16 deletions
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index 5ed33cdd..d63dbd2e 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -1252,10 +1252,6 @@ int RouteController::addInterfaceToPhysicalNetwork(unsigned netId, const char* i
MODIFY_NON_UID_BASED_RULES)) {
return ret;
}
- // TODO: Consider to remove regular table if adding local table failed.
- if (int ret = modifyVpnLocalExclusionRule(true, interface)) {
- return ret;
- }
maybeModifyQdiscClsact(interface, ACTION_ADD);
updateTableNamesFile();
@@ -1270,10 +1266,7 @@ int RouteController::removeInterfaceFromPhysicalNetwork(unsigned netId, const ch
return ret;
}
- int ret = modifyVpnLocalExclusionRule(false, interface);
- // Always perform flushRoute even if removing local exclusion rules failed.
- ret |= flushRoutes(interface);
- if (ret) {
+ if (int ret = flushRoutes(interface)) {
return ret;
}
@@ -1385,13 +1378,21 @@ int RouteController::disableTethering(const char* inputInterface, const char* ou
int RouteController::addVirtualNetworkFallthrough(unsigned vpnNetId, const char* physicalInterface,
Permission permission) {
- return modifyVpnFallthroughRule(RTM_NEWRULE, vpnNetId, physicalInterface, permission);
+ if (int ret = modifyVpnFallthroughRule(RTM_NEWRULE, vpnNetId, physicalInterface, permission)) {
+ return ret;
+ }
+
+ return modifyVpnLocalExclusionRule(true /* add */, physicalInterface);
}
int RouteController::removeVirtualNetworkFallthrough(unsigned vpnNetId,
const char* physicalInterface,
Permission permission) {
- return modifyVpnFallthroughRule(RTM_DELRULE, vpnNetId, physicalInterface, permission);
+ if (int ret = modifyVpnFallthroughRule(RTM_DELRULE, vpnNetId, physicalInterface, permission)) {
+ return ret;
+ }
+
+ return modifyVpnLocalExclusionRule(false /* add */, physicalInterface);
}
int RouteController::addUsersToPhysicalNetwork(unsigned netId, const char* interface,
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index 519effea..c01d78e9 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -225,7 +225,8 @@ class NetdBinderTest : public ::testing::Test {
unique_fd* acceptedSocket);
void createVpnNetworkWithUid(bool secure, uid_t uid, int vpnNetId = TEST_NETID2,
- int fallthroughNetId = TEST_NETID1);
+ int fallthroughNetId = TEST_NETID1,
+ int nonDefaultNetId = TEST_NETID3);
void createAndSetDefaultNetwork(int netId, const std::string& interface,
int permission = INetd::PERMISSION_NONE);
@@ -3272,18 +3273,26 @@ TEST_F(NetdBinderTest, OemNetdRelated) {
}
void NetdBinderTest::createVpnNetworkWithUid(bool secure, uid_t uid, int vpnNetId,
- int fallthroughNetId) {
+ int fallthroughNetId, int nonDefaultNetId) {
// Re-init sTun* to ensure route rule exists.
sTun.destroy();
sTun.init();
sTun2.destroy();
sTun2.init();
+ sTun3.destroy();
+ sTun3.init();
// Create physical network with fallthroughNetId but not set it as default network
auto config = makeNativeNetworkConfig(fallthroughNetId, NativeNetworkType::PHYSICAL,
INetd::PERMISSION_NONE, false, false);
EXPECT_TRUE(mNetd->networkCreate(config).isOk());
EXPECT_TRUE(mNetd->networkAddInterface(fallthroughNetId, sTun.name()).isOk());
+ // Create a physical network to test that local network access does not include the non-default
+ // networks.
+ auto nonDefaultNetworkConfig = makeNativeNetworkConfig(
+ nonDefaultNetId, NativeNetworkType::PHYSICAL, INetd::PERMISSION_NONE, false, false);
+ EXPECT_TRUE(mNetd->networkCreate(nonDefaultNetworkConfig).isOk());
+ EXPECT_TRUE(mNetd->networkAddInterface(nonDefaultNetId, sTun3.name()).isOk());
// Create VPN with vpnNetId
config.netId = vpnNetId;
@@ -3464,7 +3473,8 @@ void expectVpnFallthroughRuleExists(const std::string& ifName, int vpnNetId) {
void expectVpnFallthroughWorks(android::net::INetd* netdService, bool bypassable, uid_t uid,
const TunInterface& fallthroughNetwork,
- const TunInterface& vpnNetwork, int vpnNetId = TEST_NETID2,
+ const TunInterface& vpnNetwork,
+ const TunInterface& nonDefaultNetwork, int vpnNetId = TEST_NETID2,
int fallthroughNetId = TEST_NETID1) {
// Set default network to NETID_UNSET
EXPECT_TRUE(netdService->networkSetDefault(NETID_UNSET).isOk());
@@ -3499,8 +3509,10 @@ void expectVpnFallthroughWorks(android::net::INetd* netdService, bool bypassable
// Check if fallthrough rule exists
expectVpnFallthroughRuleExists(fallthroughNetwork.name(), vpnNetId);
- // Check if local exclusion rule exists
+ // Check if local exclusion rule exists for default network
expectVpnLocalExclusionRuleExists(fallthroughNetwork.name(), true);
+ // No local exclusion rule for non-default network
+ expectVpnLocalExclusionRuleExists(nonDefaultNetwork.name(), false);
// Expect fallthrough to default network
// The fwmark differs depending on whether the VPN is bypassable or not.
@@ -3548,14 +3560,14 @@ TEST_F(NetdBinderTest, SecureVPNFallthrough) {
createVpnNetworkWithUid(true /* secure */, TEST_UID1);
// Get current default network NetId
ASSERT_TRUE(mNetd->networkGetDefault(&mStoredDefaultNetwork).isOk());
- expectVpnFallthroughWorks(mNetd.get(), false /* bypassable */, TEST_UID1, sTun, sTun2);
+ expectVpnFallthroughWorks(mNetd.get(), false /* bypassable */, TEST_UID1, sTun, sTun2, sTun3);
}
TEST_F(NetdBinderTest, BypassableVPNFallthrough) {
createVpnNetworkWithUid(false /* secure */, TEST_UID1);
// Get current default network NetId
ASSERT_TRUE(mNetd->networkGetDefault(&mStoredDefaultNetwork).isOk());
- expectVpnFallthroughWorks(mNetd.get(), true /* bypassable */, TEST_UID1, sTun, sTun2);
+ expectVpnFallthroughWorks(mNetd.get(), true /* bypassable */, TEST_UID1, sTun, sTun2, sTun3);
}
namespace {