{
  "finding_id": "DF-5798",
  "status": "not_reproduced",
  "verdict": "Code-level race verified by source analysis but not manifested on the guest. unmount_allproc_cb() (vfs_syscalls.c:777-778) reads and cache_drop()s p->p_textnch holding only the allproc list token (allproc_scan, kern_proc.c:1401-1432), not p->p_token - the lock every other p_textnch mutation site holds (kern_exec.c:549-552, kern_exit.c:498, kern_shutdown.c:599). If the callback samples p->p_textnch.mount==mp on the old handle and exec swaps in a new handle (drop+cache_copy) before the callbacks cache_drop executes, the drop releases the NEW handles ncp/mount refs and zeroes it - a one-ref underflow on a live namecache entry (premature free -> UAF). dounmount()s MNT_FORCE retry loop re-runs the callback every iteration (up to 50 per umount -f). Stress: 6 rounds, 8x400 self-reexecing binaries on a tmpfs mount, respawning busy-holder, 10x umount -f per round (~4.5 min, >100k execs, 60 force-unmounts, 243 nlookup umount-race warnings proving heavy racing) - no panic, no divergence. The compare-to-drop gap (~tens of ns) must contain execs entire swap; window not hit in ~3000 callback scans x 10 procs. Trigger requires root (umount -f) by default; unprivileged only if vfs.usermount=1.",
  "reproduced": false,
  "impact": "none",
  "confidence": "speculative",
  "exploit_chain": "root (or usermount owner) umount -f || race exec drop/copy interleave in unmount_allproc_cb -> p_textnch new-handle ref stolen -> ncp premature free -> UAF on next exec/exit/resolve (panic to potential exploitation); chain NOT demonstrated",
  "evidence": "run.log: STRESS-DONE, mount cleaned up, no panic; dmesg.txt: 243x nlookup: warning umount race avoided (racing occurred; that defusing is nlookup-specific and does not cover p_textnch); fix.diff applies cleanly",
  "kernel_refs": [
    "sys/kern/vfs_syscalls.c:777",
    "sys/kern/vfs_syscalls.c:768",
    "sys/kern/vfs_syscalls.c:946",
    "sys/kern/kern_exec.c:549",
    "sys/kern/kern_exit.c:498",
    "sys/kern/kern_proc.c:1401"
  ],
  "poc_changes": "Wrote from scratch: reexec.c (self-reexecing binary placed on the victim mount so every exec installs p_textnch there) and stress.sh (busy-holder forcing the dounmount retry loop to iterate so the callback re-runs per iteration).",
  "attempts": 1,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 285,
  "guest_dirty": 1,
  "build_cmd": "cc -O -o /tmp/reexec /tmp/reexec.c",
  "run_cmd": "sh /tmp/stress.sh",
  "code_hash": "f8b3938b4b18e57f6516d2f3ae23fb883adc16177f57f9625618bbbf7ba9bbc4",
  "notes": "One-line fix (p_token around the drop, re-check under token) included; safe against deadlock since no other token is held across the callback at that point. Even unfixed, practical exploitability is low given the nanosecond interleave window.",
  "recommended_fix": "Take p->p_token around the p_textnch read+drop in unmount_allproc_cb() and re-check the condition under the token (see fix.diff)",
  "fix_status": "not_tested",
  "fix_baseline_reproduced": false,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff authored and git-apply-check clean; validation not applicable since the race did not reproduce in the baseline run.",
  "fix_evidence": "findings/poc/DF-5798/fix.diff"
}