⬢ DragonFlyBSD Kernel Audit
DF-5793 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5793",
  "status": "reproduced",
  "verdict": "Unprivileged two-thread process hits kern_dup()s reserved-target path (kern_descrip.c:1143-1151): pipe() holds the read-side fd reserved across its second falloc/fsetfd (sys_pipe.c:290-338), and a sibling threads dup2() onto that fd takes an unbounded retry loop of 1-second NON-PCATCH tsleeps, each printing an unrate-limited kernel warning. Measured on stock guest: 10/117 dup2 attempts parked the full 1s and printed 10 dmesg lines in 10s (1 line/sec/thread sustained, scales per thread); SIGKILL delivered mid-park took ~1s to kill the process (uninterruptible); the same flood was observed overwriting a kernel panic message on the serial console during DF-5792 verification. With a persistent reservation (memory-pressure-blocked kmalloc, SCM_RIGHTS receive loop) the dup2 thread is unkillable indefinitely.",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "exploit_chain": "thread A: pipe() churn keeps the predictable lowest-free fd (3) transiently reserved (~8.5% of wall time measured); thread B: dup2(srcfd=250, 3) -> kern_dup reserved branch -> kprintf + tsleep(fdp,0,fdres,hz) + goto retry, no bound, no PCATCH. K threads -> K msgbuf/console lines per second and K unkillable-parked threads.",
  "evidence": "run.log (attempts=117 slow=10, 10 dmesg warnings), run.2.log (sweep: 16184 attempts, 11 slow, +12 lines), run.3.log (SIGKILL-to-death 1s), fixrun.log (patched: EINTR observed, 4 rigs/10s -> 10 lines total vs ~40 expected, SIGKILL-to-death 0s).",
  "kernel_refs": [
    "sys/kern/kern_descrip.c:1143",
    "sys/kern/kern_descrip.c:1146",
    "sys/kern/kern_descrip.c:1149",
    "sys/kern/sys_pipe.c:290",
    "sys/kern/kern_event.c:730",
    "sys/kern/uipc_usrreq.c:1593"
  ],
  "poc_changes": "Rigs written fresh. Bring-up fixes: dup2() success check must be >=0 (returns new fd, not 0); the dup2 source fd must be moved out of the contested lowest-free range (fd 250) or the pipe churner closes it (every dup2 EBADF); never use fd 0 as source over ssh (stdin closed).",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 120,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o dup_directed dup_directed.c -lpthread",
  "run_cmd": "./dup_directed 10 ; dmesg | grep -c target descriptor",
  "code_hash": "0f7b9416e0c67c0f95af06d43da6789490f59b8860f3b54e770633bde4319406",
  "notes": "Fix validated on guest-built kernel #2 (same build as DF-5792s fix): krateprintf freq=1 caps at 1 line/sec system-wide; PCATCH tsleep returns EINTR (measured errno 4); SIGKILL immediate. DoS-only severity (no memory corruption). Guest reset with-src afterwards.",
  "recommended_fix": "krateprintf the warning and make the tsleep PCATCH returning EINTR (see fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline: unbounded 1 line/sec/thread + 1s uninterruptible parks (SIGKILL deferred). Patched: <=1 line/sec system-wide (4 rigs -> 10 lines/10s vs ~40 extrapolated), dup2 returns EINTR when signalled, SIGKILL death 0s.",
  "fix_evidence": "fixrun.log sections a/b/c; dmesg counts in run.log/run.2.log/fixrun.log."
}