DF-5793 / verdict.json
{ "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." } |