{
  "finding_id": "DF-2953",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "logtimeout() (softclock callout) reads logsoftc.sc_sigio without sigio_token and calls pgsigio() on the raw pointer (sys/kern/subr_log.c:247-248); concurrent FIOSETOWN/TIOCSPGRP on the klog fd frees the struct sigio (fsetown->funsetown->kfree, kern_descrip.c:1239-1372) and pgsigio then dereferences NULLed/freed fields (pgref(NULL), (NULL ucred)->cr_uid via CANSIGIO, kern_sig.c:99-104,2639-2662). Verified on the guest: kernel panic (Fatal trap 12, fault 0x40, pgsigio+0xcd, softclock/Idle context) within one second of PoC launch. Trigger requires an open /dev/klog fd (root:wheel 0600), so host-root DoS; via DF-0190 (jail root + devfs-exposed klog) it becomes a host-kernel panic from inside a jail. Validated fix: driver-local lockmgr sc_lock serializing every sc_sigio access in logopen/logclose/logtimeout/FIOSETOWN/TIOCSPGRP; patched kernel survived a 300s race soak (baseline died <1s). Two earlier fix attempts (lwkt token around pgsigio; systemic 13-file pgsigio(struct sigio**) snapshot rewrite) were built, re-panicked, and are documented as not-shipped.",
  "exploit_chain": "root (or jailed root w/ klog devfs exposure): open /dev/klog; FIOASYNC=1; FIOSETOWN(-own_pgrp) installs pgrp-owned sigio; 16 pgrp members + killpg(0) hammer stretch pgsigio()'s member loop to microseconds; /dev/console write loop keeps msgbuftrigger set so logtimeout (hz/wakeups per sec) calls pgsigio; concurrent FIOSETOWN(0)/FIOSETOWN(-pgrp) hammer frees the sigio inside pgsigio's deref window -> NULL-deref panic in softclock. Ceiling: local DoS (panic); read-side UAF of a dedicated M_SIGIO chunk with NULLed pointers - no practical write primitive.",
  "evidence": [
    "panic.txt: Fatal trap 12, fault virtual address=0x40, instruction pointer=pgsigio+0xcd, current process=Idle (softclock), Stopped at pgsigio+0xcd: movl 0x40(%rdx),%edx - baseline panic, <1s after launch",
    "run.log: all four runs (baseline panic <1s; attempt1 token fix panic; attempt2 systemic fix panic sess_rele assert; final fix 300s clean soak, load 5.04, guest up)",
    "run2_brokenfix_panic.txt: identical panic on the token-wrapped 'fix' proving lwkt tokens drop on block (lwkt_token.c:40-42)",
    "fix.diff: shipped driver-local lockmgr fix (subr_log.c, 6 hunks) - validated",
    "fix.attempt2-systemic-sigio-ref.diff.unvalidated: 13-file pgsigio(struct sigio**) snapshot rewrite - built+ran, still raced, NOT shipped",
    "build.log: final fixed-kernel build, 0 errors (Kernel build for X86_64_GENERIC completed Fri Sep 4 03:19:15 UTC 2026)",
    "klog_sigio_race.c: PoC source; build.sh/run.sh exact commands"
  ],
  "kernel_refs": [
    "sys/kern/subr_log.c:247",
    "sys/kern/subr_log.c:248",
    "sys/kern/subr_log.c:102",
    "sys/kern/subr_log.c:115",
    "sys/kern/subr_log.c:292",
    "sys/kern/subr_log.c:301",
    "sys/kern/subr_log.c:317",
    "sys/kern/kern_descrip.c:1239",
    "sys/kern/kern_descrip.c:1272",
    "sys/kern/kern_descrip.c:1296",
    "sys/kern/kern_descrip.c:1368",
    "sys/kern/kern_descrip.c:1386",
    "sys/kern/kern_sig.c:2639",
    "sys/kern/kern_sig.c:99",
    "sys/kern/kern_timeout.c:1104",
    "sys/kern/kern_timeout.c:926",
    "sys/kern/lwkt_token.c:40",
    "sys/kern/subr_prf.c:296"
  ],
  "poc_changes": "PoC authored fresh for this finding (no seed). Widening strategies that made the sub-microsecond window deterministic: (1) pgrp owner instead of proc owner so pgsigio takes the long pg_lock path; (2) 16 forked pgrp members stretch the signal loop; (3) killpg(pgrp,0) hammer contends pg_lock inside pgsigio; (4) /dev/console write loop keeps msgbuftrigger set so every logtimeout tick signals; (5) kern.log_wakeups_per_second raised to 100 (must stay >=1 - 0 is DF-0191); (6) three FIOSETOWN hammer processes for CPU spread.",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline); fixed kernel #1: Fri Sep 4 03:14:52 UTC 2026",
  "runtime_sec": 6600,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o /root/klog_sigio_race /root/klog_sigio_race.c   (in-guest, as root)",
  "run_cmd": "/etc/rc.d/syslogd stop; sysctl -w kern.log_wakeups_per_second=100; timeout 300 /root/klog_sigio_race   (as root)",
  "code_hash": "9c153a0e707e473ce8d34f87b80b365f8831c36f9503812948e2518b3ce2c5ab",
  "notes": "Related latent instance of the same bug class (token-across-blocking-pgsigio): sys/kern/sys_pipe.c:211-214 - recommend filing against sys_pipe.c. Systemic direction for upstream: FreeBSD-style pgsigio(struct sigio **) with internal locking, but any DragonFly port must avoid relying on lwkt tokens across the blocking signal path (see run 3 in run.log). Guest was reset to the clean with-src snapshot after validation.",
  "recommended_fix": "Serialize every klog-driver access of sc_sigio with a driver-local lockmgr lock held across the blocking pgsigio() path (fix.diff in this pack); alternatively upstream a reference-counted pgsigio(struct sigio **) that does not rely on lwkt tokens across blocking.",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Fri Sep 4 03:14:52 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline (stock) kernel panicked at pgsigio+0xcd within 1s of PoC launch (twice, plus once under a broken fix attempt). Kernel built with the driver-local sc_lock fix survived the identical PoC under timeout 300 with no panic (load avg 5.04 during soak; PoC exited cleanly at timeout; guest up). Two intermediate fix approaches were built and empirically refuted (lwkt token across pgsigio - drops on block per lwkt_token.c:40-42; systemic 13-file snapshot rewrite - still hit a pgrp destroy race, root cause undetermined); both are documented and the systemic diff is retained as unvalidated.",
  "fix_evidence": [
    "run.log run 4: NO PANIC, guest up, pgrep=0 after timeout, load 5.04",
    "build.log: fixed-kernel build completed 0 errors",
    "fix.diff: the validated 6-hunk driver-local fix",
    "run2_brokenfix_panic.txt / run.log runs 2-3: refuted fix attempts"
  ]
}
