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 <netdutils/NetNativeTestBase.h> 25 #include <private/android_filesystem_config.h> // AID_DNS 26 27 #include "DnsResolver.h" 28 #include "getaddrinfo.h" 29 #include "resolv_cache.h" 30 #include "resolv_private.h" 31 #include "tests/resolv_test_utils.h" 32 33 namespace android::net { 34 35 using android::base::unique_fd; 36 using android::net::NetworkDnsEventReported; 37 using android::netdutils::ScopedAddrinfo; 38 39 // Use maximum reserved appId for applications to avoid conflict with existing uids. 40 const uid_t TEST_UID = 99999; 41 // Use testUid to make sure TagSocketCallback is called. 42 static uid_t testUid = 0; 43 44 // gApiLevel would be initialized in resolv_init(). 45 #define SKIP_IF_APILEVEL_LESS_THAN(version) \ 46 do { \ 47 if (android::net::gApiLevel < (version)) { \ 48 GTEST_LOG_(INFO) << "Skip. Required API version: " << (version) << "\n"; \ 49 return; \ 50 } \ 51 } while (0) 52 getNetworkContextCallback(uint32_t,uint32_t,android_net_context *)53 void getNetworkContextCallback(uint32_t, uint32_t, android_net_context*) { 54 // No-op 55 } 56 checkCallingPermissionCallback(const char *)57 bool checkCallingPermissionCallback(const char*) { 58 // No-op 59 return true; 60 } 61 logCallback(const char *)62 void logCallback(const char*) { 63 // No-op 64 } 65 tagSocketCallback(int,uint32_t,uid_t uid,pid_t)66 int tagSocketCallback(int, uint32_t, uid_t uid, pid_t) { 67 testUid = uid; 68 return true; 69 } 70 evaluateDomainNameCallback(const android_net_context &,const char *)71 bool evaluateDomainNameCallback(const android_net_context&, const char*) { 72 // No-op 73 return true; 74 } 75 initDnsResolverCallbacks()76 void initDnsResolverCallbacks() { 77 ResolverNetdCallbacks callbacks = { 78 .check_calling_permission = &checkCallingPermissionCallback, 79 .get_network_context = &getNetworkContextCallback, 80 .log = &logCallback, 81 .tagSocket = &tagSocketCallback, 82 .evaluate_domain_name = &evaluateDomainNameCallback, 83 }; 84 // It returns fail since socket 'dnsproxyd' has been occupied. 85 // But the callback funtions is configured successfully and can 86 // be tested when running unit test cases. 87 resolv_init(&callbacks); 88 } 89 resetDnsResolverCallbacks()90 void resetDnsResolverCallbacks() { 91 ResolverNetdCallbacks callbacks = { 92 .check_calling_permission = nullptr, 93 .get_network_context = nullptr, 94 .log = nullptr, 95 .tagSocket = nullptr, 96 .evaluate_domain_name = nullptr, 97 }; 98 resolv_init(&callbacks); 99 } 100 resetCallbackParams()101 void resetCallbackParams() { 102 testUid = 0; 103 } 104 105 class CallbackTest : public NetNativeTestBase { 106 protected: SetUp()107 void SetUp() override { 108 initDnsResolverCallbacks(); 109 // Create cache for test 110 android::net::gDnsResolv->resolverCtrl.createNetworkCache(TEST_NETID); 111 AllowNetworkInBackground(TEST_UID, true); 112 } 113 TearDown()114 void TearDown() override { 115 // Reset related parameters and callback functions. 116 resetCallbackParams(); 117 resetDnsResolverCallbacks(); 118 // Delete cache for test 119 android::net::gDnsResolv->resolverCtrl.destroyNetworkCache(TEST_NETID); 120 AllowNetworkInBackground(TEST_UID, false); 121 } 122 SetResolvers()123 int SetResolvers() { 124 const std::vector<std::string> servers = {test::kDefaultListenAddr}; 125 const std::vector<std::string> domains = {"example.com"}; 126 const res_params params = { 127 .sample_validity = 300, 128 .success_threshold = 25, 129 .min_samples = 8, 130 .max_samples = 8, 131 .base_timeout_msec = 1000, 132 .retry_count = 2, 133 }; 134 return resolv_set_nameservers(TEST_NETID, servers, domains, params, std::nullopt); 135 } 136 137 const android_net_context mNetcontext = { 138 .app_netid = TEST_NETID, 139 .app_mark = MARK_UNSET, 140 .dns_netid = TEST_NETID, 141 .dns_mark = MARK_UNSET, 142 .uid = TEST_UID, 143 }; 144 }; 145 TEST_F(CallbackTest,tagSocketCallback)146 TEST_F(CallbackTest, tagSocketCallback) { 147 // tagSocketCallback is used when supported sdk version >=30. 148 SKIP_IF_APILEVEL_LESS_THAN(30); 149 150 test::DNSResponder dns; 151 dns.addMapping(kHelloExampleCom, ns_type::ns_t_a, kHelloExampleComAddrV4); 152 ASSERT_TRUE(dns.startServer()); 153 EXPECT_EQ(SetResolvers(), 0); 154 155 addrinfo* result = nullptr; 156 const addrinfo hints = {.ai_family = AF_INET}; 157 NetworkDnsEventReported event; 158 // tagSocketCallback will be called. 159 const int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event); 160 ScopedAddrinfo result_cleanup(result); 161 EXPECT_EQ(testUid, TEST_UID); 162 EXPECT_EQ(rv, 0); 163 } 164 TEST_F(CallbackTest,tagSocketFchown)165 TEST_F(CallbackTest, tagSocketFchown) { 166 const uint64_t tmpApiLevel = gApiLevel; 167 168 // Expect the given socket will be fchown() with given uid. 169 gApiLevel = 30; // R 170 unique_fd sk(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)); 171 EXPECT_GE(sk, 3); 172 resolv_tag_socket(sk, TEST_UID, -1); 173 struct stat sb; 174 EXPECT_EQ(fstat(sk, &sb), 0); 175 EXPECT_EQ(sb.st_uid, TEST_UID); 176 177 // Expect the given socket will be fchown() with AID_DNS. 178 gApiLevel = 29; // Q 179 resolv_tag_socket(sk, TEST_UID, -1); 180 EXPECT_EQ(fstat(sk, &sb), 0); 181 EXPECT_EQ(sb.st_uid, static_cast<uid_t>(AID_DNS)); 182 183 // restore API level. 184 gApiLevel = tmpApiLevel; 185 } 186 187 } // end of namespace android::net 188