summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-10-21 18:05:53 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-10-21 18:05:53 +0000
commit19d9dd4a04e12a9b19019ed5668f560733907b82 (patch)
tree19b5d316488e0ef31bc7a293f0b66929094bbe97
parenta4a25fe8abc7cd8cd3bfe213b4b867a4fa194385 (diff)
parentac72fc56126dbc1d65592325ef21080bdf487524 (diff)
downloadnetd-android10-android13-mainline-tzdata-release.tar.gz
Change-Id: I29eaa5c8c59e2b7b5cdc35e2d5d1b4adeadc64c3
-rw-r--r--resolv/libnetd_resolv_test.cpp140
-rw-r--r--resolv/res_cache.cpp9
-rw-r--r--resolv/res_send.cpp5
-rw-r--r--server/AndroidTest.xml1
4 files changed, 148 insertions, 7 deletions
diff --git a/resolv/libnetd_resolv_test.cpp b/resolv/libnetd_resolv_test.cpp
index 6e4b9eec..f961e790 100644
--- a/resolv/libnetd_resolv_test.cpp
+++ b/resolv/libnetd_resolv_test.cpp
@@ -19,18 +19,24 @@
#include <gtest/gtest.h>
#include <android-base/stringprintf.h>
+#include <android/multinetwork.h> // ResNsendFlags
#include <arpa/inet.h>
+#include <arpa/nameser.h>
#include <netdb.h>
+#include <resolv.h>
#include "dns_responder.h"
#include "getaddrinfo.h"
#include "gethnamaddr.h"
+#include "res_send.h"
#include "resolv_cache.h"
#include "stats.pb.h"
// TODO: make this dynamic and stop depending on implementation details.
constexpr unsigned int TEST_NETID = 30;
+constexpr int MAXPACKET = (8 * 1024);
+
// Specifying 0 in ai_socktype or ai_protocol of struct addrinfo indicates that any type or
// protocol can be returned by getaddrinfo().
constexpr unsigned int ANY = 0;
@@ -473,6 +479,140 @@ TEST_F(GetAddrInfoForNetContextTest, ServerTimeout) {
if (result) freeaddrinfo(result);
}
+namespace {
+
+std::string toString(uint8_t* buf, int bufLen, int ipType) {
+ ns_msg handle;
+ int ancount, n = 0;
+ ns_rr rr;
+
+ if (ns_initparse((const uint8_t*)buf, bufLen, &handle) >= 0) {
+ ancount = ns_msg_count(handle, ns_s_an);
+ if (ns_parserr(&handle, ns_s_an, n, &rr) == 0) {
+ const uint8_t* rdata = ns_rr_rdata(rr);
+ char buffer[INET6_ADDRSTRLEN];
+ if (inet_ntop(ipType, (const char*)rdata, buffer, sizeof(buffer))) {
+ return buffer;
+ }
+ }
+ }
+ return "";
+}
+
+std::string resolvResNsendHelper(const android_net_context* _Nonnull netContext, const char* host,
+ int nsType, int flag) {
+ std::vector<uint8_t> ansBuf(MAXPACKET, 0);
+ int rcode = ns_r_noerror;
+ std::vector<uint8_t> msg(MAXPACKET, 0);
+ const int msgLen = res_mkquery(ns_o_query, host, ns_c_in, nsType, nullptr, 0, nullptr,
+ msg.data(), MAXPACKET);
+ NetworkDnsEventReported event;
+ const int nsendAns = resolv_res_nsend(netContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET,
+ &rcode, static_cast<ResNsendFlags>(flag), &event);
+ return toString(ansBuf.data(), nsendAns, (nsType == ns_t_a) ? AF_INET : AF_INET6);
+}
+
+} // namespace
+
+TEST_F(GetAddrInfoForNetContextTest, Async_CacheFlags) {
+ constexpr char listen_addr[] = "127.0.0.3";
+ constexpr char listen_srv[] = "53";
+ constexpr char host1[] = "howdy.example.com.";
+ constexpr char host2[] = "howdy.example2.com.";
+ constexpr char host3[] = "howdy.example3.com.";
+ test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
+ dns.addMapping(host1, ns_type::ns_t_a, "1.2.3.4");
+ dns.addMapping(host3, ns_type::ns_t_a, "1.2.3.6");
+ dns.addMapping(host2, ns_type::ns_t_aaaa, "::1.2.3.5");
+ dns.addMapping(host3, ns_type::ns_t_aaaa, "::1.2.3.6");
+ ASSERT_TRUE(dns.startServer());
+ const char* servers[] = {listen_addr};
+ ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
+ sizeof(servers) / sizeof(servers[0]),
+ mDefaultSearchDomains, &mDefaultParams_Binder));
+
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, ANDROID_RESOLV_NO_CACHE_STORE),
+ "1.2.3.4");
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, ANDROID_RESOLV_NO_CACHE_STORE),
+ "1.2.3.4");
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, ANDROID_RESOLV_NO_CACHE_STORE),
+ "1.2.3.4");
+
+ // No cache exists, expect 3 queries
+ EXPECT_EQ(3U, GetNumQueries(dns, host1)); // no query because of the cache
+
+ // Raise a query with no flags to ensure no cache exists. Also make an cache entry for the
+ // query.
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, 0), "1.2.3.4");
+
+ // Expect 4 queries because there should be no cache before this query.
+ EXPECT_EQ(4U, GetNumQueries(dns, host1));
+
+ // Now we have the cache entry, re-query with ANDROID_RESOLV_NO_CACHE_STORE to ensure
+ // that ANDROID_RESOLV_NO_CACHE_STORE implied ANDROID_RESOLV_NO_CACHE_LOOKUP.
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, ANDROID_RESOLV_NO_CACHE_STORE),
+ "1.2.3.4");
+
+ // Expect 5 queries because we shouldn't do cache lookup for the query which has
+ // ANDROID_RESOLV_NO_CACHE_STORE.
+ EXPECT_EQ(5U, GetNumQueries(dns, host1));
+
+ // ANDROID_RESOLV_NO_CACHE_LOOKUP
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, ANDROID_RESOLV_NO_CACHE_LOOKUP),
+ "1.2.3.4");
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, ANDROID_RESOLV_NO_CACHE_LOOKUP),
+ "1.2.3.4");
+
+ // Cache was skipped, expect 2 more queries.
+ EXPECT_EQ(7U, GetNumQueries(dns, host1));
+
+ // Re-query verify cache works
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host1, ns_t_a, 0), "1.2.3.4");
+
+ // Cache hits, expect still 7 queries
+ EXPECT_EQ(7U, GetNumQueries(dns, host1));
+
+ // Start to verify if ANDROID_RESOLV_NO_CACHE_LOOKUP does write response into cache
+ dns.clearQueries();
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host2, ns_t_aaaa, ANDROID_RESOLV_NO_CACHE_LOOKUP),
+ "::1.2.3.5");
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host2, ns_t_aaaa, ANDROID_RESOLV_NO_CACHE_LOOKUP),
+ "::1.2.3.5");
+
+ // Skip cache, expect 2 queries
+ EXPECT_EQ(2U, GetNumQueries(dns, host2));
+
+ // Re-query without flags
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host2, ns_t_aaaa, 0), "::1.2.3.5");
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host2, ns_t_aaaa, 0), "::1.2.3.5");
+
+ // Cache hits, expect still 2 queries
+ EXPECT_EQ(2U, GetNumQueries(dns, host2));
+
+ // Test both ANDROID_RESOLV_NO_CACHE_STORE and ANDROID_RESOLV_NO_CACHE_LOOKUP are set
+ dns.clearQueries();
+
+ // Make sure that the cache of "howdy.example3.com" exists.
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host3, ns_t_aaaa, 0), "::1.2.3.6");
+ EXPECT_EQ(1U, GetNumQueries(dns, host3));
+
+ // Re-query with testFlags
+ const int testFlag = ANDROID_RESOLV_NO_CACHE_STORE | ANDROID_RESOLV_NO_CACHE_LOOKUP;
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host3, ns_t_aaaa, testFlag), "::1.2.3.6");
+ // Expect cache lookup is skipped.
+ EXPECT_EQ(2U, GetNumQueries(dns, host3));
+
+ // Do another query with testFlags
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host3, ns_t_a, testFlag), "1.2.3.6");
+ // Expect cache lookup is skipped.
+ EXPECT_EQ(3U, GetNumQueries(dns, host3));
+
+ // Re-query with no flags
+ EXPECT_EQ(resolvResNsendHelper(&mNetcontext, host3, ns_t_a, testFlag), "1.2.3.6");
+ // Expect no cache hit because cache storing is also skipped in previous query.
+ EXPECT_EQ(4U, GetNumQueries(dns, host3));
+}
+
TEST_F(GetHostByNameForNetContextTest, AlphabeticalHostname) {
constexpr char listen_addr[] = "127.0.0.3";
constexpr char listen_srv[] = "53";
diff --git a/resolv/res_cache.cpp b/resolv/res_cache.cpp
index d6f0cd80..879ddbb4 100644
--- a/resolv/res_cache.cpp
+++ b/resolv/res_cache.cpp
@@ -1423,7 +1423,9 @@ ResolvCacheStatus _resolv_cache_lookup(unsigned netid, const void* query, int qu
// possible to cache the answer of this query.
// If ANDROID_RESOLV_NO_CACHE_STORE is set, return RESOLV_CACHE_SKIP to skip possible cache
// storing.
- if (flags & ANDROID_RESOLV_NO_CACHE_LOOKUP) {
+ // (b/150371903): ANDROID_RESOLV_NO_CACHE_STORE should imply ANDROID_RESOLV_NO_CACHE_LOOKUP
+ // to avoid side channel attack.
+ if (flags & (ANDROID_RESOLV_NO_CACHE_LOOKUP | ANDROID_RESOLV_NO_CACHE_STORE)) {
return flags & ANDROID_RESOLV_NO_CACHE_STORE ? RESOLV_CACHE_SKIP : RESOLV_CACHE_NOTFOUND;
}
Entry key;
@@ -1456,11 +1458,6 @@ ResolvCacheStatus _resolv_cache_lookup(unsigned netid, const void* query, int qu
if (e == NULL) {
LOG(INFO) << __func__ << ": NOT IN CACHE";
- // If it is no-cache-store mode, we won't wait for possible query.
- if (flags & ANDROID_RESOLV_NO_CACHE_STORE) {
- return RESOLV_CACHE_SKIP;
- }
-
if (!cache_has_pending_request_locked(cache, &key, true)) {
return RESOLV_CACHE_NOTFOUND;
diff --git a/resolv/res_send.cpp b/resolv/res_send.cpp
index 1ccfc741..1dff2038 100644
--- a/resolv/res_send.cpp
+++ b/resolv/res_send.cpp
@@ -931,6 +931,9 @@ read_len:
else
break;
}
+ LOG(WARNING) << __func__ << ": resplen " << resplen << " exceeds buf size " << anssiz;
+ // return size should never exceed container size
+ resplen = anssiz;
}
/*
* If the calling application has bailed out of
@@ -941,7 +944,7 @@ read_len:
*/
if (hp->id != anhp->id) {
LOG(DEBUG) << __func__ << ": ld answer (unexpected):";
- res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
+ res_pquery(ans, resplen);
goto read_len;
}
diff --git a/server/AndroidTest.xml b/server/AndroidTest.xml
index 2501d781..fbb0be72 100644
--- a/server/AndroidTest.xml
+++ b/server/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for netd_unit_test">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="netd_unit_test->/data/local/tmp/netd_unit_test" />