# DF-3239 VERDICT — NOT REPRODUCED (bounded attempt; defect source-proven)

## What was run
- PoC `df3239_pfd_exit_race.c` (uid 1001 maxx) on DragonFly 6.5-DEVELOPMENT
  #0 X86_64_GENERIC (stock): parent forks children that map 16 file-backed
  regions then `_exit(0)`; parent hammers 32 full `read()`s of
  /proc/child/map across each child's exit; 508,000+ rounds in 360 s
  (~1,400 rounds/s; each round performs dozens of `vn_fullpath()` calls
  that execute `p->p_fd->fd_nrdir`, vfs_cache.c:5194).

## Result
- No panic, no crash, no dmesg anomalies, guest stayed up, run exited 0.
- Honest classification: not_reproduced / reproduced=0 / impact=none.

## Why the finding still stands (source chain, line-accurate)
1. procfs_map.c:87 releases `p->p_token` for the whole walk; procfs_map.c:143
   releases the vm_map lock per entry.
2. procfs_map.c:181 `vn_fullpath(p, vp, &fullpath, &freepath, 1)` with `p`
   the *target* proc (only PHOLD'd; PHOLD does not stop exit1).
3. vfs_cache.c:5188 `kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK)` — may block —
   then vfs_cache.c:5194 `fd_nrdir = p->p_fd->fd_nrdir;` — no token, no
   spin, no NULL check. (DF-3235 capture-pointer-then-block class.)
4. kern_exit.c:382 `fdfree(p, NULL)` runs during exit1 regardless of the
   reader's PHOLD; kern_descrip.c:2722-2726 stores `p->p_fd = NULL` under
   p_spin, then kern_descrip.c:2756 `kfree(fdp, M_FILEDESC)`.
   => reader sees NULL -> kernel NULL+offset load -> panic; or sees the old
   pointer -> UAF read of freed filedesc (only pointer-compared after).

## Why it did not fire empirically
The NULL/UAF window is the two-instruction gap between loading `p->p_fd`
and loading `->fd_nrdir` (the M_WAITOK kmalloc normally returns from cache
without sleeping). DF-3238's crash (which fires in the *same* overlap of a
map read against process exit) has a per-window window and dominated the
race space during testing; DF-3238 has since been fix-validated.

## Fix recommendation (fix.diff)
Snapshot the root nchandle under the target's p_token (or take p_token
around the vn_fullpath call) AND NULL-check `p->p_fd` in cache_fullpath.
fix.diff carries both hunks. fix_status=not_testable (no baseline
reproduction to diff against; the fix compiles by inspection against the
same lines cited).

## Artifacts
- run.log — decisive 6-minute run summary (508k rounds, exit 0)
- build.log — clean compile
- fix.diff — two-hunk fix (procfs_map.c + vfs_cache.c)

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