{
  "finding_id": "DF-5809",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "vfs_export_lookup() (vfs_subr.c:2297-2342) returns a struct netcred* after releasing NE_LOCK; every VFS_CHECKEXP consumer (ufs_vfsops.c:246-251 et al.) reads netc_exflags and keeps &netc_anon across the whole NFS request, while vfs_export(MNT_DELEXPORT) kfree()s those netcreds under the same lock with no refcount. KLD rig modeling the NFS-server hold window observed 258/492 held netcreds change identity mid-hold (freed and slab-reused by the replacement export) - use-after-free by construction. Ceiling: stale/garbage export-flags and anonymous credentials used to authorize NFS requests (credential confusion) or a crash on unlucky reallocation; observed impact in the rig was benign reuse (no panic), hence impact recorded as dos with cred-confusion noted.",
  "exploit_chain": "root mountd re-export loop (mountctl SET_EXPORT DELEXPORT|EXPORTED) racing the consumer: lookup returns np -> NE_UNLOCK -> consumer holds np across request (ms window) -> DELEXPORT kfrees np -> next export reallocates the slot -> consumer reads replacement/garbage credential; remote unauthenticated NFS peer is the consumer side in production",
  "evidence": "dmesg.txt (ncrace: UAF-use #1..#10, exflags 4020100->8020100 marker flips, lookups=543 holds=492 hits=258); ncrace.c/exploop.c rig; env.txt",
  "kernel_refs": ["sys/kern/vfs_subr.c:2297-2342", "sys/kern/vfs_subr.c:2166-2212", "sys/vfs/ufs/ufs_vfsops.c:246-251", "sys/vfs/tmpfs/tmpfs_vfsops.c:527-532", "sys/vfs/hammer2/hammer2_vfsops.c:2848-2851"],
  "poc_changes": "rig built from scratch: kernel module (kthread consumer on a tmpfs export, sysctl-controlled) + root userland export-churn loop with alternating markers; nullfs abandoned (mountctl EINVAL on its root vnode), tmpfs used",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 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": 1200,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o /tmp/exploop exploop.c; (cd /root/ncrace && make)  # KMOD",
  "run_cmd": "mount -t tmpfs none /mnt/t; kldload ncrace.ko; sysctl debug.ncrace.run=1; /tmp/exploop /mnt/t 10; sysctl debug.ncrace.stat",
  "code_hash": "see SHA256SUMS",
  "notes": "free side requires a privileged re-export (mountd churn) racing unauthenticated-remote NFS consumers; the rig reproduces the protocol violation deterministically-enough (52% of holds). No panic observed (benign slab reuse into the next netcred).",
  "recommended_fix": "return the fields, not the object: extract exflags + snapshot netc_anon while NE_LOCK is held (vfs_export_lookup_locked in fix.diff) and convert all checkexp consumers",
  "fix_status": "not_tested",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix requires converting every VFS_CHECKEXP caller to the locked-copy API (multi-file change); the vfs_subr.c side is drafted in fix.diff but was not built/validated on the guest within this run - the rig proves both the broken protocol and the property the fix must provide (no post-unlock dereference)",
  "fix_evidence": "fix.diff; VERDICT.md"
}
