DragonFlyBSD Kernel Audit
DF-2683 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2683",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "fsetown() (kern_descrip.c:1296-1380) inserts the zeroed sigio into proc->p_sigiolst / pgrp->pg_sigiolst at lines 1351/1357 and initializes sio_pgid/sio_ucred/sio_ruid/sio_myref only afterwards (1362-1366, after the owner token is dropped). Teardown walkers -- exit1()->funsetownlst() (kern_exit.c:376) and pgdelete()->funsetownlst() (kern_proc.c:680) -- consume the half-born entry: funsetown(NULL) NULL-page fault, or with sio_pgid still 0 the wrong owner branch makes SLIST_REMOVE walk off the list (fault at NULL+8). Unprivileged harness (fork short-lived same-session children + hammer F_SETOWN(child_pid)) reproduced twice on the stock kernel: run 1 hard-wedged the machine (funsetownlst livelock, no console output); run 2 gave 'Fatal trap 12 ... fault virtual address = 0x8 ... Stopped at funsetown+0x93: movq 0x8(%rdx),%rax' attributed to the unprivileged fsetown_race process, kernel halted in DDB.",
  "exploit_chain": "unprivileged fork storm + fcntl(F_SETOWN, child_pid) hammer -> child's exit1() funsetownlst() walk lands inside fsetown()'s insert->init window -> NULL-deref / wrong-list SLIST_REMOVE -> fatal kernel trap (demonstrated). Impact ceiling is local DoS (panic / permanent machine wedge); no memory-disclosure or control primitive identified for this path.",
  "evidence": [
    "panic.txt: 'Fatal trap 12 ... fault virtual address = 0x8 ... Stopped at funsetown+0x93' from unprivileged fsetown_race",
    "run.log: both stock runs (run 1 silent wedge, run 2 trap after 'round 0 (162 sets)')",
    "panic.dbg.txt: instrumented-fix crash (funsetown_free+0x95) documenting the fix-failed iteration",
    "VERDICT.md: root cause with exact line numbers, all three consumption variants, fix iteration history v1-v4"
  ],
  "kernel_refs": [
    "sys/kern/kern_descrip.c:1347",
    "sys/kern/kern_descrip.c:1351",
    "sys/kern/kern_descrip.c:1357",
    "sys/kern/kern_descrip.c:1362",
    "sys/kern/kern_descrip.c:1366",
    "sys/kern/kern_exit.c:376",
    "sys/kern/kern_proc.c:680"
  ],
  "poc_changes": "Added <sys/socket.h> include and a per-500-round progress print vs the seed sketch; core choreography unchanged.",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 460,
  "guest_dirty": 1,
  "build_cmd": "cc -O2 -o fsetown_race fsetown_race.c",
  "run_cmd": "./fsetown_race 20000",
  "code_hash": "8b696e1fdc65767e7c24df8abab393f67da0df189960c1010fa6b0f865660a8e",
  "notes": "fix.diff v4 (init-before-insert + funsetown/funsetownlst restructure with sleep-retry) compiles and boots but the 20000-round storm still crashes the restructured replacement machinery via a recycled-chunk double teardown (funsetown_free walk-off); fix_status=fix_failed after 4 documented iterations. Guest was reset with-src after the runs.",
  "recommended_fix": "Initialize every sigio field (including sio_proc/sio_pgrp and sio_myref) before the owner-list insertion, publish *sigiop only after the entry is fully linked, and give funsetownlst an atomic check-and-claim of the head entry under sigio_token (ideally replace the token composition with a per-sigio refcount)."
}