DF-2953 / run2_brokenfix_panic.txt
DF-2953 โ run 2 (BROKEN-FIX VALIDATION, kept for the record)
=============================================================
After the first (incomplete) fix attempt โ holding sigio_token across the
existing pgsigio() call in logtimeout โ the rebuilt kernel (#1: Fri Sep 4
02:04:08 UTC 2026, subr_log.o confirmed recompiled in build.log:14546) was
booted and the same PoC re-run. The guest panicked AGAIN at the identical
faulting instruction:
Fatal trap 12: page fault while in kernel mode
cpuid = 2; lapic id = 2
fault virtual address = 0x40
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff8066212d
current process = Idle
current thread = pri 12
Stopped at pgsigio+0xcd: movl 0x40(%rdx),%edx
(dfbsd-qemu/boot.log after the second run; console interleaved with the
PoC's console-noise writes.)
Root cause of the failure: lwkt tokens do not protect across blocking โ
sys/kern/lwkt_token.c:40-42:
"Tokens are locks which serialize a thread only while the thread is
running. If the thread blocks all tokens are released, then
reacquired when the thread resumes."
pgsigio() blocks in lockmgr(&pg->pg_lock) (contended by the PoC's
killpg() hammer), which silently drops the token and lets
funsetown()/fsetown() free the sigio. The same broken pattern exists at
sys/kern/sys_pipe.c:211-214 (lwkt_gettoken(&sigio_token) around
pgsigio(pb->sigio, ...) followed by lockmgr inside pgsigio) โ a related
latent instance of this bug class in pipes, out of this file's scope.
Conclusion: the correct fix is the snapshot+reference pgsigio(struct
sigio **) in fix.diff, validated as run 3.