# DF-5793 VERDICT — reproduced (dos: unkillable spin + console/msgbuf flood); fix validated

## Bottom line

**REPRODUCED.** On the stock DragonFly 6.5-DEVELOPMENT guest, an
unprivileged two-thread process triggered the `kern_dup()` reserved-target
retry path at ~8.5% of dup2() attempts; every hit (a) emitted an
unrate-limited `Warning: dup(): target descriptor %d is reserved` line to
the console/dmesg and (b) parked the dup2 thread for a full 1-second
**uninterruptible** tsleep, with the retry loop unbounded while the peer
thread keeps re-reserving descriptors. `kill -9` delivered mid-park did
not take effect for ~1s (measured). The kernel-message flood was even
observed overwriting a kernel panic message on the serial console during
DF-5792 verification (serial_panic_run1.txt). Severity: Low (local DoS /
log flood; the unkillable-window becomes permanent if the reservation
holder blocks indefinitely, e.g. M_WAITOK kmalloc under memory pressure).

## Root cause (path:line)

* `sys/kern/kern_descrip.c:1143-1151` — plain `kprintf` per retry
  iteration + `tsleep(fdp, 0, "fdres", hz)` (flags=0 → not PCATCH) +
  `goto retry` with no attempt bound.
* Reservations spanning blocking work: `sys/kern/sys_pipe.c:290-338`
  (fd1 reserved across the second falloc and both fsetfds — the code
  comment even acknowledges racing dup()s), `sys/kern/kern_event.c:730`,
  `sys/kern/uipc_usrreq.c:1593-1620` (per-fd reservation loop),
  `sys/kern/kern_checkpoint.c:664`.
* Any thread of the process can observe a sibling's in-flight reservation
  by targeting the fd the sibling just allocated (lowest-free is
  predictable).

## Evidence (stock kernel #0, unprivileged user `maxx` uid 1001)

run.log (directed, 10s):

```
spammer: attempts=117 slow=10 err=0 errno_last=9(Bad file descriptor)
directed: pipes=5129795
dmesg reserved-warnings: 10        <- exactly one per 1s park
Warning: dup(): target descriptor 3 is reserved, waiting for it to be resolved   (x10)
```

run2.log (sweep variant, 12s):

```
DF-5793: pipes=4525216 dup2 attempts=16184 slow(>=250ms dup2)=11 err=0
total reserved-warnings now: 22    <- 12 new
```

kill.log (SIGKILL latency, stock):

```
pid=1315
SIGKILL-to-death sec: 1           <- uninterruptible park survives SIGKILL ~1s
warnings: 32
```

Note: only 117 dup2 attempts completed in 10s — each of the 10 hits
consumed a full second parked; steady state is one warning line + one
parked second per hit, per thread, forever.

## Fix validation (kernel #2 `Mon Oct 12 19:39:15 UTC 2026`)

`fix.diff`: `krateprintf(&krate_dupres /* .freq = 1 */, ...)` and
`tsleep(fdp, PCATCH, "fdres", hz)` → `return (EINTR)` on signal.

fixrun.log:

* patched directed run: `errno_last=4 (Interrupted system call)` — the
  once-uninterruptible wait now returns EINTR;
* 4 concurrent rigs × 10s → 10 warning lines total (krate cap; the
  unpatched per-thread rate of 10 lines/10s would give ~40);
* SIGKILL mid-park → death in 0s (vs 1s stock).

**fix_status: fixed** (flood bounded to ≤1 line/sec system-wide;
interruptible; no behavior change for the non-racing dup2 path — the
DF-5792 storms ran 20.8M opens/closes plus dup traffic on the same patched
kernel with zero anomalies).

## Rig notes (what had to be fixed vs a naive PoC)

* dup2() returns the new fd on success (not 0) — a `== 0` success check
  silently miscounts;
* the dup2 *source* fd must live outside the contested range (e.g. dup2'd
  to fd 250) or the churner's close-storm closes it and every dup2
  returns EBADF;
* ssh sessions may run with fd 0 closed — never use fd 0 as the source.

## Environment

Same guest as DF-5792 (see ../DF-5792/env.txt): DragonFly 6.5-DEVELOPMENT
#0 baseline; patched #2 for fix validation. Guest reset afterwards.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
