From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Thu, 15 Jun 2023 17:46:16 +0800 Subject: [PATCH] Fix use-after-free in DNS64 discovery thread DNS64 discovery thread is detached from binder requesting thread. But the discovery thread references resources not belongs to itself, which can be destroyed in dnsresolver destruction. Holds a strong pointer of Dns64Configuration in DNS64 discovery thread so that the instance of Dns64Configuration will keep until the DNS64 thread is force terminated. Ignore-AOSP-First: Fix security vulnerability Bug: 278303745 Test: m, fuzzing Fuzzing: mma resolv_service_fuzzer && adb sync data && adb shell /data/fuzz/arm64/resolv_service_fuzzer/resolv_service_fuzzer (cherry picked from commit 254115584ff558fb87ee6ec5f5bb043f76219910) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:cad5a8c884345689f5f2a1b6679c89524b066d15) Merged-In: Id74ea4e6f54a00805d3cc8a9d7e15e58a473b7d3 Change-Id: Id74ea4e6f54a00805d3cc8a9d7e15e58a473b7d3 --- resolv/Android.bp | 1 + resolv/Dns64Configuration.cpp | 17 ++++++++++------- resolv/Dns64Configuration.h | 3 ++- resolv/ResolverController.cpp | 15 +++++++-------- resolv/ResolverController.h | 2 +- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/resolv/Android.bp b/resolv/Android.bp index 50243f2b..6064fe21 100644 --- a/resolv/Android.bp +++ b/resolv/Android.bp @@ -91,6 +91,7 @@ cc_library { "libutils", "netd_event_listener_interface-ndk_platform", "dnsresolver_aidl_interface-ndk_platform", + "libutils", "server_configurable_flags", "stats_proto", "libprotobuf-cpp-lite", diff --git a/resolv/Dns64Configuration.cpp b/resolv/Dns64Configuration.cpp index a1dfdca0..865583e6 100644 --- a/resolv/Dns64Configuration.cpp +++ b/resolv/Dns64Configuration.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -38,6 +39,7 @@ namespace android { using android::net::NetworkDnsEventReported; +using android::sp; using netdutils::DumpWriter; using netdutils::IPAddress; using netdutils::IPPrefix; @@ -61,8 +63,9 @@ void Dns64Configuration::startPrefixDiscovery(unsigned netId) { // Emplace a copy of |cfg| in the map. mDns64Configs.emplace(std::make_pair(netId, cfg)); + const sp thiz = this; // Note that capturing |cfg| in this lambda creates a copy. - std::thread discovery_thread([this, cfg] { + std::thread discovery_thread([thiz, cfg] { // Make a mutable copy rather than mark the whole lambda mutable. // No particular reason. Dns64Config evalCfg(cfg); @@ -73,28 +76,28 @@ void Dns64Configuration::startPrefixDiscovery(unsigned netId) { .build(); while (true) { - if (!this->shouldContinueDiscovery(evalCfg)) break; + if (!thiz->shouldContinueDiscovery(evalCfg)) break; android_net_context netcontext{}; - mGetNetworkContextCallback(evalCfg.netId, 0, &netcontext); + thiz->mGetNetworkContextCallback(evalCfg.netId, 0, &netcontext); // Prefix discovery must bypass private DNS because in strict mode // the server generally won't know the NAT64 prefix. netcontext.flags |= NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS; if (doRfc7050PrefixDiscovery(netcontext, &evalCfg)) { - this->recordDns64Config(evalCfg); + thiz->recordDns64Config(evalCfg); break; } - if (!this->shouldContinueDiscovery(evalCfg)) break; + if (!thiz->shouldContinueDiscovery(evalCfg)) break; if (!backoff.hasNextTimeout()) break; { - std::unique_lock cvGuard(mMutex); + std::unique_lock cvGuard(thiz->mMutex); // TODO: Consider some chrono math, combined with wait_until() // perhaps, to prevent early re-resolves from the removal of // other netids with IPv6-only nameservers. - mCv.wait_for(cvGuard, backoff.getNextTimeout()); + thiz->mCv.wait_for(cvGuard, backoff.getNextTimeout()); } } }); diff --git a/resolv/Dns64Configuration.h b/resolv/Dns64Configuration.h index 58b115eb..aa899189 100644 --- a/resolv/Dns64Configuration.h +++ b/resolv/Dns64Configuration.h @@ -26,6 +26,7 @@ #include #include "netdutils/DumpWriter.h" #include "netdutils/InternetAddresses.h" +#include struct android_net_context; @@ -47,7 +48,7 @@ namespace net { * Thread-safety: All public methods in this class MUST be thread-safe. * (In other words: this class handles all its locking privately.) */ -class Dns64Configuration { +class Dns64Configuration : virtual public RefBase { public: // Simple data struct for passing back packet NAT64 prefix event information to the // Dns64PrefixCallback callback. diff --git a/resolv/ResolverController.cpp b/resolv/ResolverController.cpp index ac242596..b3515ff0 100644 --- a/resolv/ResolverController.cpp +++ b/resolv/ResolverController.cpp @@ -175,17 +175,17 @@ int getDnsInfo(unsigned netId, std::vector* servers, std::vectordump(dw, netId); ExternalPrivateDnsStatus privateDnsStatus = {PrivateDnsMode::OFF, 0, {}}; gPrivateDnsConfiguration.getStatus(netId, &privateDnsStatus); dw.println("Private DNS mode: %s", getPrivateDnsModeString(privateDnsStatus.mode)); diff --git a/resolv/ResolverController.h b/resolv/ResolverController.h index 6d08cdbe..2163a080 100644 --- a/resolv/ResolverController.h +++ b/resolv/ResolverController.h @@ -59,7 +59,7 @@ class ResolverController { void dump(netdutils::DumpWriter& dw, unsigned netId); private: - Dns64Configuration mDns64Configuration; + android::sp mDns64Configuration; }; } // namespace net } // namespace android