# DF-3160 VERDICT — not_reproduced (structural defect, empirically not hittable here)

## Reproduced?
No.  Three hammer runs on the audit QEMU guest
(DragonFly 6.5-DEVELOPMENT #0, 6 vCPU, INVARIANTS stock kernel):

1. Unloaded, 1 reader + 1 writer, 60 s:
   `writer done: 1455169 opens, 0 slow (>50ms), max 0.2 ms`
2. 4 fifos, 4 readers (1 s hold every 8th cycle) + 4 writers, 170 s:
   one writer: `693731 opens, 114 slow (>50ms), max 202.8 ms`
3. 4 fifos, 4 readers (2 s hold every 50th cycle) + 4 writers, 170 s:
   all four writers: `0 slow (>50ms)`, max 21.8 ms (4.8M opens total).

## Why the run-2 stalls are NOT the lost wakeup
A genuine lost wakeup pins the writer until the reader's *next* 0->1
transition; with 1 s holds the stall distribution must reach ~1000 ms.
Every one of the 114 stalls was 68-203 ms — never near the hold time —
and run 3 (identical duty cycle, longer holds, more opens) produced zero.
They are fip-teardown/recreate (`fifo_fip_create`: two `socreate` +
`unp_connect2` on every readers->0->1 cycle) plus scheduler noise under
8-process load.

## Structural analysis (the defect is real in the code)
- Writer path: `fifo_vnops.c:319-325` — check `fi_readers == 0` under
  fifo_lock; `fifo_unlock(vp); vn_unlock(vp); tsleep(&fip->fi_writers, PCATCH, ...)`.
- The two lock releases and the `tsleep` are not atomic w.r.t. the
  reader's `wakeup(&fip->fi_writers)` (`fifo_vnops.c:276`), and after the
  wakeup the condition is never re-checked (comment at :328-333 asserts
  the wakeup implies a reader).
- FreeBSD's equivalent loops (`while (fip->fi_writers == 0)`) *and*
  sleeps with the vnode lock as interlock (`msleep(&fip->fi_readers,
  vp->v_vnlock, ...)`), which closes the window.
- DFly `tsleep` has no built-in condition interlock (classic sleep-queue
  wakeup; no pending-bit).

## Impact if it were hit
One blocked `open()` stalls until a future peer arrives; PCATCH makes it
killable.  Ceiling: local DoS of one thread.  Not memory corruption.

## Recommended fix
Re-check the condition in a loop and interlock the sleep with a lock the
waking side holds across its counter transition (vp->v_token is already
taken by the io paths; the wakeup side would take it around the
0->1 transition + wakeup), e.g.:

	while (... && fip->fi_writers == 0) {
		tsleep_interlock(&fip->fi_readers, PCATCH);
		fifo_unlock(vp);
		vn_unlock(vp);
		error = tsleep(&fip->fi_readers,
			       PCATCH | PINTERLOCKED, "fifoor", 0);
		...
	}
with the FREAD/FWRITE arrival paths in fifo_open sending their wakeup()
while holding vp->v_token.  (Sketch — a DFfly committer should pick the
exact token; the essential part is interlock + loop.)

## verdict.json summary
status=not_reproduced, reproduced=0, impact=none (no manifestation),
confidence=speculative (code defect certain, exploitability not
demonstrated), attempts=3, ~7.7M open() iterations.

## 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.

(No fix.diff for this item: documented recommendation only - see Fix above.)
