blob: 3b83381905c7dd24fbacc72773a61d63f1f506e0 [file] [log] [blame]
Luke Huang403c0442019-02-25 15:33:42 +08001/**
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
Ken Chen5471dca2019-04-15 15:25:35 +080017#define LOG_TAG "resolv"
Luke Huang403c0442019-02-25 15:33:42 +080018
Luke Huang36796f32019-03-13 02:54:45 +080019#include "DnsResolverService.h"
20
Luke Huang403c0442019-02-25 15:33:42 +080021#include <set>
22#include <vector>
23
Luke Huangf4c98f22019-06-14 01:57:00 +080024#include <BinderUtil.h>
Luke Huang403c0442019-02-25 15:33:42 +080025#include <android-base/stringprintf.h>
26#include <android-base/strings.h>
27#include <android/binder_manager.h>
28#include <android/binder_process.h>
Luke Huang598daad2019-05-02 18:10:15 +080029#include <netdutils/DumpWriter.h>
Luke Huang403c0442019-02-25 15:33:42 +080030#include <private/android_filesystem_config.h> // AID_SYSTEM
31
Luke Huang36796f32019-03-13 02:54:45 +080032#include "DnsResolver.h"
Luke Huang403c0442019-02-25 15:33:42 +080033#include "NetdPermissions.h" // PERM_*
Hungming Chena32c8c12019-01-25 10:47:40 +080034#include "ResolverEventReporter.h"
Luke Huangc6bbbe72019-03-28 21:38:28 +080035#include "resolv_cache.h"
Luke Huang403c0442019-02-25 15:33:42 +080036
waynema37255182019-03-18 13:22:56 +080037using aidl::android::net::ResolverParamsParcel;
Luke Huang403c0442019-02-25 15:33:42 +080038using android::base::Join;
39using android::base::StringPrintf;
Luke Huang7b26b202019-03-28 14:09:24 +080040using android::netdutils::DumpWriter;
Luke Huang403c0442019-02-25 15:33:42 +080041
42namespace android {
43namespace net {
44
45namespace {
46
47#define ENFORCE_ANY_PERMISSION(...) \
48 do { \
49 ::ndk::ScopedAStatus status = checkAnyPermission({__VA_ARGS__}); \
50 if (!status.isOk()) { \
51 return status; \
52 } \
53 } while (0)
54
55#define ENFORCE_INTERNAL_PERMISSIONS() \
56 ENFORCE_ANY_PERMISSION(PERM_CONNECTIVITY_INTERNAL, PERM_MAINLINE_NETWORK_STACK)
57
58#define ENFORCE_NETWORK_STACK_PERMISSIONS() \
59 ENFORCE_ANY_PERMISSION(PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK)
60
Hungming Chena32c8c12019-01-25 10:47:40 +080061inline ::ndk::ScopedAStatus statusFromErrcode(int ret) {
62 if (ret) {
63 return ::ndk::ScopedAStatus(
64 AStatus_fromServiceSpecificErrorWithMessage(-ret, strerror(-ret)));
65 }
66 return ::ndk::ScopedAStatus(AStatus_newOk());
67}
68
Luke Huang403c0442019-02-25 15:33:42 +080069} // namespace
70
Luke Huang598daad2019-05-02 18:10:15 +080071DnsResolverService::DnsResolverService() {
72 // register log callback to BnDnsResolver::logFunc
73 BnDnsResolver::logFunc =
74 std::bind(binderCallLogFn, std::placeholders::_1,
75 [](const std::string& msg) { gResNetdCallbacks.log(msg.c_str()); });
76}
77
Luke Huang36796f32019-03-13 02:54:45 +080078binder_status_t DnsResolverService::start() {
Luke Huang403c0442019-02-25 15:33:42 +080079 // TODO: Add disableBackgroundScheduling(true) after libbinder_ndk support it. b/126506010
80 // NetdNativeService does call disableBackgroundScheduling currently, so it is fine now.
Luke Huang36796f32019-03-13 02:54:45 +080081 DnsResolverService* resolverService = new DnsResolverService();
Luke Huang403c0442019-02-25 15:33:42 +080082 binder_status_t status =
83 AServiceManager_addService(resolverService->asBinder().get(), getServiceName());
84 if (status != STATUS_OK) {
85 return status;
86 }
87
88 ABinderProcess_startThreadPool();
89
90 // TODO: register log callback if binder NDK backend support it. b/126501406
91
92 return STATUS_OK;
93}
94
Luke Huangc6bbbe72019-03-28 21:38:28 +080095binder_status_t DnsResolverService::dump(int fd, const char**, uint32_t) {
96 auto dump_permission = checkAnyPermission({PERM_DUMP});
97 if (!dump_permission.isOk()) {
98 return STATUS_PERMISSION_DENIED;
99 }
100
101 // This method does not grab any locks. If individual classes need locking
102 // their dump() methods MUST handle locking appropriately.
103 DumpWriter dw(fd);
104 for (auto netId : resolv_list_caches()) {
105 dw.println("NetId: %u", netId);
106 gDnsResolv->resolverCtrl.dump(dw, netId);
107 dw.blankline();
108 }
109
Luke Huang7b26b202019-03-28 14:09:24 +0800110 return STATUS_OK;
111}
112
Luke Huang403c0442019-02-25 15:33:42 +0800113::ndk::ScopedAStatus DnsResolverService::isAlive(bool* alive) {
114 ENFORCE_INTERNAL_PERMISSIONS();
115
116 *alive = true;
117
118 return ::ndk::ScopedAStatus(AStatus_newOk());
119}
120
Hungming Chena32c8c12019-01-25 10:47:40 +0800121::ndk::ScopedAStatus DnsResolverService::registerEventListener(
122 const std::shared_ptr<aidl::android::net::metrics::INetdEventListener>& listener) {
123 ENFORCE_NETWORK_STACK_PERMISSIONS();
124
125 int res = ResolverEventReporter::getInstance().addListener(listener);
126
127 return statusFromErrcode(res);
128}
129
Luke Huang403c0442019-02-25 15:33:42 +0800130::ndk::ScopedAStatus DnsResolverService::checkAnyPermission(
131 const std::vector<const char*>& permissions) {
132 // TODO: Remove callback and move this to unnamed namespace after libbiner_ndk supports
133 // check_permission.
Luke Huang36796f32019-03-13 02:54:45 +0800134 if (!gResNetdCallbacks.check_calling_permission) {
Luke Huang403c0442019-02-25 15:33:42 +0800135 return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
136 EX_NULL_POINTER, "check_calling_permission is null"));
137 }
138 pid_t pid = AIBinder_getCallingPid();
139 uid_t uid = AIBinder_getCallingUid();
140
141 // If the caller is the system UID, don't check permissions.
142 // Otherwise, if the system server's binder thread pool is full, and all the threads are
143 // blocked on a thread that's waiting for us to complete, we deadlock. http://b/69389492
144 //
145 // From a security perspective, there is currently no difference, because:
146 // 1. The only permissions we check in netd's binder interface are CONNECTIVITY_INTERNAL
147 // and NETWORK_STACK, which the system server always has (or MAINLINE_NETWORK_STACK, which
148 // is equivalent to having both CONNECTIVITY_INTERNAL and NETWORK_STACK).
149 // 2. AID_SYSTEM always has all permissions. See ActivityManager#checkComponentPermission.
150 if (uid == AID_SYSTEM) {
151 return ::ndk::ScopedAStatus(AStatus_newOk());
152 }
153
154 for (const char* permission : permissions) {
Luke Huang36796f32019-03-13 02:54:45 +0800155 if (gResNetdCallbacks.check_calling_permission(permission)) {
Luke Huang403c0442019-02-25 15:33:42 +0800156 return ::ndk::ScopedAStatus(AStatus_newOk());
157 }
158 }
159
160 auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s",
161 uid, pid, Join(permissions, ',').c_str());
162 return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str()));
163}
164
Luke Huang7b26b202019-03-28 14:09:24 +0800165::ndk::ScopedAStatus DnsResolverService::setResolverConfiguration(
waynema37255182019-03-18 13:22:56 +0800166 const ResolverParamsParcel& resolverParams) {
Luke Huang7b26b202019-03-28 14:09:24 +0800167 // Locking happens in PrivateDnsConfiguration and res_* functions.
168 ENFORCE_INTERNAL_PERMISSIONS();
Luke Huang598daad2019-05-02 18:10:15 +0800169 // TODO: Remove this log after AIDL gen_log supporting more types, b/129732660
Luke Huangc6bbbe72019-03-28 21:38:28 +0800170 auto entry =
171 gDnsResolverLog.newEntry()
172 .prettyFunction(__PRETTY_FUNCTION__)
waynema37255182019-03-18 13:22:56 +0800173 .args(resolverParams.netId, resolverParams.servers, resolverParams.domains,
174 resolverParams.sampleValiditySeconds, resolverParams.successThreshold,
175 resolverParams.minSamples, resolverParams.maxSamples,
waynema9a530232019-04-18 19:13:26 +0800176 resolverParams.baseTimeoutMsec, resolverParams.retryCount,
waynema0e73c2e2019-07-31 15:04:08 +0800177 resolverParams.tlsName, resolverParams.tlsServers);
Luke Huang7b26b202019-03-28 14:09:24 +0800178
waynema0e73c2e2019-07-31 15:04:08 +0800179 int res = gDnsResolv->resolverCtrl.setResolverConfiguration(resolverParams);
Luke Huang598daad2019-05-02 18:10:15 +0800180 gResNetdCallbacks.log(entry.returns(res).withAutomaticDuration().toString().c_str());
181
182 return statusFromErrcode(res);
Luke Huang7b26b202019-03-28 14:09:24 +0800183}
184
185::ndk::ScopedAStatus DnsResolverService::getResolverInfo(
186 int32_t netId, std::vector<std::string>* servers, std::vector<std::string>* domains,
187 std::vector<std::string>* tlsServers, std::vector<int32_t>* params,
188 std::vector<int32_t>* stats, std::vector<int32_t>* wait_for_pending_req_timeout_count) {
189 // Locking happens in PrivateDnsConfiguration and res_* functions.
190 ENFORCE_NETWORK_STACK_PERMISSIONS();
191
Luke Huang598daad2019-05-02 18:10:15 +0800192 int res = gDnsResolv->resolverCtrl.getResolverInfo(netId, servers, domains, tlsServers, params,
Luke Huang7b26b202019-03-28 14:09:24 +0800193 stats, wait_for_pending_req_timeout_count);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800194
Luke Huang598daad2019-05-02 18:10:15 +0800195 return statusFromErrcode(res);
Luke Huang7b26b202019-03-28 14:09:24 +0800196}
197
198::ndk::ScopedAStatus DnsResolverService::startPrefix64Discovery(int32_t netId) {
199 // Locking happens in Dns64Configuration.
200 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800201
Luke Huang7b26b202019-03-28 14:09:24 +0800202 gDnsResolv->resolverCtrl.startPrefix64Discovery(netId);
203
204 return ::ndk::ScopedAStatus(AStatus_newOk());
205}
206
207::ndk::ScopedAStatus DnsResolverService::stopPrefix64Discovery(int32_t netId) {
208 // Locking happens in Dns64Configuration.
209 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800210
Luke Huang7b26b202019-03-28 14:09:24 +0800211 gDnsResolv->resolverCtrl.stopPrefix64Discovery(netId);
212
213 return ::ndk::ScopedAStatus(AStatus_newOk());
214}
215
216::ndk::ScopedAStatus DnsResolverService::getPrefix64(int netId, std::string* stringPrefix) {
217 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huangc6bbbe72019-03-28 21:38:28 +0800218
Luke Huang7b26b202019-03-28 14:09:24 +0800219 netdutils::IPPrefix prefix{};
Luke Huang598daad2019-05-02 18:10:15 +0800220 int res = gDnsResolv->resolverCtrl.getPrefix64(netId, &prefix);
Luke Huang7b26b202019-03-28 14:09:24 +0800221 *stringPrefix = prefix.toString();
222
Luke Huang598daad2019-05-02 18:10:15 +0800223 return statusFromErrcode(res);
Luke Huang7b26b202019-03-28 14:09:24 +0800224}
225
Ken Chend99022c2019-02-20 21:34:14 +0800226::ndk::ScopedAStatus DnsResolverService::setLogSeverity(int32_t logSeverity) {
227 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huang598daad2019-05-02 18:10:15 +0800228
Ken Chend99022c2019-02-20 21:34:14 +0800229 int res = gDnsResolv->setLogSeverity(logSeverity);
230
Ken Chend99022c2019-02-20 21:34:14 +0800231 return statusFromErrcode(res);
232}
233
Luke Huang9b80e6c2019-04-09 17:54:09 +0800234::ndk::ScopedAStatus DnsResolverService::destroyNetworkCache(int netId) {
235 // Locking happens in res_cache.cpp functions.
Luke Huang5bd827c2019-03-14 16:10:04 +0800236 ENFORCE_NETWORK_STACK_PERMISSIONS();
237
Luke Huang9b80e6c2019-04-09 17:54:09 +0800238 gDnsResolv->resolverCtrl.destroyNetworkCache(netId);
Luke Huangc6bbbe72019-03-28 21:38:28 +0800239
Luke Huang5bd827c2019-03-14 16:10:04 +0800240 return ::ndk::ScopedAStatus(AStatus_newOk());
241}
242
Luke Huang9b80e6c2019-04-09 17:54:09 +0800243::ndk::ScopedAStatus DnsResolverService::createNetworkCache(int netId) {
244 // Locking happens in res_cache.cpp functions.
245 ENFORCE_NETWORK_STACK_PERMISSIONS();
Luke Huang9b80e6c2019-04-09 17:54:09 +0800246
247 int res = gDnsResolv->resolverCtrl.createNetworkCache(netId);
248
Luke Huang9b80e6c2019-04-09 17:54:09 +0800249 return statusFromErrcode(res);
250}
251
Luke Huang403c0442019-02-25 15:33:42 +0800252} // namespace net
253} // namespace android