DragonFlyBSD Kernel Audit
DF-3061 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3061",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "nfs_namei()'s retry protocol (nfs_subs.c:1003) rescues only nd->nl_path before nlookup_init_raw() bzero()s the reused nlookupdata, leaking the exclusively-locked leaf ncp, its cache ref, root/jail refs and a crhold'd ucred; nfsrv_rename()'s 'goto again' retry (nfs_serv.c:2255) additionally leaves stale fnchd_status/tnchd_status and fdirp/tdirp, driving double cache_unlock/cache_drop/vrele on the second iteration's failure path. Racing RENAME RPCs against concurrent rename/unlink of the same exported names triggers the retry and panics the kernel in the nfsd process (lockmgr_release+0x11, fault 0xc8 = NULL ncp's nc_lock at offset 0xc0). Reproduced 2/2 on the stock INVARIANTS guest (~2.5 min of racing each); fix validated: patched kernel survived >6 min of the identical race with 8 retry events and zero traps/panics.",
  "exploit_chain": "authorized NFS client -> racing RENAME(src,dst) vs concurrent rename/unlink on the exported tree -> nfsrv_rename topology-revalidation retry fires -> nfs_namei isretry bzero of live nlookupdata + stale status/dirp cleanup -> lock operation on stale/NULL ncp -> Fatal trap 12, all CPUs stopped (remote kernel DoS). Refcount-underflow components (double cache_drop, double vrele) are present as potential memory-corruption primitives; uid0 chain not developed.",
  "evidence": [
    "panic.txt / panic_run2.txt: both baseline panics, each immediately preceded by the 'nfs - retry rename src to dst' console marker",
    "panic_boot_full.log: full serial console of baseline run 1",
    "run.log: baseline runs 1+2 results, the patched-kernel fix run (8 retries, 0 Fatal, >6 min race), and the verbatim kernel build/install completion banners (build.log itself was lost to a failed scp before the guest reset)",
    "fix.diff: nfs_subs.c retry-path nlookup_done() + nfs_serv.c status/pointer reset",
    "env.txt: guest uname + toolchain"
  ],
  "kernel_refs": [
    "sys/vfs/nfs/nfs_subs.c:1003",
    "sys/vfs/nfs/nfs_subs.c:1155",
    "sys/vfs/nfs/nfs_serv.c:2255",
    "sys/vfs/nfs/nfs_serv.c:2382",
    "sys/kern/vfs_nlookup.c:265",
    "sys/kern/vfs_nlookup.c:366",
    "sys/kern/vfs_cache.c:1154",
    "sys/sys/namecache.h:146"
  ],
  "poc_changes": "PoC authored fresh for this finding (no seed). Key tuning: the server-side racer must delete/recreate 'src' only ~1/64 of iterations so client RENAME RPCs actually reach nfsrv_rename's fromnd lookup (constant deletion makes the client fail its own pre-checks and no RENAME RPC is sent); WebNFS-free plain v3 mount over loopback; 2 racers + 6 client hammers repro in ~2.5 min.",
  "attempts": 5,
  "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 (baseline); #1: Sat Sep 5 19:57:12 UTC 2026 (patched)",
  "runtime_sec": 1080,
  "guest_dirty": 1,
  "build_cmd": "cd /usr/src && patch -p1 < /tmp/fix.diff && make nativekernel KERNCONF=X86_64_GENERIC && make installkernel KERNCONF=X86_64_GENERIC",
  "run_cmd": "./run.sh (in-guest: nfsd+mountd+loopback mount, 2x rc4 /export, 6x cl /mnt/nfs, ~2.5 min to panic on stock kernel)",
  "code_hash": "03d85e1eeba2a3d134a075f2ca22042ba66f466749aceb35f83cc91d9aa17507 (run.sh, the authoritative repro script; racer.c 3ad8cd357e239a211c61066d0dab9533284afb0cee280ad89104e8691a10b4c4)",
  "notes": "Post-race umount of the loopback NFS mount hung the guest's login path on the patched kernel; unattributable (stock never reaches umount - it panics first) and does not affect the fix criterion. Two earlier race configurations (full-speed racer, non-overlapping names) produced 0 hits - see poc_changes for the working recipe. Guest left reset-with-src clean.",
  "recommended_fix": "In nfs_namei() retry path, call nlookup_done(nd) after rescuing the path buffer; in nfsrv_rename() retry branch, zero fnchd_status/tnchd_status and NULL fdirp/tdirp after releasing them.",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sat Sep 5 19:57:12 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Patched kernel ran the identical race >2x the baseline panic time with 8 'nfs - retry rename' events and zero traps/panics (baseline: 2/2 panics in ~2.5 min).",
  "fix_evidence": "run.log (fix-validation section incl. verbatim 'Kernel build for X86_64_GENERIC completed' and 'Kernel install ... completed' banners); fix_kernel_uname (#1 Sep 5 19:57:12 UTC 2026)"
}