CVE-2023-40100 AI-generated analysis
platform/packages/modules/DnsResolver, DNS64 / NAT64 prefix discovery (Dns64Configuration, ResolverController)
Makes Dns64Configuration reference counted (RefBase) and has the detached DNS64 prefix discovery thread capture a strong pointer (sp) to it instead of a raw this, so the object outlives the thread; ResolverController now owns it through android::sp.
Root cause
Dns64Configuration::startPrefixDiscovery (Dns64Configuration.cpp) spawns a std::thread whose lambda captured a raw `this` and used it (explicitly and implicitly) to access shouldContinueDiscovery, mGetNetworkContextCallback, recordDns64Config, mMutex and mCv. The thread is detached from the binder thread that requested discovery and retries with a backoff (maximum retransmission time 3600 s per index search). ResolverController held Dns64Configuration by value (`Dns64Configuration mDns64Configuration;`), so nothing tied the object's lifetime to the running thread. Per the commit message, the object can be destroyed during dnsresolver destruction while the discovery thread still uses it, which gives a use-after-free.
How the fix works
- Dns64Configuration.h: `class Dns64Configuration` now derives `virtual public RefBase` (include <utils/RefBase.h>), which makes instances reference counted.
- Dns64Configuration.cpp:startPrefixDiscovery: creates `const sp<Dns64Configuration> thiz = sp<Dns64Configuration>::fromExisting(this);` before spawning the thread and captures `thiz` in the lambda instead of `this`. Every member access in the loop (shouldContinueDiscovery, mGetNetworkContextCallback, recordDns64Config, mMutex, mCv) now goes through `thiz->`, so the thread holds a strong reference for its whole lifetime.
- ResolverController.h / ResolverController.cpp: the member becomes `android::sp<Dns64Configuration> mDns64Configuration`. The ResolverController constructor builds it with `sp<Dns64Configuration>::make(...)`, which gives fromExisting(this) a valid refcount. All uses (destroyNetworkCache, startPrefix64Discovery, stopPrefix64Discovery, getPrefix64, dump, setPrefix64, clearPrefix64) switch from `.` to `->`.
- Android.bp and tests/Android.bp: add `libutils` to the static_libs of the resolver cc_library and of the unit test cc_test. They also move the fuzzer's libutils dependency out of cc_fuzz and into the cc_defaults, as shared_libs for android and static_libs for host.
Completeness
- Covers the only raw-this capture shown in the diff: the detached discovery thread in Dns64Configuration::startPrefixDiscovery. All member accesses inside that lambda go through the strong pointer.
- The fix extends the object's lifetime rather than stopping or joining the thread on destruction. No destructor logic is added, so a running discovery thread keeps the Dns64Configuration alive until it exits on its own (shouldContinueDiscovery false, successful discovery, or exhausted backoff).
- Other things reached from the thread (gResNetdCallbacks via the mGetNetworkContextCallback lambda, sendNat64PrefixEvent via std::bind) are not changed by this fix. The diff does not address their lifetime relative to the thread.
- Correctness relies on every Dns64Configuration being created via sp (sp::make in ResolverController), because sp::fromExisting on an object not already managed by sp would not be safe. The diff shows only the ResolverController construction site.
Behavior changes
- Dns64Configuration is now heap allocated and reference counted. It stays alive as long as any discovery thread is running, even after ResolverController is destroyed.
- The resolver library now links libutils statically, and the test and fuzzer targets gain a libutils dependency.
- No change to DNS64 discovery semantics, return codes or timing is visible in the diff.
Per major
- Android 14: same fix: commit de58649ab30a (cherry-pick of 254115584ff5, Change-Id Id74ea4e6f54a00805d3cc8a9d7e15e58a473b7d3) in android-security-14.0.0_r2. At android-security-14.0.0_r29 all 8/8 patched lines are present. Per index search, the android-14.0.0_r75 snapshot shows a std::shared_ptr / shared_from_this form of the thiz capture instead. This does not match the r29 code and is unverified.
- Android 15: not affected per the bulletin (not listed); the patched region is present (8/8 lines) at android-security-15.0.0_r17.
- Android 16: not affected per the bulletin (not listed); the patched region is present (8/8 lines) at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin (not listed); the patched region is present (8/8 lines) at android-security-17.0.0_r1.
Unknowns
- What triggers destruction of the ResolverController / Dns64Configuration in a running dnsresolver (the commit message only says dnsresolver destruction).
- Whether a destructor or shutdown path elsewhere stops the discovery thread.
- Whether test code constructs Dns64Configuration outside sp ownership, which would be incompatible with sp::fromExisting.
- Why the index snapshot (android-14.0.0_r75) shows a shared_ptr-based variant while android-security-14.0.0_r29 shows the sp-based fix.
- The original AOSP commit 254115584ff5 and the 11/12/12L/13 branch commits are not included in the material.
- Where gResNetdCallbacks is declared and how long it lives.