Loading DnsResolver.cpp +2 −8 Original line number Diff line number Diff line Loading @@ -17,26 +17,20 @@ #include "DnsResolver.h" #include <android-base/logging.h> #include <android-base/properties.h> #include "DnsProxyListener.h" #include "DnsResolverService.h" #include "netd_resolv/resolv.h" #include "res_debug.h" #include "util.h" bool resolv_init(const ResolverNetdCallbacks* callbacks) { android::base::InitLogging(/*argv=*/nullptr); android::base::SetDefaultTag("libnetd_resolv"); LOG(INFO) << __func__ << ": Initializing resolver"; resolv_set_log_severity(android::base::WARNING); uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0); uint64_t buildVersionPreviewSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.preview_sdk", 0); uint64_t firstApiLevel = android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0); using android::net::gApiLevel; gApiLevel = std::max(buildVersionSdk + !!buildVersionPreviewSdk, firstApiLevel); gApiLevel = getApiLevel(); using android::net::gResNetdCallbacks; gResNetdCallbacks.check_calling_permission = callbacks->check_calling_permission; gResNetdCallbacks.get_network_context = callbacks->get_network_context; Loading tests/resolv_integration_test.cpp +49 −24 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ #include <aidl/android/net/IDnsResolver.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <util.h> // getApiLevel #include "NetdClient.h" #include "ResolverStats.h" #include "netid_client.h" // NETID_UNSET Loading Loading @@ -162,6 +163,8 @@ class ScopedSystemProperties { std::string mStoredValue; }; const bool isAtLeastR = (getApiLevel() >= 30); } // namespace class ResolverTest : public ::testing::Test { Loading Loading @@ -4120,17 +4123,24 @@ TEST_F(ResolverTest, BlockDnsQueryWithUidRule) { EXPECT_TRUE(fd1 != -1); EXPECT_TRUE(fd2 != -1); uint8_t buf[MAXPACKET] = {}; uint8_t buf1[MAXPACKET] = {}; uint8_t buf2[MAXPACKET] = {}; int rcode; int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); memset(buf, 0, MAXPACKET); res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); int res2 = getAsyncResponse(fd2, &rcode, buf2, MAXPACKET); int res1 = getAsyncResponse(fd1, &rcode, buf1, MAXPACKET); // If API level >= 30 (R+), these queries should be blocked. if (isAtLeastR) { EXPECT_EQ(res2, -ECONNREFUSED); EXPECT_EQ(res1, -ECONNREFUSED); ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {}); ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {}); } else { EXPECT_GT(res2, 0); EXPECT_EQ("::1.2.3.4", toString(buf2, res2, AF_INET6)); EXPECT_GT(res1, 0); EXPECT_EQ("1.2.3.4", toString(buf1, res1, AF_INET)); // To avoid flaky test, do not evaluate DnsEvent since event order is not guaranteed. } } TEST_F(ResolverTest, EnforceDnsUid) { Loading @@ -4156,23 +4166,31 @@ TEST_F(ResolverTest, EnforceDnsUid) { ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk()); uint8_t buf[MAXPACKET] = {}; uint8_t buf2[MAXPACKET] = {}; int rcode; { ScopeBlockedUIDRule scopeBlockUidRule(netdService, TEST_UID); // Dns Queries should be blocked int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0); int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0); const int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0); const int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0); EXPECT_TRUE(fd1 != -1); EXPECT_TRUE(fd2 != -1); int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); memset(buf, 0, MAXPACKET); res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); const int res2 = getAsyncResponse(fd2, &rcode, buf2, MAXPACKET); const int res1 = getAsyncResponse(fd1, &rcode, buf, MAXPACKET); // If API level >= 30 (R+), the query should be blocked. if (isAtLeastR) { EXPECT_EQ(res2, -ECONNREFUSED); EXPECT_EQ(res1, -ECONNREFUSED); } else { EXPECT_GT(res2, 0); EXPECT_EQ("::1.2.3.4", toString(buf2, res2, AF_INET6)); EXPECT_GT(res1, 0); EXPECT_EQ("1.2.3.4", toString(buf, res1, AF_INET)); } } memset(buf, 0, MAXPACKET); parcel.resolverOptions.enforceDnsUid = true; ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk()); { Loading Loading @@ -5168,16 +5186,23 @@ TEST_F(ResolverTest, BlockDnsQueryUidDoesNotLeadToBadServer) { for (int i = 0; i < 10; i++) { std::string hostName = fmt::format("blocked{}.com", i); const addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_DGRAM}; EXPECT_EQ(safe_getaddrinfo(hostName.c_str(), nullptr, &hints), nullptr); // The query result between R+ and Q would be different, but we don't really care // about the result here because this test is only used to ensure blocked uid rule // won't cause bad servers. safe_getaddrinfo(hostName.c_str(), nullptr, &hints); } } // Since all query packets are blocked, we should not see any stats of them. const std::vector<NameserverStats> expectedEmptyDnsStats = { NameserverStats(listen_addr1), ResolverParamsParcel setupParams = DnsResponderClient::GetDefaultResolverParamsParcel(); // If api level >= 30 (R+), expect all query packets to be blocked, hence we should not see any // of their stats show up. Otherwise, all queries should succeed. const std::vector<NameserverStats> expectedDnsStats = { NameserverStats(listen_addr1).setSuccesses(isAtLeastR ? 0 : setupParams.maxSamples), NameserverStats(listen_addr2), }; expectStatsEqualTo(expectedEmptyDnsStats); EXPECT_EQ(dns1.queries().size(), 0U); expectStatsEqualTo(expectedDnsStats); // If api level >= 30 (R+), expect server won't receive any queries, // otherwise expect 20 == 10 * (setupParams.domains.size() + 1) queries. EXPECT_EQ(dns1.queries().size(), isAtLeastR ? 0U : 10 * (setupParams.domains.size() + 1)); EXPECT_EQ(dns2.queries().size(), 0U); } Loading util.h +20 −0 Original line number Diff line number Diff line Loading @@ -21,9 +21,29 @@ #include <netinet/in.h> #include <android-base/properties.h> socklen_t sockaddrSize(const sockaddr* sa); socklen_t sockaddrSize(const sockaddr_storage& ss); // TODO: getExperimentFlagString // TODO: Migrate it to DnsResolverExperiments.cpp int getExperimentFlagInt(const std::string& flagName, int defaultValue); // When sdk X release branch is created, aosp's sdk version would still be X-1, // internal would be X. Also there might be some different setting between real devices and // CF. Below is the example for the sdk related properties in later R development stage. (internal // should be cosidered as S and aosp should be considered as R.) // R version is 30, rvc-dev aosp(CF) aosp(non-CF) internal // ro.build.version.sdk: [30] [29] [29] [30] // Note that, ro.product.first_api_level is device specific - so the value might be various. // ro.product.first_api_level: [26-30] [31] [28] [26-30] // ro.build.version.preview_sdk: [0] [1] [1] [1] inline uint64_t getApiLevel() { uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0); uint64_t buildVersionPreviewSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.preview_sdk", 0); uint64_t firstApiLevel = android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0); return std::max(buildVersionSdk + !!buildVersionPreviewSdk, firstApiLevel); } Loading
DnsResolver.cpp +2 −8 Original line number Diff line number Diff line Loading @@ -17,26 +17,20 @@ #include "DnsResolver.h" #include <android-base/logging.h> #include <android-base/properties.h> #include "DnsProxyListener.h" #include "DnsResolverService.h" #include "netd_resolv/resolv.h" #include "res_debug.h" #include "util.h" bool resolv_init(const ResolverNetdCallbacks* callbacks) { android::base::InitLogging(/*argv=*/nullptr); android::base::SetDefaultTag("libnetd_resolv"); LOG(INFO) << __func__ << ": Initializing resolver"; resolv_set_log_severity(android::base::WARNING); uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0); uint64_t buildVersionPreviewSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.preview_sdk", 0); uint64_t firstApiLevel = android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0); using android::net::gApiLevel; gApiLevel = std::max(buildVersionSdk + !!buildVersionPreviewSdk, firstApiLevel); gApiLevel = getApiLevel(); using android::net::gResNetdCallbacks; gResNetdCallbacks.check_calling_permission = callbacks->check_calling_permission; gResNetdCallbacks.get_network_context = callbacks->get_network_context; Loading
tests/resolv_integration_test.cpp +49 −24 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ #include <aidl/android/net/IDnsResolver.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <util.h> // getApiLevel #include "NetdClient.h" #include "ResolverStats.h" #include "netid_client.h" // NETID_UNSET Loading Loading @@ -162,6 +163,8 @@ class ScopedSystemProperties { std::string mStoredValue; }; const bool isAtLeastR = (getApiLevel() >= 30); } // namespace class ResolverTest : public ::testing::Test { Loading Loading @@ -4120,17 +4123,24 @@ TEST_F(ResolverTest, BlockDnsQueryWithUidRule) { EXPECT_TRUE(fd1 != -1); EXPECT_TRUE(fd2 != -1); uint8_t buf[MAXPACKET] = {}; uint8_t buf1[MAXPACKET] = {}; uint8_t buf2[MAXPACKET] = {}; int rcode; int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); memset(buf, 0, MAXPACKET); res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); int res2 = getAsyncResponse(fd2, &rcode, buf2, MAXPACKET); int res1 = getAsyncResponse(fd1, &rcode, buf1, MAXPACKET); // If API level >= 30 (R+), these queries should be blocked. if (isAtLeastR) { EXPECT_EQ(res2, -ECONNREFUSED); EXPECT_EQ(res1, -ECONNREFUSED); ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {}); ExpectDnsEvent(INetdEventListener::EVENT_RES_NSEND, EAI_SYSTEM, "howdy.example.com", {}); } else { EXPECT_GT(res2, 0); EXPECT_EQ("::1.2.3.4", toString(buf2, res2, AF_INET6)); EXPECT_GT(res1, 0); EXPECT_EQ("1.2.3.4", toString(buf1, res1, AF_INET)); // To avoid flaky test, do not evaluate DnsEvent since event order is not guaranteed. } } TEST_F(ResolverTest, EnforceDnsUid) { Loading @@ -4156,23 +4166,31 @@ TEST_F(ResolverTest, EnforceDnsUid) { ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk()); uint8_t buf[MAXPACKET] = {}; uint8_t buf2[MAXPACKET] = {}; int rcode; { ScopeBlockedUIDRule scopeBlockUidRule(netdService, TEST_UID); // Dns Queries should be blocked int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0); int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0); const int fd1 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_a, 0); const int fd2 = resNetworkQuery(TEST_NETID, host_name, ns_c_in, ns_t_aaaa, 0); EXPECT_TRUE(fd1 != -1); EXPECT_TRUE(fd2 != -1); int res = getAsyncResponse(fd2, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); memset(buf, 0, MAXPACKET); res = getAsyncResponse(fd1, &rcode, buf, MAXPACKET); EXPECT_EQ(-ECONNREFUSED, res); const int res2 = getAsyncResponse(fd2, &rcode, buf2, MAXPACKET); const int res1 = getAsyncResponse(fd1, &rcode, buf, MAXPACKET); // If API level >= 30 (R+), the query should be blocked. if (isAtLeastR) { EXPECT_EQ(res2, -ECONNREFUSED); EXPECT_EQ(res1, -ECONNREFUSED); } else { EXPECT_GT(res2, 0); EXPECT_EQ("::1.2.3.4", toString(buf2, res2, AF_INET6)); EXPECT_GT(res1, 0); EXPECT_EQ("1.2.3.4", toString(buf, res1, AF_INET)); } } memset(buf, 0, MAXPACKET); parcel.resolverOptions.enforceDnsUid = true; ASSERT_TRUE(mDnsClient.resolvService()->setResolverConfiguration(parcel).isOk()); { Loading Loading @@ -5168,16 +5186,23 @@ TEST_F(ResolverTest, BlockDnsQueryUidDoesNotLeadToBadServer) { for (int i = 0; i < 10; i++) { std::string hostName = fmt::format("blocked{}.com", i); const addrinfo hints = {.ai_family = AF_INET, .ai_socktype = SOCK_DGRAM}; EXPECT_EQ(safe_getaddrinfo(hostName.c_str(), nullptr, &hints), nullptr); // The query result between R+ and Q would be different, but we don't really care // about the result here because this test is only used to ensure blocked uid rule // won't cause bad servers. safe_getaddrinfo(hostName.c_str(), nullptr, &hints); } } // Since all query packets are blocked, we should not see any stats of them. const std::vector<NameserverStats> expectedEmptyDnsStats = { NameserverStats(listen_addr1), ResolverParamsParcel setupParams = DnsResponderClient::GetDefaultResolverParamsParcel(); // If api level >= 30 (R+), expect all query packets to be blocked, hence we should not see any // of their stats show up. Otherwise, all queries should succeed. const std::vector<NameserverStats> expectedDnsStats = { NameserverStats(listen_addr1).setSuccesses(isAtLeastR ? 0 : setupParams.maxSamples), NameserverStats(listen_addr2), }; expectStatsEqualTo(expectedEmptyDnsStats); EXPECT_EQ(dns1.queries().size(), 0U); expectStatsEqualTo(expectedDnsStats); // If api level >= 30 (R+), expect server won't receive any queries, // otherwise expect 20 == 10 * (setupParams.domains.size() + 1) queries. EXPECT_EQ(dns1.queries().size(), isAtLeastR ? 0U : 10 * (setupParams.domains.size() + 1)); EXPECT_EQ(dns2.queries().size(), 0U); } Loading
util.h +20 −0 Original line number Diff line number Diff line Loading @@ -21,9 +21,29 @@ #include <netinet/in.h> #include <android-base/properties.h> socklen_t sockaddrSize(const sockaddr* sa); socklen_t sockaddrSize(const sockaddr_storage& ss); // TODO: getExperimentFlagString // TODO: Migrate it to DnsResolverExperiments.cpp int getExperimentFlagInt(const std::string& flagName, int defaultValue); // When sdk X release branch is created, aosp's sdk version would still be X-1, // internal would be X. Also there might be some different setting between real devices and // CF. Below is the example for the sdk related properties in later R development stage. (internal // should be cosidered as S and aosp should be considered as R.) // R version is 30, rvc-dev aosp(CF) aosp(non-CF) internal // ro.build.version.sdk: [30] [29] [29] [30] // Note that, ro.product.first_api_level is device specific - so the value might be various. // ro.product.first_api_level: [26-30] [31] [28] [26-30] // ro.build.version.preview_sdk: [0] [1] [1] [1] inline uint64_t getApiLevel() { uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0); uint64_t buildVersionPreviewSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.preview_sdk", 0); uint64_t firstApiLevel = android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0); return std::max(buildVersionSdk + !!buildVersionPreviewSdk, firstApiLevel); }