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 52 void getNetworkContextCallback(uint32_t, uint32_t, android_net_context*) { 53 // No-op 54 } 55 56 bool checkCallingPermissionCallback(const char*) { 57 // No-op 58 return true; 59 } 60 61 void logCallback(const char*) { 62 // No-op 63 } 64 65 int tagSocketCallback(int, uint32_t, uid_t uid, pid_t) { 66 testUid = uid; 67 return true; 68 } 69 70 bool evaluateDomainNameCallback(const android_net_context&, const char*) { 71 // No-op 72 return true; 73 } 74 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 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 100 void resetCallbackParams() { 101 testUid = 0; 102 } 103 104 class CallbackTest : public ::testing::Test { 105 protected: 106 void SetUp() override { 107 initDnsResolverCallbacks(); 108 // Create cache for test 109 android::net::gDnsResolv->resolverCtrl.createNetworkCache(TEST_NETID); 110 } 111 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 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 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 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