DF-0033 / panic.txt
=== DF-0033 PANIC / CRASH EVIDENCE (this verification session) ===
All from unprivileged user 'maxx' via rfork(RFPROC|RFTHREAD) fdshare racing
fdl_refcount ++ (kern_fork.c:569, p_token) vs -- (kern_descrip.c:2675, fd_spin).
--------------------------------------------------------------------------------
1. INVARIANTS #0 audit kernel โ race CONFIRMED (botch panic, ~25s):
--------------------------------------------------------------------------------
(./fdtol_race 25 12 as maxx)
panic with 1 spinlocks held
panic: filedesc_to_refcount botch: fdl_refcount=-1925828443
Debugger("panic")
Stopped at Debugger+0x7c: movb $0,0xbdaf09(%rip)
Trace: fdfree <- fdfree <- exit1 <- sys_exit <- syscall2
The garbage fdl_refcount value (-1925828443 = 0x8D8E0D2B-style bytes) proves the
freed fdtol slot was RECLAIMED BY AN UNRELATED OBJECT before the victim's fdfree
read it back โ i.e. cross-type slab reclamation of the UAF'd chunk is occurring.
This reproduces the prior session's panic and confirms the race is LIVE.
--------------------------------------------------------------------------------
2. Non-INVARIANTS (X86_64_NOINV) kernel โ race fires SILENTLY, splice fires:
--------------------------------------------------------------------------------
(./exploit ... as maxx, with the sysctl-name2oid reclaim spray)
Fatal trap 12: page fault while in kernel mode
Stopped at slab_cleanup+0xa4: movq (%rdx),%rdx
Trace: slab_cleanup <- slotimer_callback <- softclock_handler
This crash is the slab garbage-collector dereferencing a corrupted free-list
pointer created by a DOUBLE-FREE of the prematurely-freed fdtol chunk. The
double-free only happens when a surviving peer/child's fdfree reads the reclaimed
chunk with fdl_refcount field == 1 (drives 1->0 -> splice + kfree = double-free).
On a non-INVARIANTS slab the KKASSERT at kern_descrip.c:2627 is compiled out, so
the corruption proceeds silently until the periodic (10s) slab_cleanup dereferences
the corrupted pointer. This proves the SPLICE PATH IS REACHED (a victim read
refcount=1 and executed the list-splice at kern_descrip.c:2678-2679).
--------------------------------------------------------------------------------
3. SEPARATE interfering race (NOT DF-0033) โ exit1 p_peers list walk:
--------------------------------------------------------------------------------
Stopped at exit1+0x155: movq 0x3e8(%rdx),%rax
(kern_exit.c:384-390 โ p_peers linked-list walk is unsynchronized across
concurrent rfork(RFPROC|RFTHREAD) peer/child exits; p_peers @ struct proc 0x3e8)
This is a DIFFERENT bug (same CLASS as DF-0033: per-proc p_token fails to
serialize peers sharing a structure) that fires under the same rfork+exit
concurrency the DF-0033 race needs. It frequently crashed the system before the
DF-0033 splice could be exploited, narrowing the usable concurrency window.
--------------------------------------------------------------------------------
4. kmem monitor โ definitive splice-target check:
--------------------------------------------------------------------------------
A libkvm monitor polling sysent[25].sy_call @ 0xffffffff81037360 every 3ms
showed it NEVER changed from sys_geteuid (0xffffffff8062f720) across all runs,
even when the slab_cleanup double-free cascade fired. Conclusion: the splice
that fired was driven by a NATURALLY-reclaimed chunk (offset-0 byte == 1 by
coincidence, valid pointers at 24/32 by coincidence -> no GPF, but writes to a
wrong address), NOT by the attacker's sysctl-name2oid reclaim. The attacker's
controlled content never landed in the freed fdtol chunk. See VERDICT.md
"Grooming failure โ root cause" for the slab-architecture analysis.