# DF-3161 VERDICT — reproduced (permanent kernel resource leak on umount -f)

## Reproduced?  Yes.
Deterministic PoC (`umount_fifoleak_scmrights.c`, run as root on the stock
INVARIANTS guest kernel #0, 2026-09-07):

- baseline connected unix-domain stream sockets: 4
- fifo open on a fresh tmpfs: 6  (+2 = the internal socket pair)
- fifo fd hidden in a unix-socket receive buffer (SCM_RIGHTS, never
  received) so no process owns it
- `umount -f`: dounmount's SIGINT/SIGKILL protocol
  (sys/kern/vfs_syscalls.c:929-946) cannot find a holder; 50 retries x
  0.25 s exhaust; console prints `forced umount of "(null)" - 1
  namecache refs, 1 mount refs`; the mount is ripped.
- close the holding socketpair, wait 2 s: **still 6** — the socket pair
  is never freed.

Control: the same fifo opened/closed normally (and even the process-held
umount -f variant, where SIGINT kills the holder first) returns to the
baseline count of 4.  The leak is specifically the force-close path.

## Why (line-level)
1. `vgone_vxlocked` -> `vclean_vxlocked(vp, DOCLOSE)`
   (sys/kern/vfs_subr.c:1285, 1567).
2. Force-close loop `sys/kern/vfs_subr.c:1341-1352`: passes only
   `FWRITE|FNONBLOCK` (if `vp->v_writecount`) or `FNONBLOCK`.  **FREAD is
   never passed.**
3. `fifo_close` (`sys/vfs/fifofs/fifo_vnops.c:610-614`): `fi_readers--`
   happens only under `ap->a_fflag & FREAD` -> stays 1.
4. Destroy condition `fi_readers == 0 && fi_writers == 0`
   (fifo_vnops.c:620-622) never fires; `v_fifoinfo` and the connected
   socket pair (socreate x2 + unp_connect2, fifo_vnops.c:194-216) leak.
5. The later userspace close of the (now dead) vnode goes to
   `dead_close` (sys/vfs/deadfs/dead_vnops.c:118-133), which only
   clamps v_opencount/v_writecount and never reaches the fifo layer.

For the O_RDWR fd in the PoC the first (and only) loop iteration passes
`FWRITE|FNONBLOCK`, decrementing only `fi_writers`; `fi_readers` remains
1 forever.  Each repetition of the scenario leaks 2 sockets + 1
`fifoinfo` (~1 KiB) — unbounded with repeated mounts.

## Impact
Permanent kernel memory/socket leak, root-triggered (`umount -f`,
shutdown of mounts with orphaned fifo descriptors — SCM_RIGHTS in
flight, descriptor held by a dying-but-unkillable process, etc.).
Not memory corruption: the leaked objects stay referenced and consistent.

## Fix validation (see run.2.log / fix logs)
`fix.diff` (this directory) makes the force-close loop VFIFO-aware
(FREAD|FWRITE / FREAD flags) and clamps fifo_close's decrements.
Applied to a clean-source guest, kernel rebuilt with
`make nativekernel`, guest rebooted:

- baseline PoC behavior pre-patch (stock kernel #0): leak reproduced
  (6 sockets persisting; see run.log).
- post-patch: `after umount -f + close ...: 4 stream sockets` — back to
  baseline, leak gone; no panic; normal fifo open/close/read/write and
  the SIGINT-kill protocol unaffected (regression checks in fix_run.log).

## Chain summary
unpriv user -> NOT applicable; requires root's umount -f (or shutdown) +
a fifo fd that no process can be forced to close.  Pure resource leak.

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