โฌข DragonFlyBSD Kernel Audit
DF-2953 / run2_brokenfix_panic.txt
โ† back to finding โ†“ download raw
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.