Audit report AR-05
Reported privately in an independent security review, 2026-08-07.
- Report date
- 2026-08-07
- Kind
- Bug
- Status on master
- Partly fixed in mp#201
- Proposed issue state
- Open
Summary
The report mentions the thread-context cleanup races described in mp#189 but does not count them, on the grounds that later event-loop changes may have fixed them and that it had not reproduced them. That reason does not hold for all of mp#189. Its first two problems were fixed by mp#201, but a third, a double destroy of a thread-map entry during teardown, was reproduced under ASan on 2026-08-12 and is still open, with a fix pending in mp#361. Real bug, partly fixed.
The report
This is an informational note with no severity, reproduction or fix. In full, it says that mp#189 describes thread-context cleanup races and stale map iterators, and that current code has later event-loop serialization and extraction changes, so the original problem was not counted without a fresh reproduction.
For context, mp#189 (2025-07-10) describes what happens when the destructors of the per-thread ThreadContext maps and the event loop's disconnect cleanup run on different threads at the same time. Every thread that makes IPC calls owns a thread_local ThreadContext with maps of ProxyClient<Thread> objects keyed by Connection*. Two sides can destroy an entry: the owning thread when it exits or finishes a call, and the event-loop thread when the connection breaks.
Proposed change
None in the report.
Assessment
The races are real, and the reason for discounting them is wrong for the part that is still open:
- Problems 1 and 2 of mp#189, the server worker thread and the event-loop disconnect handler both destroying the same
request_threadsentry as a call returns, were fixed by mp#201 (merged 2025-09-17). Bug page: Server worker thread and event-loop disconnect handler both destroy the same request_threads ProxyClient. - Problem 3, a thread exiting while the event loop destroys its
Connection, is still present on libmultiprocess master. It surfaced on 2026-08-12 as adouble free or corruptionabort in CI for mp#335 and was then reproduced as a heap-use-after-free under gdb and ASan. It became easier to hit after mp#298 (the fix for AR-01 and AR-16) moved client connection deletion to the event-loop thread at disconnect. Bug page: A thread exiting after making IPC calls and the event loop destroying its Connection both destroy the same ProxyClientmap entry .
The later changes the report refers to did not remove the unlocked handoff between ~ThreadContext and the SetThread cleanup callback that causes problem 3. No hostile peer is needed; a peer that disconnects while a client thread exits is enough. Of everything in this set of reports, this open item has the most direct effect on stability.
Status
Partly fixed: mp#201 is in libmultiprocess and Bitcoin Core. The remaining teardown race is open, with a fix and a deterministic test in mp#361 awaiting review and merge.
Reported privately in an independent security review on 2026-08-07.