DF-2691 / run.log
run.log - DF-2691 decisive run #1 (fresh boot, unprivileged user t1)
Command: su -l t1 -c /tmp/t1home/kqsig_uaf
Setup: sysctl kern.ps_arg_cache_limit=8192 (debug knob, allows large
argv to be cached in p_args for the content-controlled recycle
demonstration; the trigger itself needs no privileges)
Guest: DragonFly 6.5-DEVELOPMENT #0 X86_64_GENERIC (INVARIANTS), 6 vCPU
stdout:
[64 dangling sig-knotes attached to freed procs]
[400 p_args spray children exec'd, argv=1251 bytes]
closing kqueue...
<guest dies - no SURVIVED line>
serial console (panic.txt):
Fatal user address access from kernel mode from kqsig_uaf at ffffffff8063c973
Fatal trap 12: page fault while in kernel mode
cpuid = 1; lapic id = 1
fault virtual address = 0x18
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff8063c973
current process = 4104
kernel: type 12 trap, code=0
CPU1 stopping CPUs: 0x0000003d
stopped
Stopped at knote_remove+0x33: movq 0x18(%rdx),%rax
db>
0x18 == offsetof(struct knote, kn_next): this is the SLIST_REMOVE walk
`while (SLIST_NEXT(curelm, kn_next) != elm)` with curelm == NULL, i.e.
SLIST_FIRST(&victim->p_klist) == NULL because the freed struct proc chunk
was recycled as a fresh (M_ZERO) process. The kernel reached this code
from close(kq) -> kqueue_close -> knote drain -> filt_sigdetach ->
knote_remove(&kn->kn_ptr.p_proc->p_klist, kn) with p_proc pointing at
memory freed by kern_wait()'s kfree(p, M_PROC).
Result: reproduced, impact=panic (unprivileged, deterministic enough to
hit on the first run both times), class=UAF (write into freed memory on
the un-recycled path, wild pointer walk on the recycled path).