Loading Android.bp +34 −51 Original line number Original line Diff line number Diff line Loading @@ -53,12 +53,12 @@ cc_library_headers { ], ], } } dnsresolver_aidl_interface_lateststable_version = "V8" dnsresolver_aidl_interface_lateststable_version = "V10" cc_library_static { cc_library_static { name: "dnsresolver_aidl_interface-lateststable-ndk_platform", name: "dnsresolver_aidl_interface-lateststable-ndk", whole_static_libs: [ whole_static_libs: [ "dnsresolver_aidl_interface-" + dnsresolver_aidl_interface_lateststable_version + "-ndk_platform", "dnsresolver_aidl_interface-" + dnsresolver_aidl_interface_lateststable_version + "-ndk", ], ], apex_available: [ apex_available: [ "com.android.resolv", "com.android.resolv", Loading @@ -78,7 +78,7 @@ aidl_interface { "binder/android/net/resolv/aidl/**/*.aidl", "binder/android/net/resolv/aidl/**/*.aidl", ], ], imports: [ imports: [ "netd_event_listener_interface", "netd_event_listener_interface-V1", ], ], backend: { backend: { java: { java: { Loading Loading @@ -106,6 +106,8 @@ aidl_interface { "6", "6", "7", "7", "8", "8", "9", "10", ], ], dumpapi: { dumpapi: { no_license: true, no_license: true, Loading Loading @@ -191,16 +193,17 @@ cc_library { // Link most things statically to minimize our dependence on system ABIs. // Link most things statically to minimize our dependence on system ABIs. stl: "libc++_static", stl: "libc++_static", static_libs: [ static_libs: [ "dnsresolver_aidl_interface-lateststable-ndk_platform", "dnsresolver_aidl_interface-lateststable-ndk", "libbase", "libbase", "libcutils", "libcutils", "libnetdutils", "libnetdutils", "libdoh_ffi", "libdoh_ffi", "libmodules-utils-build", "libprotobuf-cpp-lite", "libprotobuf-cpp-lite", "libstatslog_resolv", "libstatslog_resolv", "libstatspush_compat", "libstatspush_compat", "libsysutils", "libsysutils", "netd_event_listener_interface-lateststable-ndk_platform", "netd_event_listener_interface-lateststable-ndk", "server_configurable_flags", "server_configurable_flags", "stats_proto", "stats_proto", ], ], Loading Loading @@ -323,24 +326,26 @@ filegroup { ], ], } } rust_ffi_static { doh_rust_deps = [ name: "libdoh_ffi", crate_name: "doh", srcs: ["doh.rs"], edition: "2018", rlibs: [ "libandroid_logger", "libandroid_logger", "libanyhow", "libanyhow", "libbase64_rust", "libbase64_rust", "libfutures", "libfutures", "liblibc", "liblibc", "liblog_rust", "liblog_rust", "libquiche", "libring", "libring", "libthiserror", "libtokio", "libtokio", "liburl", "liburl", ], ] rust_ffi_static { name: "libdoh_ffi", crate_name: "doh", srcs: ["doh/doh.rs"], edition: "2018", rlibs: doh_rust_deps + ["libquiche"], prefer_rlib: true, prefer_rlib: true, shared_libs: [ shared_libs: [ Loading @@ -350,7 +355,7 @@ rust_ffi_static { apex_available: [ apex_available: [ "//apex_available:platform", // Needed by doh_ffi_test "//apex_available:platform", // Needed by doh_ffi_test "com.android.resolv" "com.android.resolv", ], ], min_sdk_version: "29", min_sdk_version: "29", } } Loading @@ -358,25 +363,14 @@ rust_ffi_static { rust_test { rust_test { name: "doh_unit_test", name: "doh_unit_test", crate_name: "doh", crate_name: "doh", srcs: ["doh.rs"], srcs: ["doh/doh.rs"], edition: "2018", edition: "2018", test_suites: ["general-tests"], test_suites: ["general-tests"], auto_gen_config: true, auto_gen_config: true, // Used to enable root permission for the test. // Used to enable root permission for the test. // TODO: remove after 'require_root' is supported in rust_test. // TODO: remove after 'require_root' is supported in rust_test. test_config_template: ":resolv_rust_test_config_template", test_config_template: ":resolv_rust_test_config_template", rustlibs: [ rustlibs: doh_rust_deps + ["libquiche_static"], "libandroid_logger", "libanyhow", "libbase64_rust", "libfutures", "liblibc", "liblog_rust", "libquiche_static", "libring", "libtokio", "liburl", ], min_sdk_version: "29", min_sdk_version: "29", } } Loading @@ -384,28 +378,17 @@ rust_test { rust_ffi_static { rust_ffi_static { name: "libdoh_ffi_for_test", name: "libdoh_ffi_for_test", crate_name: "doh", crate_name: "doh", srcs: ["doh.rs"], srcs: ["doh/doh.rs"], edition: "2018", edition: "2018", rlibs: [ rlibs: doh_rust_deps + ["libquiche_static"], "libandroid_logger", "libanyhow", "libbase64_rust", "libfutures", "liblibc", "liblog_rust", "libquiche_static", "libring", "libtokio", "liburl", ], prefer_rlib: true, prefer_rlib: true, // TODO(b/194022174), for unit tests to run on the Android 10 platform, // TODO(b/194022174), for unit tests to run on the Android 10 platform, // libunwind must be statically linked. // libunwind must be statically linked. whole_static_libs: ["libunwind"], whole_static_libs: ["libunwind"], apex_available: [ apex_available: [ "//apex_available:platform", // Needed by doh_ffi_test "//apex_available:platform", // Needed by doh_ffi_test "com.android.resolv" "com.android.resolv", ], ], min_sdk_version: "29", min_sdk_version: "29", } } Dns64Configuration.cpp +1 −2 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,6 @@ namespace android { namespace android { using android::base::StringPrintf; using android::net::NetworkDnsEventReported; using android::net::NetworkDnsEventReported; using netdutils::DumpWriter; using netdutils::DumpWriter; using netdutils::IPAddress; using netdutils::IPAddress; Loading Loading @@ -65,7 +64,7 @@ void Dns64Configuration::startPrefixDiscovery(unsigned netId) { // Note that capturing |cfg| in this lambda creates a copy. // Note that capturing |cfg| in this lambda creates a copy. std::thread discovery_thread([this, cfg, netId] { std::thread discovery_thread([this, cfg, netId] { setThreadName(StringPrintf("Nat64Pfx_%u", netId).c_str()); setThreadName(fmt::format("Nat64Pfx_{}", netId)); // Make a mutable copy rather than mark the whole lambda mutable. // Make a mutable copy rather than mark the whole lambda mutable. // No particular reason. // No particular reason. Loading DnsProxyListener.cpp +32 −28 Original line number Original line Diff line number Diff line Loading @@ -34,13 +34,11 @@ #include <algorithm> #include <algorithm> #include <vector> #include <vector> #include <android-base/stringprintf.h> #include <android/multinetwork.h> // ResNsendFlags #include <android/multinetwork.h> // ResNsendFlags #include <cutils/misc.h> // FIRST_APPLICATION_UID #include <cutils/misc.h> // FIRST_APPLICATION_UID #include <cutils/multiuser.h> #include <cutils/multiuser.h> #include <netdutils/InternetAddresses.h> #include <netdutils/InternetAddresses.h> #include <netdutils/ResponseCode.h> #include <netdutils/ResponseCode.h> #include <netdutils/Slice.h> #include <netdutils/Stopwatch.h> #include <netdutils/Stopwatch.h> #include <netdutils/ThreadUtil.h> #include <netdutils/ThreadUtil.h> #include <private/android_filesystem_config.h> // AID_SYSTEM #include <private/android_filesystem_config.h> // AID_SYSTEM Loading @@ -48,6 +46,7 @@ #include <sysutils/SocketClient.h> #include <sysutils/SocketClient.h> #include "DnsResolver.h" #include "DnsResolver.h" #include "Experiments.h" #include "NetdPermissions.h" #include "NetdPermissions.h" #include "OperationLimiter.h" #include "OperationLimiter.h" #include "PrivateDnsConfiguration.h" #include "PrivateDnsConfiguration.h" Loading @@ -65,6 +64,7 @@ using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using android::net::NetworkDnsEventReported; using android::net::NetworkDnsEventReported; using std::span; namespace android { namespace android { Loading Loading @@ -147,11 +147,11 @@ void maybeFixupNetContext(android_net_context* ctx, pid_t pid) { void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr, void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr, socklen_t addrlen); socklen_t addrlen); int extractResNsendAnswers(const uint8_t* answer, size_t anslen, int ipType, int extractResNsendAnswers(std::span<const uint8_t> answer, int ipType, std::vector<std::string>* ip_addrs) { std::vector<std::string>* ip_addrs) { int total_ip_addr_count = 0; int total_ip_addr_count = 0; ns_msg handle; ns_msg handle; if (ns_initparse((const uint8_t*)answer, anslen, &handle) < 0) { if (ns_initparse(answer.data(), answer.size(), &handle) < 0) { return 0; return 0; } } int ancount = ns_msg_count(handle, ns_s_an); int ancount = ns_msg_count(handle, ns_s_an); Loading Loading @@ -250,21 +250,20 @@ bool simpleStrtoul(const char* input, IntegralType* output, int base = 10) { return true; return true; } } bool setQueryId(uint8_t* msg, size_t msgLen, uint16_t query_id) { bool setQueryId(span<uint8_t> msg, uint16_t query_id) { if (msgLen < sizeof(HEADER)) { if ((size_t)msg.size() < sizeof(HEADER)) { errno = EINVAL; errno = EINVAL; return false; return false; } } auto hp = reinterpret_cast<HEADER*>(msg); auto hp = reinterpret_cast<HEADER*>(msg.data()); hp->id = htons(query_id); hp->id = htons(query_id); return true; return true; } } bool parseQuery(const uint8_t* msg, size_t msgLen, uint16_t* query_id, int* rr_type, bool parseQuery(span<const uint8_t> msg, uint16_t* query_id, int* rr_type, std::string* rr_name) { std::string* rr_name) { ns_msg handle; ns_msg handle; ns_rr rr; ns_rr rr; if (ns_initparse((const uint8_t*)msg, msgLen, &handle) < 0 || if (ns_initparse(msg.data(), msg.size(), &handle) < 0 || ns_parserr(&handle, ns_s_qd, 0, &rr) < 0) { ns_parserr(&handle, ns_s_qd, 0, &rr) < 0) { return false; return false; } } Loading Loading @@ -306,8 +305,8 @@ void initDnsEvent(NetworkDnsEventReported* event, const android_net_context& net // Return 0 if the event should not be logged. // Return 0 if the event should not be logged. // Otherwise, return subsampling_denom // Otherwise, return subsampling_denom uint32_t getDnsEventSubsamplingRate(int netid, int returnCode) { uint32_t getDnsEventSubsamplingRate(int netid, int returnCode, bool isMdns) { uint32_t subsampling_denom = resolv_cache_get_subsampling_denom(netid, returnCode); uint32_t subsampling_denom = resolv_cache_get_subsampling_denom(netid, returnCode, isMdns); if (subsampling_denom == 0) return 0; if (subsampling_denom == 0) return 0; // Sample the event with a chance of 1 / denom. // Sample the event with a chance of 1 / denom. return (arc4random_uniform(subsampling_denom) == 0) ? subsampling_denom : 0; return (arc4random_uniform(subsampling_denom) == 0) ? subsampling_denom : 0; Loading @@ -334,7 +333,12 @@ void maybeLogQuery(int eventType, const android_net_context& netContext, void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs, void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs, int returnCode, NetworkDnsEventReported& event, const std::string& query_name, int returnCode, NetworkDnsEventReported& event, const std::string& query_name, const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) { const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) { if (uint32_t rate = getDnsEventSubsamplingRate(netContext.dns_netid, returnCode)) { uint32_t rate = (query_name.ends_with(".local") && android::net::Experiments::getInstance()->getFlag("mdns_resolution", 1)) ? getDnsEventSubsamplingRate(netContext.dns_netid, returnCode, true) : getDnsEventSubsamplingRate(netContext.dns_netid, returnCode, false); if (rate) { const std::string& dnsQueryStats = event.dns_query_events().SerializeAsString(); const std::string& dnsQueryStats = event.dns_query_events().SerializeAsString(); stats::BytesField dnsQueryBytesField{dnsQueryStats.c_str(), dnsQueryStats.size()}; stats::BytesField dnsQueryBytesField{dnsQueryStats.c_str(), dnsQueryStats.size()}; event.set_return_code(static_cast<ReturnCode>(returnCode)); event.set_return_code(static_cast<ReturnCode>(returnCode)); Loading Loading @@ -560,7 +564,7 @@ bool getDns64Prefix(unsigned netId, netdutils::IPPrefix* prefix) { std::string makeThreadName(unsigned netId, uint32_t uid) { std::string makeThreadName(unsigned netId, uint32_t uid) { // The maximum of netId and app_id are 5-digit numbers. // The maximum of netId and app_id are 5-digit numbers. return android::base::StringPrintf("Dns_%u_%u", netId, multiuser_get_app_id(uid)); return fmt::format("Dns_{}_{}", netId, multiuser_get_app_id(uid)); } } } // namespace } // namespace Loading Loading @@ -922,8 +926,8 @@ void DnsProxyListener::ResNSendHandler::run() { uint16_t original_query_id = 0; uint16_t original_query_id = 0; // TODO: Handle the case which is msg contains more than one query // TODO: Handle the case which is msg contains more than one query if (!parseQuery(msg.data(), msgLen, &original_query_id, &rr_type, &rr_name) || if (!parseQuery({msg.data(), msgLen}, &original_query_id, &rr_type, &rr_name) || !setQueryId(msg.data(), msgLen, arc4random_uniform(65536))) { !setQueryId({msg.data(), msgLen}, arc4random_uniform(65536))) { // If the query couldn't be parsed, block the request. // If the query couldn't be parsed, block the request. LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid << ", invalid query"; LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid << ", invalid query"; sendBE32(mClient, -EINVAL); sendBE32(mClient, -EINVAL); Loading @@ -933,21 +937,21 @@ void DnsProxyListener::ResNSendHandler::run() { // Send DNS query // Send DNS query std::vector<uint8_t> ansBuf(MAXPACKET, 0); std::vector<uint8_t> ansBuf(MAXPACKET, 0); int rcode = ns_r_noerror; int rcode = ns_r_noerror; int nsendAns = -1; int ansLen = -1; NetworkDnsEventReported event; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { if (queryLimiter.start(uid)) { if (evaluate_domain_name(mNetContext, rr_name.c_str())) { if (evaluate_domain_name(mNetContext, rr_name.c_str())) { nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET, ansLen = resolv_res_nsend(&mNetContext, {msg.data(), msgLen}, ansBuf, &rcode, &rcode, static_cast<ResNsendFlags>(mFlags), &event); static_cast<ResNsendFlags>(mFlags), &event); } else { } else { nsendAns = -EAI_SYSTEM; ansLen = -EAI_SYSTEM; } } queryLimiter.finish(uid); queryLimiter.finish(uid); } else { } else { LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid << ", max concurrent queries reached"; << ", max concurrent queries reached"; nsendAns = -EBUSY; ansLen = -EBUSY; } } const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); Loading @@ -956,14 +960,14 @@ void DnsProxyListener::ResNSendHandler::run() { event.set_res_nsend_flags(static_cast<ResNsendFlags>(mFlags)); event.set_res_nsend_flags(static_cast<ResNsendFlags>(mFlags)); // Fail, send -errno // Fail, send -errno if (nsendAns < 0) { if (ansLen < 0) { if (!sendBE32(mClient, nsendAns)) { if (!sendBE32(mClient, ansLen)) { PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send errno to uid " << uid PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send errno to uid " << uid << " pid " << mClient->getPid(); << " pid " << mClient->getPid(); } } if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, rcode), event, rr_name); resNSendToAiError(ansLen, rcode), event, rr_name); } } return; return; } } Loading @@ -976,8 +980,8 @@ void DnsProxyListener::ResNSendHandler::run() { } } // Restore query id and send answer // Restore query id and send answer if (!setQueryId(ansBuf.data(), nsendAns, original_query_id) || if (!setQueryId({ansBuf.data(), ansLen}, original_query_id) || !sendLenAndData(mClient, nsendAns, ansBuf.data())) { !sendLenAndData(mClient, ansLen, ansBuf.data())) { PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send answer to uid " << uid PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send answer to uid " << uid << " pid " << mClient->getPid(); << " pid " << mClient->getPid(); return; return; Loading @@ -986,9 +990,9 @@ void DnsProxyListener::ResNSendHandler::run() { if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { std::vector<std::string> ip_addrs; std::vector<std::string> ip_addrs; const int total_ip_addr_count = const int total_ip_addr_count = extractResNsendAnswers((uint8_t*)ansBuf.data(), nsendAns, rr_type, &ip_addrs); extractResNsendAnswers({ansBuf.data(), ansLen}, rr_type, &ip_addrs); reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, rcode), event, rr_name, ip_addrs, resNSendToAiError(ansLen, rcode), event, rr_name, ip_addrs, total_ip_addr_count); total_ip_addr_count); } } } } Loading DnsResolver.cpp +3 −2 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. * limitations under the License. */ */ #define LOG_TAG "resolv" #include "DnsResolver.h" #include "DnsResolver.h" #include <android-base/logging.h> #include <android-base/logging.h> Loading @@ -28,12 +30,11 @@ bool resolv_init(const ResolverNetdCallbacks* callbacks) { bool resolv_init(const ResolverNetdCallbacks* callbacks) { android::base::InitLogging(/*argv=*/nullptr); android::base::InitLogging(/*argv=*/nullptr); android::base::SetDefaultTag("libnetd_resolv"); LOG(INFO) << __func__ << ": Initializing resolver"; LOG(INFO) << __func__ << ": Initializing resolver"; // TODO(b/170539625): restore log level to WARNING after clarifying flaky tests. // TODO(b/170539625): restore log level to WARNING after clarifying flaky tests. const bool isDebug = isUserDebugBuild(); const bool isDebug = isUserDebugBuild(); resolv_set_log_severity(isDebug ? android::base::DEBUG : android::base::WARNING); resolv_set_log_severity(isDebug ? android::base::DEBUG : android::base::WARNING); doh_init_logger(isDebug ? LOG_LEVEL_DEBUG : LOG_LEVEL_WARN); doh_init_logger(isDebug ? DOH_LOG_LEVEL_DEBUG : DOH_LOG_LEVEL_WARN); using android::net::gApiLevel; using android::net::gApiLevel; gApiLevel = getApiLevel(); gApiLevel = getApiLevel(); using android::net::gResNetdCallbacks; using android::net::gResNetdCallbacks; Loading DnsResolverService.cpp +12 −5 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,6 @@ #include <vector> #include <vector> #include <BinderUtil.h> #include <BinderUtil.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <android/binder_manager.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <android/binder_process.h> Loading @@ -36,9 +35,9 @@ #include "ResolverEventReporter.h" #include "ResolverEventReporter.h" #include "resolv_cache.h" #include "resolv_cache.h" using aidl::android::net::ResolverOptionsParcel; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::ResolverParamsParcel; using android::base::Join; using android::base::Join; using android::base::StringPrintf; using android::netdutils::DumpWriter; using android::netdutils::DumpWriter; using android::netdutils::IPPrefix; using android::netdutils::IPPrefix; Loading Loading @@ -181,8 +180,8 @@ binder_status_t DnsResolverService::dump(int fd, const char** args, uint32_t num } } } } auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s", auto err = fmt::format("UID {} / PID {} does not have any of the following permissions: {}", uid, pid, Join(permissions, ',').c_str()); uid, pid, Join(permissions, ',')); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); } } Loading @@ -196,7 +195,7 @@ binder_status_t DnsResolverService::dump(int fd, const char** args, uint32_t num uid_t uid = AIBinder_getCallingUid(); uid_t uid = AIBinder_getCallingUid(); // CAUTION: caCertificate should NOT be used except for internal testing. // CAUTION: caCertificate should NOT be used except for internal testing. if (resolverParams.caCertificate.size() != 0 && uid != AID_ROOT) { if (resolverParams.caCertificate.size() != 0 && uid != AID_ROOT) { auto err = StringPrintf("UID %d is not authorized to set a non-empty CA certificate", uid); auto err = fmt::format("UID {} is not authorized to set a non-empty CA certificate", uid); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); } } Loading Loading @@ -307,5 +306,13 @@ binder_status_t DnsResolverService::dump(int fd, const char** args, uint32_t num return statusFromErrcode(res); return statusFromErrcode(res); } } ::ndk::ScopedAStatus DnsResolverService::setResolverOptions(int32_t netId, const ResolverOptionsParcel& options) { // Locking happens in res_cache.cpp functions. ENFORCE_NETWORK_STACK_PERMISSIONS(); return statusFromErrcode(resolv_set_options(netId, options)); } } // namespace net } // namespace net } // namespace android } // namespace android Loading
Android.bp +34 −51 Original line number Original line Diff line number Diff line Loading @@ -53,12 +53,12 @@ cc_library_headers { ], ], } } dnsresolver_aidl_interface_lateststable_version = "V8" dnsresolver_aidl_interface_lateststable_version = "V10" cc_library_static { cc_library_static { name: "dnsresolver_aidl_interface-lateststable-ndk_platform", name: "dnsresolver_aidl_interface-lateststable-ndk", whole_static_libs: [ whole_static_libs: [ "dnsresolver_aidl_interface-" + dnsresolver_aidl_interface_lateststable_version + "-ndk_platform", "dnsresolver_aidl_interface-" + dnsresolver_aidl_interface_lateststable_version + "-ndk", ], ], apex_available: [ apex_available: [ "com.android.resolv", "com.android.resolv", Loading @@ -78,7 +78,7 @@ aidl_interface { "binder/android/net/resolv/aidl/**/*.aidl", "binder/android/net/resolv/aidl/**/*.aidl", ], ], imports: [ imports: [ "netd_event_listener_interface", "netd_event_listener_interface-V1", ], ], backend: { backend: { java: { java: { Loading Loading @@ -106,6 +106,8 @@ aidl_interface { "6", "6", "7", "7", "8", "8", "9", "10", ], ], dumpapi: { dumpapi: { no_license: true, no_license: true, Loading Loading @@ -191,16 +193,17 @@ cc_library { // Link most things statically to minimize our dependence on system ABIs. // Link most things statically to minimize our dependence on system ABIs. stl: "libc++_static", stl: "libc++_static", static_libs: [ static_libs: [ "dnsresolver_aidl_interface-lateststable-ndk_platform", "dnsresolver_aidl_interface-lateststable-ndk", "libbase", "libbase", "libcutils", "libcutils", "libnetdutils", "libnetdutils", "libdoh_ffi", "libdoh_ffi", "libmodules-utils-build", "libprotobuf-cpp-lite", "libprotobuf-cpp-lite", "libstatslog_resolv", "libstatslog_resolv", "libstatspush_compat", "libstatspush_compat", "libsysutils", "libsysutils", "netd_event_listener_interface-lateststable-ndk_platform", "netd_event_listener_interface-lateststable-ndk", "server_configurable_flags", "server_configurable_flags", "stats_proto", "stats_proto", ], ], Loading Loading @@ -323,24 +326,26 @@ filegroup { ], ], } } rust_ffi_static { doh_rust_deps = [ name: "libdoh_ffi", crate_name: "doh", srcs: ["doh.rs"], edition: "2018", rlibs: [ "libandroid_logger", "libandroid_logger", "libanyhow", "libanyhow", "libbase64_rust", "libbase64_rust", "libfutures", "libfutures", "liblibc", "liblibc", "liblog_rust", "liblog_rust", "libquiche", "libring", "libring", "libthiserror", "libtokio", "libtokio", "liburl", "liburl", ], ] rust_ffi_static { name: "libdoh_ffi", crate_name: "doh", srcs: ["doh/doh.rs"], edition: "2018", rlibs: doh_rust_deps + ["libquiche"], prefer_rlib: true, prefer_rlib: true, shared_libs: [ shared_libs: [ Loading @@ -350,7 +355,7 @@ rust_ffi_static { apex_available: [ apex_available: [ "//apex_available:platform", // Needed by doh_ffi_test "//apex_available:platform", // Needed by doh_ffi_test "com.android.resolv" "com.android.resolv", ], ], min_sdk_version: "29", min_sdk_version: "29", } } Loading @@ -358,25 +363,14 @@ rust_ffi_static { rust_test { rust_test { name: "doh_unit_test", name: "doh_unit_test", crate_name: "doh", crate_name: "doh", srcs: ["doh.rs"], srcs: ["doh/doh.rs"], edition: "2018", edition: "2018", test_suites: ["general-tests"], test_suites: ["general-tests"], auto_gen_config: true, auto_gen_config: true, // Used to enable root permission for the test. // Used to enable root permission for the test. // TODO: remove after 'require_root' is supported in rust_test. // TODO: remove after 'require_root' is supported in rust_test. test_config_template: ":resolv_rust_test_config_template", test_config_template: ":resolv_rust_test_config_template", rustlibs: [ rustlibs: doh_rust_deps + ["libquiche_static"], "libandroid_logger", "libanyhow", "libbase64_rust", "libfutures", "liblibc", "liblog_rust", "libquiche_static", "libring", "libtokio", "liburl", ], min_sdk_version: "29", min_sdk_version: "29", } } Loading @@ -384,28 +378,17 @@ rust_test { rust_ffi_static { rust_ffi_static { name: "libdoh_ffi_for_test", name: "libdoh_ffi_for_test", crate_name: "doh", crate_name: "doh", srcs: ["doh.rs"], srcs: ["doh/doh.rs"], edition: "2018", edition: "2018", rlibs: [ rlibs: doh_rust_deps + ["libquiche_static"], "libandroid_logger", "libanyhow", "libbase64_rust", "libfutures", "liblibc", "liblog_rust", "libquiche_static", "libring", "libtokio", "liburl", ], prefer_rlib: true, prefer_rlib: true, // TODO(b/194022174), for unit tests to run on the Android 10 platform, // TODO(b/194022174), for unit tests to run on the Android 10 platform, // libunwind must be statically linked. // libunwind must be statically linked. whole_static_libs: ["libunwind"], whole_static_libs: ["libunwind"], apex_available: [ apex_available: [ "//apex_available:platform", // Needed by doh_ffi_test "//apex_available:platform", // Needed by doh_ffi_test "com.android.resolv" "com.android.resolv", ], ], min_sdk_version: "29", min_sdk_version: "29", } }
Dns64Configuration.cpp +1 −2 Original line number Original line Diff line number Diff line Loading @@ -36,7 +36,6 @@ namespace android { namespace android { using android::base::StringPrintf; using android::net::NetworkDnsEventReported; using android::net::NetworkDnsEventReported; using netdutils::DumpWriter; using netdutils::DumpWriter; using netdutils::IPAddress; using netdutils::IPAddress; Loading Loading @@ -65,7 +64,7 @@ void Dns64Configuration::startPrefixDiscovery(unsigned netId) { // Note that capturing |cfg| in this lambda creates a copy. // Note that capturing |cfg| in this lambda creates a copy. std::thread discovery_thread([this, cfg, netId] { std::thread discovery_thread([this, cfg, netId] { setThreadName(StringPrintf("Nat64Pfx_%u", netId).c_str()); setThreadName(fmt::format("Nat64Pfx_{}", netId)); // Make a mutable copy rather than mark the whole lambda mutable. // Make a mutable copy rather than mark the whole lambda mutable. // No particular reason. // No particular reason. Loading
DnsProxyListener.cpp +32 −28 Original line number Original line Diff line number Diff line Loading @@ -34,13 +34,11 @@ #include <algorithm> #include <algorithm> #include <vector> #include <vector> #include <android-base/stringprintf.h> #include <android/multinetwork.h> // ResNsendFlags #include <android/multinetwork.h> // ResNsendFlags #include <cutils/misc.h> // FIRST_APPLICATION_UID #include <cutils/misc.h> // FIRST_APPLICATION_UID #include <cutils/multiuser.h> #include <cutils/multiuser.h> #include <netdutils/InternetAddresses.h> #include <netdutils/InternetAddresses.h> #include <netdutils/ResponseCode.h> #include <netdutils/ResponseCode.h> #include <netdutils/Slice.h> #include <netdutils/Stopwatch.h> #include <netdutils/Stopwatch.h> #include <netdutils/ThreadUtil.h> #include <netdutils/ThreadUtil.h> #include <private/android_filesystem_config.h> // AID_SYSTEM #include <private/android_filesystem_config.h> // AID_SYSTEM Loading @@ -48,6 +46,7 @@ #include <sysutils/SocketClient.h> #include <sysutils/SocketClient.h> #include "DnsResolver.h" #include "DnsResolver.h" #include "Experiments.h" #include "NetdPermissions.h" #include "NetdPermissions.h" #include "OperationLimiter.h" #include "OperationLimiter.h" #include "PrivateDnsConfiguration.h" #include "PrivateDnsConfiguration.h" Loading @@ -65,6 +64,7 @@ using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::DnsHealthEventParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using android::net::NetworkDnsEventReported; using android::net::NetworkDnsEventReported; using std::span; namespace android { namespace android { Loading Loading @@ -147,11 +147,11 @@ void maybeFixupNetContext(android_net_context* ctx, pid_t pid) { void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr, void addIpAddrWithinLimit(std::vector<std::string>* ip_addrs, const sockaddr* addr, socklen_t addrlen); socklen_t addrlen); int extractResNsendAnswers(const uint8_t* answer, size_t anslen, int ipType, int extractResNsendAnswers(std::span<const uint8_t> answer, int ipType, std::vector<std::string>* ip_addrs) { std::vector<std::string>* ip_addrs) { int total_ip_addr_count = 0; int total_ip_addr_count = 0; ns_msg handle; ns_msg handle; if (ns_initparse((const uint8_t*)answer, anslen, &handle) < 0) { if (ns_initparse(answer.data(), answer.size(), &handle) < 0) { return 0; return 0; } } int ancount = ns_msg_count(handle, ns_s_an); int ancount = ns_msg_count(handle, ns_s_an); Loading Loading @@ -250,21 +250,20 @@ bool simpleStrtoul(const char* input, IntegralType* output, int base = 10) { return true; return true; } } bool setQueryId(uint8_t* msg, size_t msgLen, uint16_t query_id) { bool setQueryId(span<uint8_t> msg, uint16_t query_id) { if (msgLen < sizeof(HEADER)) { if ((size_t)msg.size() < sizeof(HEADER)) { errno = EINVAL; errno = EINVAL; return false; return false; } } auto hp = reinterpret_cast<HEADER*>(msg); auto hp = reinterpret_cast<HEADER*>(msg.data()); hp->id = htons(query_id); hp->id = htons(query_id); return true; return true; } } bool parseQuery(const uint8_t* msg, size_t msgLen, uint16_t* query_id, int* rr_type, bool parseQuery(span<const uint8_t> msg, uint16_t* query_id, int* rr_type, std::string* rr_name) { std::string* rr_name) { ns_msg handle; ns_msg handle; ns_rr rr; ns_rr rr; if (ns_initparse((const uint8_t*)msg, msgLen, &handle) < 0 || if (ns_initparse(msg.data(), msg.size(), &handle) < 0 || ns_parserr(&handle, ns_s_qd, 0, &rr) < 0) { ns_parserr(&handle, ns_s_qd, 0, &rr) < 0) { return false; return false; } } Loading Loading @@ -306,8 +305,8 @@ void initDnsEvent(NetworkDnsEventReported* event, const android_net_context& net // Return 0 if the event should not be logged. // Return 0 if the event should not be logged. // Otherwise, return subsampling_denom // Otherwise, return subsampling_denom uint32_t getDnsEventSubsamplingRate(int netid, int returnCode) { uint32_t getDnsEventSubsamplingRate(int netid, int returnCode, bool isMdns) { uint32_t subsampling_denom = resolv_cache_get_subsampling_denom(netid, returnCode); uint32_t subsampling_denom = resolv_cache_get_subsampling_denom(netid, returnCode, isMdns); if (subsampling_denom == 0) return 0; if (subsampling_denom == 0) return 0; // Sample the event with a chance of 1 / denom. // Sample the event with a chance of 1 / denom. return (arc4random_uniform(subsampling_denom) == 0) ? subsampling_denom : 0; return (arc4random_uniform(subsampling_denom) == 0) ? subsampling_denom : 0; Loading @@ -334,7 +333,12 @@ void maybeLogQuery(int eventType, const android_net_context& netContext, void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs, void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs, int returnCode, NetworkDnsEventReported& event, const std::string& query_name, int returnCode, NetworkDnsEventReported& event, const std::string& query_name, const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) { const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) { if (uint32_t rate = getDnsEventSubsamplingRate(netContext.dns_netid, returnCode)) { uint32_t rate = (query_name.ends_with(".local") && android::net::Experiments::getInstance()->getFlag("mdns_resolution", 1)) ? getDnsEventSubsamplingRate(netContext.dns_netid, returnCode, true) : getDnsEventSubsamplingRate(netContext.dns_netid, returnCode, false); if (rate) { const std::string& dnsQueryStats = event.dns_query_events().SerializeAsString(); const std::string& dnsQueryStats = event.dns_query_events().SerializeAsString(); stats::BytesField dnsQueryBytesField{dnsQueryStats.c_str(), dnsQueryStats.size()}; stats::BytesField dnsQueryBytesField{dnsQueryStats.c_str(), dnsQueryStats.size()}; event.set_return_code(static_cast<ReturnCode>(returnCode)); event.set_return_code(static_cast<ReturnCode>(returnCode)); Loading Loading @@ -560,7 +564,7 @@ bool getDns64Prefix(unsigned netId, netdutils::IPPrefix* prefix) { std::string makeThreadName(unsigned netId, uint32_t uid) { std::string makeThreadName(unsigned netId, uint32_t uid) { // The maximum of netId and app_id are 5-digit numbers. // The maximum of netId and app_id are 5-digit numbers. return android::base::StringPrintf("Dns_%u_%u", netId, multiuser_get_app_id(uid)); return fmt::format("Dns_{}_{}", netId, multiuser_get_app_id(uid)); } } } // namespace } // namespace Loading Loading @@ -922,8 +926,8 @@ void DnsProxyListener::ResNSendHandler::run() { uint16_t original_query_id = 0; uint16_t original_query_id = 0; // TODO: Handle the case which is msg contains more than one query // TODO: Handle the case which is msg contains more than one query if (!parseQuery(msg.data(), msgLen, &original_query_id, &rr_type, &rr_name) || if (!parseQuery({msg.data(), msgLen}, &original_query_id, &rr_type, &rr_name) || !setQueryId(msg.data(), msgLen, arc4random_uniform(65536))) { !setQueryId({msg.data(), msgLen}, arc4random_uniform(65536))) { // If the query couldn't be parsed, block the request. // If the query couldn't be parsed, block the request. LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid << ", invalid query"; LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid << ", invalid query"; sendBE32(mClient, -EINVAL); sendBE32(mClient, -EINVAL); Loading @@ -933,21 +937,21 @@ void DnsProxyListener::ResNSendHandler::run() { // Send DNS query // Send DNS query std::vector<uint8_t> ansBuf(MAXPACKET, 0); std::vector<uint8_t> ansBuf(MAXPACKET, 0); int rcode = ns_r_noerror; int rcode = ns_r_noerror; int nsendAns = -1; int ansLen = -1; NetworkDnsEventReported event; NetworkDnsEventReported event; initDnsEvent(&event, mNetContext); initDnsEvent(&event, mNetContext); if (queryLimiter.start(uid)) { if (queryLimiter.start(uid)) { if (evaluate_domain_name(mNetContext, rr_name.c_str())) { if (evaluate_domain_name(mNetContext, rr_name.c_str())) { nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET, ansLen = resolv_res_nsend(&mNetContext, {msg.data(), msgLen}, ansBuf, &rcode, &rcode, static_cast<ResNsendFlags>(mFlags), &event); static_cast<ResNsendFlags>(mFlags), &event); } else { } else { nsendAns = -EAI_SYSTEM; ansLen = -EAI_SYSTEM; } } queryLimiter.finish(uid); queryLimiter.finish(uid); } else { } else { LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid << ", max concurrent queries reached"; << ", max concurrent queries reached"; nsendAns = -EBUSY; ansLen = -EBUSY; } } const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs()); Loading @@ -956,14 +960,14 @@ void DnsProxyListener::ResNSendHandler::run() { event.set_res_nsend_flags(static_cast<ResNsendFlags>(mFlags)); event.set_res_nsend_flags(static_cast<ResNsendFlags>(mFlags)); // Fail, send -errno // Fail, send -errno if (nsendAns < 0) { if (ansLen < 0) { if (!sendBE32(mClient, nsendAns)) { if (!sendBE32(mClient, ansLen)) { PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send errno to uid " << uid PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send errno to uid " << uid << " pid " << mClient->getPid(); << " pid " << mClient->getPid(); } } if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, rcode), event, rr_name); resNSendToAiError(ansLen, rcode), event, rr_name); } } return; return; } } Loading @@ -976,8 +980,8 @@ void DnsProxyListener::ResNSendHandler::run() { } } // Restore query id and send answer // Restore query id and send answer if (!setQueryId(ansBuf.data(), nsendAns, original_query_id) || if (!setQueryId({ansBuf.data(), ansLen}, original_query_id) || !sendLenAndData(mClient, nsendAns, ansBuf.data())) { !sendLenAndData(mClient, ansLen, ansBuf.data())) { PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send answer to uid " << uid PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send answer to uid " << uid << " pid " << mClient->getPid(); << " pid " << mClient->getPid(); return; return; Loading @@ -986,9 +990,9 @@ void DnsProxyListener::ResNSendHandler::run() { if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { if (rr_type == ns_t_a || rr_type == ns_t_aaaa) { std::vector<std::string> ip_addrs; std::vector<std::string> ip_addrs; const int total_ip_addr_count = const int total_ip_addr_count = extractResNsendAnswers((uint8_t*)ansBuf.data(), nsendAns, rr_type, &ip_addrs); extractResNsendAnswers({ansBuf.data(), ansLen}, rr_type, &ip_addrs); reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs, resNSendToAiError(nsendAns, rcode), event, rr_name, ip_addrs, resNSendToAiError(ansLen, rcode), event, rr_name, ip_addrs, total_ip_addr_count); total_ip_addr_count); } } } } Loading
DnsResolver.cpp +3 −2 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. * limitations under the License. */ */ #define LOG_TAG "resolv" #include "DnsResolver.h" #include "DnsResolver.h" #include <android-base/logging.h> #include <android-base/logging.h> Loading @@ -28,12 +30,11 @@ bool resolv_init(const ResolverNetdCallbacks* callbacks) { bool resolv_init(const ResolverNetdCallbacks* callbacks) { android::base::InitLogging(/*argv=*/nullptr); android::base::InitLogging(/*argv=*/nullptr); android::base::SetDefaultTag("libnetd_resolv"); LOG(INFO) << __func__ << ": Initializing resolver"; LOG(INFO) << __func__ << ": Initializing resolver"; // TODO(b/170539625): restore log level to WARNING after clarifying flaky tests. // TODO(b/170539625): restore log level to WARNING after clarifying flaky tests. const bool isDebug = isUserDebugBuild(); const bool isDebug = isUserDebugBuild(); resolv_set_log_severity(isDebug ? android::base::DEBUG : android::base::WARNING); resolv_set_log_severity(isDebug ? android::base::DEBUG : android::base::WARNING); doh_init_logger(isDebug ? LOG_LEVEL_DEBUG : LOG_LEVEL_WARN); doh_init_logger(isDebug ? DOH_LOG_LEVEL_DEBUG : DOH_LOG_LEVEL_WARN); using android::net::gApiLevel; using android::net::gApiLevel; gApiLevel = getApiLevel(); gApiLevel = getApiLevel(); using android::net::gResNetdCallbacks; using android::net::gResNetdCallbacks; Loading
DnsResolverService.cpp +12 −5 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,6 @@ #include <vector> #include <vector> #include <BinderUtil.h> #include <BinderUtil.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <android/binder_manager.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <android/binder_process.h> Loading @@ -36,9 +35,9 @@ #include "ResolverEventReporter.h" #include "ResolverEventReporter.h" #include "resolv_cache.h" #include "resolv_cache.h" using aidl::android::net::ResolverOptionsParcel; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::ResolverParamsParcel; using android::base::Join; using android::base::Join; using android::base::StringPrintf; using android::netdutils::DumpWriter; using android::netdutils::DumpWriter; using android::netdutils::IPPrefix; using android::netdutils::IPPrefix; Loading Loading @@ -181,8 +180,8 @@ binder_status_t DnsResolverService::dump(int fd, const char** args, uint32_t num } } } } auto err = StringPrintf("UID %d / PID %d does not have any of the following permissions: %s", auto err = fmt::format("UID {} / PID {} does not have any of the following permissions: {}", uid, pid, Join(permissions, ',').c_str()); uid, pid, Join(permissions, ',')); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); } } Loading @@ -196,7 +195,7 @@ binder_status_t DnsResolverService::dump(int fd, const char** args, uint32_t num uid_t uid = AIBinder_getCallingUid(); uid_t uid = AIBinder_getCallingUid(); // CAUTION: caCertificate should NOT be used except for internal testing. // CAUTION: caCertificate should NOT be used except for internal testing. if (resolverParams.caCertificate.size() != 0 && uid != AID_ROOT) { if (resolverParams.caCertificate.size() != 0 && uid != AID_ROOT) { auto err = StringPrintf("UID %d is not authorized to set a non-empty CA certificate", uid); auto err = fmt::format("UID {} is not authorized to set a non-empty CA certificate", uid); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); return ::ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, err.c_str())); } } Loading Loading @@ -307,5 +306,13 @@ binder_status_t DnsResolverService::dump(int fd, const char** args, uint32_t num return statusFromErrcode(res); return statusFromErrcode(res); } } ::ndk::ScopedAStatus DnsResolverService::setResolverOptions(int32_t netId, const ResolverOptionsParcel& options) { // Locking happens in res_cache.cpp functions. ENFORCE_NETWORK_STACK_PERMISSIONS(); return statusFromErrcode(resolv_set_options(netId, options)); } } // namespace net } // namespace net } // namespace android } // namespace android