Follow-up to the re-exec fix, from the challenger read the frozen scope
requires for security-boundary units. Three findings, all addressed here; two
direction questions go to the maintainer separately.
1. src/daemon/ipc.c stated an invariant that is FALSE. The comment above
posix_ancestor_overflow_uid() read "Derived once from immutable /proc
state". /proc/self/uid_map is not immutable -- unshare(CLONE_NEWUSER) is
exactly what rewrites it -- and pthread_once state survives fork() already
marked done. The hazard was written up in the tests, which is the one place
an ipc.c maintainer will never look, while production shipped the opposite
claim. The comment now states the real guarantee: the cache is safe only
because every caller runs in a freshly exec'd process, and it names what
would break it.
An audit of every process-creation site in src/ backs that: the daemon
double-fork execs (daemon/bootstrap.c), cbm_fork_with_retry execs
(foundation/subprocess.c), index workers go through cbm_subprocess_spawn,
worker_pool.c never forks, and src/ contains no setns or unshare at all.
No production path forks without exec and then reaches this check.
2. The probe now _exit()s instead of returning. The runner is built with
-fsanitize=address, so returning runs the atexit chain, and a future leak
anywhere in the prologue would exit 23 -- which the parent would have read
as a verdict on a security test that has none.
3. The parent now treats 0/1/2/3 as the closed protocol and names anything
else with the code it actually saw. A signal or a sanitizer exit is a broken
harness, not a refusal, and must not be able to look like one.
The probe guard also now matches its caller (linux AND test seams) instead of
compiling dead code in a non-seams build.
VERIFICATION. The challenger was right that the earlier proof was incomplete:
it showed the new test goes green, never that the test still binds the #1830
relaxation. Stubbing posix_compute_ancestor_overflow_uid() to
POSIX_NO_OVERFLOW_UID -- the relaxation removed -- and running as uid 1001:
tolerance off, new probe 48 passed, 1 failed (refused, exit 1)
tolerance on, new probe 49 passed, 0 skipped
so the smoke test is revert-sensitive to the production decision, not merely to
the test change. Worth recording: both deterministic #1830 tests PASSED with
the tolerance stubbed off, because they drive the test-seam override rather
than the real derivation. They bind the decision table; only this smoke test
binds the wiring.
macOS daemon_ipc 53 passed 1 skipped; linux/arm64 49 passed 0 skipped;
lint-ci clean.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>