Loading Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -400,7 +400,8 @@ rust_ffi_static { "liburl", ], prefer_rlib: true, // For unit tests to run on the Android 10 platform, libunwind must be statically linked.. whole_static_libs: ["libunwind"], apex_available: [ "//apex_available:platform", // Needed by doh_ffi_test "com.android.resolv" Loading tests/resolv_integration_test.cpp +150 −48 Original line number Diff line number Diff line Loading @@ -6427,6 +6427,14 @@ class ResolverMultinetworkTest : public ResolverTest { bool clearDnsConfiguration() const; unsigned netId() const { return mNetId; } std::string name() const { return mNetworkName; } Result<void> addUser(uid_t uid) const { return addUidRange(uid, uid); } Result<void> addUidRange(uid_t from, uid_t to) const { if (auto r = mNetdSrv->networkAddUidRanges(mNetId, {makeUidRangeParcel(from, to)}); !r.isOk()) { return Error() << r.getMessage(); } return {}; } protected: // Subclasses should implement it to decide which network should be create. Loading Loading @@ -6510,14 +6518,6 @@ class ResolverMultinetworkTest : public ResolverTest { mVpnIsolationUids.erase(uid); return {}; } Result<void> addUser(uid_t uid) const { return addUidRange(uid, uid); } Result<void> addUidRange(uid_t from, uid_t to) const { if (auto r = mNetdSrv->networkAddUidRanges(mNetId, {makeUidRangeParcel(from, to)}); !r.isOk()) { return Error() << r.getMessage(); } return {}; } protected: Result<void> createNetwork() const override { Loading Loading @@ -6578,6 +6578,17 @@ class ResolverMultinetworkTest : public ResolverTest { if (mNextNetId == TEST_NETID_BASE + 256) mNextNetId = TEST_NETID_BASE; return mNextNetId++; } Result<std::shared_ptr<test::DNSResponder>> setupDns(ConnectivityType type, ScopedNetwork* nw, const char* host_name, const char* ipv4_addr, const char* ipv6_addr); void expectDnsQueryCountsFn(std::shared_ptr<test::DNSResponder> dnsServer, const char* host_name, size_t count, unsigned expectedDnsNetId) { EXPECT_EQ(GetNumQueries(*dnsServer, host_name), count); EXPECT_TRUE(mDnsClient.resolvService()->flushNetworkCache(expectedDnsNetId).isOk()); dnsServer->clearQueries(); } private: // Use a different netId because this class inherits from the class ResolverTest which Loading Loading @@ -6643,6 +6654,21 @@ void ResolverMultinetworkTest::StartDns(test::DNSResponder& dns, } } Result<std::shared_ptr<test::DNSResponder>> ResolverMultinetworkTest::setupDns( ConnectivityType type, ScopedNetwork* nw, const char* host_name, const char* ipv4_addr, const char* ipv6_addr) { // Add a testing DNS server to networks. const Result<DnsServerPair> dnsSvPair = (type == ConnectivityType::V4) ? nw->addIpv4Dns() : nw->addIpv6Dns(); if (!dnsSvPair.ok()) return Error() << dnsSvPair.error(); StartDns(*dnsSvPair->dnsServer, {{host_name, ns_type::ns_t_a, ipv4_addr}, {host_name, ns_type::ns_t_aaaa, ipv6_addr}}); if (!nw->setDnsConfiguration()) return Error() << "setDnsConfiguration() failed"; if (!nw->startTunForwarder()) return Error() << "startTunForwarder() failed"; return dnsSvPair->dnsServer; } Result<ResolverMultinetworkTest::DnsServerPair> ResolverMultinetworkTest::ScopedNetwork::addDns( ConnectivityType type) { const int index = mDnsServerPairs.size(); Loading Loading @@ -6875,30 +6901,15 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { ASSERT_RESULT_OK(bypassableVpnNetwork.addUser(TEST_UID)); ASSERT_RESULT_OK(secureVpnNetwork.addUser(TEST_UID2)); auto setupDnsFn = [&](std::shared_ptr<test::DNSResponder> dnsServer, ScopedNetwork* nw) -> void { StartDns(*dnsServer, {{host_name, ns_type::ns_t_a, ipv4_addr}, {host_name, ns_type::ns_t_aaaa, ipv6_addr}}); ASSERT_TRUE(nw->setDnsConfiguration()); ASSERT_TRUE(nw->startTunForwarder()); }; // Add a testing DNS server to networks. const Result<DnsServerPair> underlyingPair = (type == ConnectivityType::V4) ? underlyingNetwork.addIpv4Dns() : underlyingNetwork.addIpv6Dns(); ASSERT_RESULT_OK(underlyingPair); const Result<DnsServerPair> bypassableVpnPair = (type == ConnectivityType::V4) ? bypassableVpnNetwork.addIpv4Dns() : bypassableVpnNetwork.addIpv6Dns(); ASSERT_RESULT_OK(bypassableVpnPair); const Result<DnsServerPair> secureVpnPair = (type == ConnectivityType::V4) ? secureVpnNetwork.addIpv4Dns() : secureVpnNetwork.addIpv6Dns(); ASSERT_RESULT_OK(secureVpnPair); // Set up resolver and start forwarding for networks. setupDnsFn(underlyingPair->dnsServer, &underlyingNetwork); setupDnsFn(bypassableVpnPair->dnsServer, &bypassableVpnNetwork); setupDnsFn(secureVpnPair->dnsServer, &secureVpnNetwork); auto underlyingNwDnsSv = setupDns(type, &underlyingNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(underlyingNwDnsSv); auto bypassableVpnDnsSv = setupDns(type, &bypassableVpnNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(bypassableVpnDnsSv); auto secureVpnDnsSv = setupDns(type, &secureVpnNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(secureVpnDnsSv); setDefaultNetwork(underlyingNetwork.netId()); const unsigned underlyingNetId = underlyingNetwork.netId(); Loading @@ -6906,15 +6917,6 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { const unsigned secureVpnNetId = secureVpnNetwork.netId(); // We've called setNetworkForProcess in SetupOemNetwork, so reset to default first. ScopedSetNetworkForProcess scopedSetNetworkForProcess(NETID_UNSET); auto expectDnsQueryCountsFn = [&](size_t count, std::shared_ptr<test::DNSResponder> dnsServer, unsigned expectedDnsNetId) -> void { EXPECT_EQ(GetNumQueries(*dnsServer, host_name), count); EXPECT_TRUE(mDnsClient.resolvService()->flushNetworkCache(expectedDnsNetId).isOk()); dnsServer->clearQueries(); // Give DnsResolver some time to clear cache to avoid race. usleep(5 * 1000); }; // Create a object to represent default network, do not init it. ScopedPhysicalNetwork defaultNetwork{NETID_UNSET, "Default"}; Loading @@ -6928,20 +6930,20 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { } vpnWithDnsServerConfigs[]{ // clang-format off // Queries use the bypassable VPN by default. {&defaultNetwork, bypassableVpnNetId, bypassableVpnPair->dnsServer}, {&defaultNetwork, bypassableVpnNetId, *bypassableVpnDnsSv}, // Choosing the underlying network works because the VPN is bypassable. {&underlyingNetwork, underlyingNetId, underlyingPair->dnsServer}, {&underlyingNetwork, underlyingNetId, *underlyingNwDnsSv}, // Selecting the VPN sends the query on the VPN. {&bypassableVpnNetwork, bypassableVpnNetId, bypassableVpnPair->dnsServer}, {&bypassableVpnNetwork, bypassableVpnNetId, *bypassableVpnDnsSv}, // TEST_UID does not have access to the secure VPN. {&secureVpnNetwork, bypassableVpnNetId, bypassableVpnPair->dnsServer}, {&secureVpnNetwork, bypassableVpnNetId, *bypassableVpnDnsSv}, // clang-format on }; for (const auto& config : vpnWithDnsServerConfigs) { SCOPED_TRACE(fmt::format("Bypassble VPN with DnsServer, selectedNetwork = {}", config.selectedNetwork->name())); expectDnsWorksForUid(host_name, config.selectedNetwork->netId(), TEST_UID, result); expectDnsQueryCountsFn(result.size(), config.expectedDnsServer, expectDnsQueryCountsFn(config.expectedDnsServer, host_name, result.size(), config.expectedDnsNetId); } Loading @@ -6954,7 +6956,7 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { SCOPED_TRACE(fmt::format("Bypassble VPN without DnsServer, selectedNetwork = {}", selectedNetwork->name())); expectDnsWorksForUid(host_name, selectedNetwork->netId(), TEST_UID, result); expectDnsQueryCountsFn(result.size(), underlyingPair->dnsServer, underlyingNetId); expectDnsQueryCountsFn(*underlyingNwDnsSv, host_name, result.size(), underlyingNetId); } // The same test scenario as before plus enableVpnIsolation for secure VPN, TEST_UID2. Loading @@ -6970,7 +6972,8 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { SCOPED_TRACE(fmt::format("Secure VPN without DnsServer, selectedNetwork = {}", selectedNetwork->name())); expectDnsWorksForUid(host_name, selectedNetwork->netId(), TEST_UID2, result); expectDnsQueryCountsFn(result.size(), underlyingPair->dnsServer, underlyingNetId); expectDnsQueryCountsFn(*underlyingNwDnsSv, host_name, result.size(), underlyingNetId); } // Test secure VPN with DNS server. Loading @@ -6979,7 +6982,7 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { SCOPED_TRACE(fmt::format("Secure VPN with DnsServer, selectedNetwork = {}", selectedNetwork->name())); expectDnsWorksForUid(host_name, selectedNetwork->netId(), TEST_UID2, result); expectDnsQueryCountsFn(result.size(), secureVpnPair->dnsServer, secureVpnNetId); expectDnsQueryCountsFn(*secureVpnDnsSv, host_name, result.size(), secureVpnNetId); } if (enableVpnIsolation) { Loading @@ -6988,3 +6991,102 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { } } } // verify per-application default network selection on DNS. TEST_F(ResolverMultinetworkTest, PerAppDefaultNetwork) { // Netd supports uid ranges on physical network from v6. SKIP_IF_REMOTE_VERSION_LESS_THAN(mDnsClient.netdService(), 6); constexpr char host_name[] = "ohayou.example.com."; constexpr char ipv4_addr[] = "192.0.2.0"; constexpr char ipv6_addr[] = "2001:db8:cafe:d00d::31"; const std::pair<ConnectivityType, std::vector<std::string>> testPairs[] = { {ConnectivityType::V4, {ipv4_addr}}, {ConnectivityType::V6, {ipv6_addr}}, {ConnectivityType::V4V6, {ipv6_addr, ipv4_addr}}, }; for (const auto& [ipVersion, expectedDnsReply] : testPairs) { SCOPED_TRACE(StringPrintf("ConnectivityType: %d", ipVersion)); // Create networks. ScopedPhysicalNetwork sysDefaultNetwork = CreateScopedPhysicalNetwork(ipVersion, "SysDefault"); ScopedPhysicalNetwork appDefaultNetwork = CreateScopedPhysicalNetwork(ipVersion, "AppDefault"); ScopedVirtualNetwork vpn = CreateScopedVirtualNetwork(ipVersion, false, "Vpn"); ASSERT_RESULT_OK(sysDefaultNetwork.init()); ASSERT_RESULT_OK(appDefaultNetwork.init()); ASSERT_RESULT_OK(vpn.init()); // Set up resolver and start forwarding for networks. auto sysDefaultNwDnsSv = setupDns(ipVersion, &sysDefaultNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(sysDefaultNwDnsSv); auto appDefaultNwDnsSv = setupDns(ipVersion, &appDefaultNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(appDefaultNwDnsSv); auto vpnDnsSv = setupDns(ipVersion, &vpn, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(vpnDnsSv); const unsigned systemDefaultNetId = sysDefaultNetwork.netId(); const unsigned appDefaultNetId = appDefaultNetwork.netId(); const unsigned vpnNetId = vpn.netId(); setDefaultNetwork(systemDefaultNetId); EXPECT_TRUE( mDnsClient.netdService() ->networkSetPermissionForNetwork(appDefaultNetId, INetd::PERMISSION_SYSTEM) .isOk()); // We've called setNetworkForProcess in SetupOemNetwork, reset to default first. ScopedSetNetworkForProcess scopedSetNetworkForProcess(NETID_UNSET); // Test DNS query without selecting a network. --> use system default network. expectDnsWorksForUid(host_name, NETID_UNSET, TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*sysDefaultNwDnsSv, host_name, expectedDnsReply.size(), systemDefaultNetId); // Add user to app default network. --> use app default network. ASSERT_RESULT_OK(appDefaultNetwork.addUser(TEST_UID)); expectDnsWorksForUid(host_name, NETID_UNSET, TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*appDefaultNwDnsSv, host_name, expectedDnsReply.size(), appDefaultNetId); // Test DNS query with a selected network. // App default network applies to uid, vpn does not applies to uid. const struct TestConfig { ScopedNetwork* selectedNetwork; unsigned expectedDnsNetId; std::shared_ptr<test::DNSResponder> expectedDnsServer; } vpnWithDnsServerConfigs[]{ // clang-format off // App can select the system default network without any permission. {&sysDefaultNetwork, systemDefaultNetId, *sysDefaultNwDnsSv}, // App can select the restricted network, since its uid was assigned to the network. {&appDefaultNetwork, appDefaultNetId, *appDefaultNwDnsSv}, // App does not have access to the VPN. --> fallback to app default network. {&vpn, appDefaultNetId, *appDefaultNwDnsSv}, // clang-format on }; for (const auto& config : vpnWithDnsServerConfigs) { SCOPED_TRACE(fmt::format("Dns over app default network, selectedNetwork = {}", config.selectedNetwork->name())); expectDnsWorksForUid(host_name, config.selectedNetwork->netId(), TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(config.expectedDnsServer, host_name, expectedDnsReply.size(), config.expectedDnsNetId); } // App default network applies to uid, vpn applies to uid. --> use vpn. ASSERT_RESULT_OK(vpn.addUser(TEST_UID)); expectDnsWorksForUid(host_name, vpn.netId(), TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*vpnDnsSv, host_name, expectedDnsReply.size(), vpnNetId); // vpn without server. --> fallback to app default network. ASSERT_TRUE(vpn.clearDnsConfiguration()); expectDnsWorksForUid(host_name, vpn.netId(), TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*appDefaultNwDnsSv, host_name, expectedDnsReply.size(), appDefaultNetId); } } Loading
Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -400,7 +400,8 @@ rust_ffi_static { "liburl", ], prefer_rlib: true, // For unit tests to run on the Android 10 platform, libunwind must be statically linked.. whole_static_libs: ["libunwind"], apex_available: [ "//apex_available:platform", // Needed by doh_ffi_test "com.android.resolv" Loading
tests/resolv_integration_test.cpp +150 −48 Original line number Diff line number Diff line Loading @@ -6427,6 +6427,14 @@ class ResolverMultinetworkTest : public ResolverTest { bool clearDnsConfiguration() const; unsigned netId() const { return mNetId; } std::string name() const { return mNetworkName; } Result<void> addUser(uid_t uid) const { return addUidRange(uid, uid); } Result<void> addUidRange(uid_t from, uid_t to) const { if (auto r = mNetdSrv->networkAddUidRanges(mNetId, {makeUidRangeParcel(from, to)}); !r.isOk()) { return Error() << r.getMessage(); } return {}; } protected: // Subclasses should implement it to decide which network should be create. Loading Loading @@ -6510,14 +6518,6 @@ class ResolverMultinetworkTest : public ResolverTest { mVpnIsolationUids.erase(uid); return {}; } Result<void> addUser(uid_t uid) const { return addUidRange(uid, uid); } Result<void> addUidRange(uid_t from, uid_t to) const { if (auto r = mNetdSrv->networkAddUidRanges(mNetId, {makeUidRangeParcel(from, to)}); !r.isOk()) { return Error() << r.getMessage(); } return {}; } protected: Result<void> createNetwork() const override { Loading Loading @@ -6578,6 +6578,17 @@ class ResolverMultinetworkTest : public ResolverTest { if (mNextNetId == TEST_NETID_BASE + 256) mNextNetId = TEST_NETID_BASE; return mNextNetId++; } Result<std::shared_ptr<test::DNSResponder>> setupDns(ConnectivityType type, ScopedNetwork* nw, const char* host_name, const char* ipv4_addr, const char* ipv6_addr); void expectDnsQueryCountsFn(std::shared_ptr<test::DNSResponder> dnsServer, const char* host_name, size_t count, unsigned expectedDnsNetId) { EXPECT_EQ(GetNumQueries(*dnsServer, host_name), count); EXPECT_TRUE(mDnsClient.resolvService()->flushNetworkCache(expectedDnsNetId).isOk()); dnsServer->clearQueries(); } private: // Use a different netId because this class inherits from the class ResolverTest which Loading Loading @@ -6643,6 +6654,21 @@ void ResolverMultinetworkTest::StartDns(test::DNSResponder& dns, } } Result<std::shared_ptr<test::DNSResponder>> ResolverMultinetworkTest::setupDns( ConnectivityType type, ScopedNetwork* nw, const char* host_name, const char* ipv4_addr, const char* ipv6_addr) { // Add a testing DNS server to networks. const Result<DnsServerPair> dnsSvPair = (type == ConnectivityType::V4) ? nw->addIpv4Dns() : nw->addIpv6Dns(); if (!dnsSvPair.ok()) return Error() << dnsSvPair.error(); StartDns(*dnsSvPair->dnsServer, {{host_name, ns_type::ns_t_a, ipv4_addr}, {host_name, ns_type::ns_t_aaaa, ipv6_addr}}); if (!nw->setDnsConfiguration()) return Error() << "setDnsConfiguration() failed"; if (!nw->startTunForwarder()) return Error() << "startTunForwarder() failed"; return dnsSvPair->dnsServer; } Result<ResolverMultinetworkTest::DnsServerPair> ResolverMultinetworkTest::ScopedNetwork::addDns( ConnectivityType type) { const int index = mDnsServerPairs.size(); Loading Loading @@ -6875,30 +6901,15 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { ASSERT_RESULT_OK(bypassableVpnNetwork.addUser(TEST_UID)); ASSERT_RESULT_OK(secureVpnNetwork.addUser(TEST_UID2)); auto setupDnsFn = [&](std::shared_ptr<test::DNSResponder> dnsServer, ScopedNetwork* nw) -> void { StartDns(*dnsServer, {{host_name, ns_type::ns_t_a, ipv4_addr}, {host_name, ns_type::ns_t_aaaa, ipv6_addr}}); ASSERT_TRUE(nw->setDnsConfiguration()); ASSERT_TRUE(nw->startTunForwarder()); }; // Add a testing DNS server to networks. const Result<DnsServerPair> underlyingPair = (type == ConnectivityType::V4) ? underlyingNetwork.addIpv4Dns() : underlyingNetwork.addIpv6Dns(); ASSERT_RESULT_OK(underlyingPair); const Result<DnsServerPair> bypassableVpnPair = (type == ConnectivityType::V4) ? bypassableVpnNetwork.addIpv4Dns() : bypassableVpnNetwork.addIpv6Dns(); ASSERT_RESULT_OK(bypassableVpnPair); const Result<DnsServerPair> secureVpnPair = (type == ConnectivityType::V4) ? secureVpnNetwork.addIpv4Dns() : secureVpnNetwork.addIpv6Dns(); ASSERT_RESULT_OK(secureVpnPair); // Set up resolver and start forwarding for networks. setupDnsFn(underlyingPair->dnsServer, &underlyingNetwork); setupDnsFn(bypassableVpnPair->dnsServer, &bypassableVpnNetwork); setupDnsFn(secureVpnPair->dnsServer, &secureVpnNetwork); auto underlyingNwDnsSv = setupDns(type, &underlyingNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(underlyingNwDnsSv); auto bypassableVpnDnsSv = setupDns(type, &bypassableVpnNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(bypassableVpnDnsSv); auto secureVpnDnsSv = setupDns(type, &secureVpnNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(secureVpnDnsSv); setDefaultNetwork(underlyingNetwork.netId()); const unsigned underlyingNetId = underlyingNetwork.netId(); Loading @@ -6906,15 +6917,6 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { const unsigned secureVpnNetId = secureVpnNetwork.netId(); // We've called setNetworkForProcess in SetupOemNetwork, so reset to default first. ScopedSetNetworkForProcess scopedSetNetworkForProcess(NETID_UNSET); auto expectDnsQueryCountsFn = [&](size_t count, std::shared_ptr<test::DNSResponder> dnsServer, unsigned expectedDnsNetId) -> void { EXPECT_EQ(GetNumQueries(*dnsServer, host_name), count); EXPECT_TRUE(mDnsClient.resolvService()->flushNetworkCache(expectedDnsNetId).isOk()); dnsServer->clearQueries(); // Give DnsResolver some time to clear cache to avoid race. usleep(5 * 1000); }; // Create a object to represent default network, do not init it. ScopedPhysicalNetwork defaultNetwork{NETID_UNSET, "Default"}; Loading @@ -6928,20 +6930,20 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { } vpnWithDnsServerConfigs[]{ // clang-format off // Queries use the bypassable VPN by default. {&defaultNetwork, bypassableVpnNetId, bypassableVpnPair->dnsServer}, {&defaultNetwork, bypassableVpnNetId, *bypassableVpnDnsSv}, // Choosing the underlying network works because the VPN is bypassable. {&underlyingNetwork, underlyingNetId, underlyingPair->dnsServer}, {&underlyingNetwork, underlyingNetId, *underlyingNwDnsSv}, // Selecting the VPN sends the query on the VPN. {&bypassableVpnNetwork, bypassableVpnNetId, bypassableVpnPair->dnsServer}, {&bypassableVpnNetwork, bypassableVpnNetId, *bypassableVpnDnsSv}, // TEST_UID does not have access to the secure VPN. {&secureVpnNetwork, bypassableVpnNetId, bypassableVpnPair->dnsServer}, {&secureVpnNetwork, bypassableVpnNetId, *bypassableVpnDnsSv}, // clang-format on }; for (const auto& config : vpnWithDnsServerConfigs) { SCOPED_TRACE(fmt::format("Bypassble VPN with DnsServer, selectedNetwork = {}", config.selectedNetwork->name())); expectDnsWorksForUid(host_name, config.selectedNetwork->netId(), TEST_UID, result); expectDnsQueryCountsFn(result.size(), config.expectedDnsServer, expectDnsQueryCountsFn(config.expectedDnsServer, host_name, result.size(), config.expectedDnsNetId); } Loading @@ -6954,7 +6956,7 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { SCOPED_TRACE(fmt::format("Bypassble VPN without DnsServer, selectedNetwork = {}", selectedNetwork->name())); expectDnsWorksForUid(host_name, selectedNetwork->netId(), TEST_UID, result); expectDnsQueryCountsFn(result.size(), underlyingPair->dnsServer, underlyingNetId); expectDnsQueryCountsFn(*underlyingNwDnsSv, host_name, result.size(), underlyingNetId); } // The same test scenario as before plus enableVpnIsolation for secure VPN, TEST_UID2. Loading @@ -6970,7 +6972,8 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { SCOPED_TRACE(fmt::format("Secure VPN without DnsServer, selectedNetwork = {}", selectedNetwork->name())); expectDnsWorksForUid(host_name, selectedNetwork->netId(), TEST_UID2, result); expectDnsQueryCountsFn(result.size(), underlyingPair->dnsServer, underlyingNetId); expectDnsQueryCountsFn(*underlyingNwDnsSv, host_name, result.size(), underlyingNetId); } // Test secure VPN with DNS server. Loading @@ -6979,7 +6982,7 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { SCOPED_TRACE(fmt::format("Secure VPN with DnsServer, selectedNetwork = {}", selectedNetwork->name())); expectDnsWorksForUid(host_name, selectedNetwork->netId(), TEST_UID2, result); expectDnsQueryCountsFn(result.size(), secureVpnPair->dnsServer, secureVpnNetId); expectDnsQueryCountsFn(*secureVpnDnsSv, host_name, result.size(), secureVpnNetId); } if (enableVpnIsolation) { Loading @@ -6988,3 +6991,102 @@ TEST_F(ResolverMultinetworkTest, DnsWithVpn) { } } } // verify per-application default network selection on DNS. TEST_F(ResolverMultinetworkTest, PerAppDefaultNetwork) { // Netd supports uid ranges on physical network from v6. SKIP_IF_REMOTE_VERSION_LESS_THAN(mDnsClient.netdService(), 6); constexpr char host_name[] = "ohayou.example.com."; constexpr char ipv4_addr[] = "192.0.2.0"; constexpr char ipv6_addr[] = "2001:db8:cafe:d00d::31"; const std::pair<ConnectivityType, std::vector<std::string>> testPairs[] = { {ConnectivityType::V4, {ipv4_addr}}, {ConnectivityType::V6, {ipv6_addr}}, {ConnectivityType::V4V6, {ipv6_addr, ipv4_addr}}, }; for (const auto& [ipVersion, expectedDnsReply] : testPairs) { SCOPED_TRACE(StringPrintf("ConnectivityType: %d", ipVersion)); // Create networks. ScopedPhysicalNetwork sysDefaultNetwork = CreateScopedPhysicalNetwork(ipVersion, "SysDefault"); ScopedPhysicalNetwork appDefaultNetwork = CreateScopedPhysicalNetwork(ipVersion, "AppDefault"); ScopedVirtualNetwork vpn = CreateScopedVirtualNetwork(ipVersion, false, "Vpn"); ASSERT_RESULT_OK(sysDefaultNetwork.init()); ASSERT_RESULT_OK(appDefaultNetwork.init()); ASSERT_RESULT_OK(vpn.init()); // Set up resolver and start forwarding for networks. auto sysDefaultNwDnsSv = setupDns(ipVersion, &sysDefaultNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(sysDefaultNwDnsSv); auto appDefaultNwDnsSv = setupDns(ipVersion, &appDefaultNetwork, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(appDefaultNwDnsSv); auto vpnDnsSv = setupDns(ipVersion, &vpn, host_name, ipv4_addr, ipv6_addr); ASSERT_RESULT_OK(vpnDnsSv); const unsigned systemDefaultNetId = sysDefaultNetwork.netId(); const unsigned appDefaultNetId = appDefaultNetwork.netId(); const unsigned vpnNetId = vpn.netId(); setDefaultNetwork(systemDefaultNetId); EXPECT_TRUE( mDnsClient.netdService() ->networkSetPermissionForNetwork(appDefaultNetId, INetd::PERMISSION_SYSTEM) .isOk()); // We've called setNetworkForProcess in SetupOemNetwork, reset to default first. ScopedSetNetworkForProcess scopedSetNetworkForProcess(NETID_UNSET); // Test DNS query without selecting a network. --> use system default network. expectDnsWorksForUid(host_name, NETID_UNSET, TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*sysDefaultNwDnsSv, host_name, expectedDnsReply.size(), systemDefaultNetId); // Add user to app default network. --> use app default network. ASSERT_RESULT_OK(appDefaultNetwork.addUser(TEST_UID)); expectDnsWorksForUid(host_name, NETID_UNSET, TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*appDefaultNwDnsSv, host_name, expectedDnsReply.size(), appDefaultNetId); // Test DNS query with a selected network. // App default network applies to uid, vpn does not applies to uid. const struct TestConfig { ScopedNetwork* selectedNetwork; unsigned expectedDnsNetId; std::shared_ptr<test::DNSResponder> expectedDnsServer; } vpnWithDnsServerConfigs[]{ // clang-format off // App can select the system default network without any permission. {&sysDefaultNetwork, systemDefaultNetId, *sysDefaultNwDnsSv}, // App can select the restricted network, since its uid was assigned to the network. {&appDefaultNetwork, appDefaultNetId, *appDefaultNwDnsSv}, // App does not have access to the VPN. --> fallback to app default network. {&vpn, appDefaultNetId, *appDefaultNwDnsSv}, // clang-format on }; for (const auto& config : vpnWithDnsServerConfigs) { SCOPED_TRACE(fmt::format("Dns over app default network, selectedNetwork = {}", config.selectedNetwork->name())); expectDnsWorksForUid(host_name, config.selectedNetwork->netId(), TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(config.expectedDnsServer, host_name, expectedDnsReply.size(), config.expectedDnsNetId); } // App default network applies to uid, vpn applies to uid. --> use vpn. ASSERT_RESULT_OK(vpn.addUser(TEST_UID)); expectDnsWorksForUid(host_name, vpn.netId(), TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*vpnDnsSv, host_name, expectedDnsReply.size(), vpnNetId); // vpn without server. --> fallback to app default network. ASSERT_TRUE(vpn.clearDnsConfiguration()); expectDnsWorksForUid(host_name, vpn.netId(), TEST_UID, expectedDnsReply); expectDnsQueryCountsFn(*appDefaultNwDnsSv, host_name, expectedDnsReply.size(), appDefaultNetId); } }