• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "resolv_callback_unit_test"
18 
19 #include <sys/stat.h>
20 
21 #include <android-base/file.h>
22 #include <android-base/properties.h>
23 #include <gtest/gtest.h>
24 #include <private/android_filesystem_config.h>  // AID_DNS
25 
26 #include "DnsResolver.h"
27 #include "getaddrinfo.h"
28 #include "resolv_cache.h"
29 #include "resolv_private.h"
30 #include "tests/resolv_test_utils.h"
31 
32 namespace android::net {
33 
34 using android::base::unique_fd;
35 using android::net::NetworkDnsEventReported;
36 using android::netdutils::ScopedAddrinfo;
37 
38 // Use maximum reserved appId for applications to avoid conflict with existing uids.
39 const uid_t TEST_UID = 99999;
40 // Use testUid to make sure TagSocketCallback is called.
41 static uid_t testUid = 0;
42 
43 // gApiLevel would be initialized in resolv_init().
44 #define SKIP_IF_APILEVEL_LESS_THAN(version)                                          \
45     do {                                                                             \
46         if (android::net::gApiLevel < (version)) {                                   \
47             GTEST_LOG_(INFO) << "Skip. Required API version: " << (version) << "\n"; \
48             return;                                                                  \
49         }                                                                            \
50     } while (0)
51 
getNetworkContextCallback(uint32_t,uint32_t,android_net_context *)52 void getNetworkContextCallback(uint32_t, uint32_t, android_net_context*) {
53     // No-op
54 }
55 
checkCallingPermissionCallback(const char *)56 bool checkCallingPermissionCallback(const char*) {
57     // No-op
58     return true;
59 }
60 
logCallback(const char *)61 void logCallback(const char*) {
62     // No-op
63 }
64 
tagSocketCallback(int,uint32_t,uid_t uid,pid_t)65 int tagSocketCallback(int, uint32_t, uid_t uid, pid_t) {
66     testUid = uid;
67     return true;
68 }
69 
evaluateDomainNameCallback(const android_net_context &,const char *)70 bool evaluateDomainNameCallback(const android_net_context&, const char*) {
71     // No-op
72     return true;
73 }
74 
initDnsResolverCallbacks()75 void initDnsResolverCallbacks() {
76     ResolverNetdCallbacks callbacks = {
77             .check_calling_permission = &checkCallingPermissionCallback,
78             .get_network_context = &getNetworkContextCallback,
79             .log = &logCallback,
80             .tagSocket = &tagSocketCallback,
81             .evaluate_domain_name = &evaluateDomainNameCallback,
82     };
83     // It returns fail since socket 'dnsproxyd' has been occupied.
84     // But the callback funtions is configured successfully and can
85     // be tested when running unit test cases.
86     resolv_init(&callbacks);
87 }
88 
resetDnsResolverCallbacks()89 void resetDnsResolverCallbacks() {
90     ResolverNetdCallbacks callbacks = {
91             .check_calling_permission = nullptr,
92             .get_network_context = nullptr,
93             .log = nullptr,
94             .tagSocket = nullptr,
95             .evaluate_domain_name = nullptr,
96     };
97     resolv_init(&callbacks);
98 }
99 
resetCallbackParams()100 void resetCallbackParams() {
101     testUid = 0;
102 }
103 
104 class CallbackTest : public ::testing::Test {
105   protected:
SetUp()106     void SetUp() override {
107         initDnsResolverCallbacks();
108         // Create cache for test
109         android::net::gDnsResolv->resolverCtrl.createNetworkCache(TEST_NETID);
110     }
111 
TearDown()112     void TearDown() override {
113         // Reset related parameters and callback functions.
114         resetCallbackParams();
115         resetDnsResolverCallbacks();
116         // Delete cache for test
117         android::net::gDnsResolv->resolverCtrl.destroyNetworkCache(TEST_NETID);
118     }
119 
SetResolvers()120     int SetResolvers() {
121         const std::vector<std::string> servers = {test::kDefaultListenAddr};
122         const std::vector<std::string> domains = {"example.com"};
123         const res_params params = {
124                 .sample_validity = 300,
125                 .success_threshold = 25,
126                 .min_samples = 8,
127                 .max_samples = 8,
128                 .base_timeout_msec = 1000,
129                 .retry_count = 2,
130         };
131         return resolv_set_nameservers(TEST_NETID, servers, domains, params, std::nullopt);
132     }
133 
134     const android_net_context mNetcontext = {
135             .app_netid = TEST_NETID,
136             .app_mark = MARK_UNSET,
137             .dns_netid = TEST_NETID,
138             .dns_mark = MARK_UNSET,
139             .uid = TEST_UID,
140     };
141 };
142 
TEST_F(CallbackTest,tagSocketCallback)143 TEST_F(CallbackTest, tagSocketCallback) {
144     // tagSocketCallback is used when supported sdk version >=30.
145     SKIP_IF_APILEVEL_LESS_THAN(30);
146 
147     test::DNSResponder dns;
148     dns.addMapping(kHelloExampleCom, ns_type::ns_t_a, kHelloExampleComAddrV4);
149     ASSERT_TRUE(dns.startServer());
150     EXPECT_EQ(SetResolvers(), 0);
151 
152     addrinfo* result = nullptr;
153     const addrinfo hints = {.ai_family = AF_INET};
154     NetworkDnsEventReported event;
155     // tagSocketCallback will be called.
156     const int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
157     ScopedAddrinfo result_cleanup(result);
158     EXPECT_EQ(testUid, TEST_UID);
159     EXPECT_EQ(rv, 0);
160 }
161 
TEST_F(CallbackTest,tagSocketFchown)162 TEST_F(CallbackTest, tagSocketFchown) {
163     const uint64_t tmpApiLevel = gApiLevel;
164 
165     // Expect the given socket will be fchown() with given uid.
166     gApiLevel = 30;  // R
167     unique_fd sk(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
168     EXPECT_GE(sk, 3);
169     resolv_tag_socket(sk, TEST_UID, -1);
170     struct stat sb;
171     EXPECT_EQ(fstat(sk, &sb), 0);
172     EXPECT_EQ(sb.st_uid, TEST_UID);
173 
174     // Expect the given socket will be fchown() with AID_DNS.
175     gApiLevel = 29;  // Q
176     resolv_tag_socket(sk, TEST_UID, -1);
177     EXPECT_EQ(fstat(sk, &sb), 0);
178     EXPECT_EQ(sb.st_uid, static_cast<uid_t>(AID_DNS));
179 
180     // restore API level.
181     gApiLevel = tmpApiLevel;
182 }
183 
184 }  // end of namespace android::net
185