Audit report AR-12

Reported privately in an independent security review, 2026-08-07.

Report date
2026-08-07
Kind
Hardening
Status on master
Partly fixed in mp#312
Proposed issue state
Open
Linked bugs
Bug 2: Spawned child process can deadlock before it starts running

Summary

A collection of error-handling weaknesses in libmultiprocess's process helpers: descriptor leaks on some setup failures, no EINTR retry around waitpid, permissive parsing of the descriptor number passed to a spawned child, a non-async-signal-safe diagnostic after fork(), and weak handling of empty argument lists and throwing callbacks. mp#312 fixed the post-fork diagnostic and the fork-failure leak four days after the report; the other items remain. Each is real and small, none is reachable by a peer. Hardening.

The report

The report lists these weaknesses in the process helpers in src/mp/util.cpp, and suggests fixing them in the same pass as the descriptor-inheritance problems of AR-15:

It gives no code or reproduction for these items.

Proposed change

Fix the items in a spawn-hardening pass. No code.

Assessment

Checked against src/mp/util.cpp on libmultiprocess master.

Fixed by mp#312 (merged 2026-08-11):

Still present on master:

The inputs for all of these come from the spawning process itself, not from a peer. On Bitcoin Core master SpawnProcess is reached only through the test-only echoipc RPC; it matters more on the unmerged multiprocess branch, where the GUI spawns the node and the node spawns wallets. An earlier, fixed leak on a different error path is SpawnProcess leaks the parent's end of the socketpair if closing the child's end fails.

Status

Partly fixed by mp#312. The remaining items are a few lines each: an EINTR loop in WaitProcess, std::from_chars with a full-match check in StartSpawned, RAII ownership of the socket pairs until fork(), and an argument-count check. Small libmultiprocess cleanup; no issue open.

Reported privately in an independent security review on 2026-08-07.