# DF-5831 VERDICT — REPRODUCED (kernel panic, remotely triggerable via NFS)

## Bottom line

**Reproduced on the first guest run, in under two minutes of racing.**
The stock INVARIANTS guest (DragonFly 6.5-DEVELOPMENT, see `env.txt`)
panicked in the **nfsd** process with exactly the predicted signature:

```
kern_rename: retry due to race on: "sub" -> "sub2" (16,0)
Fatal user address access from kernel mode from nfsd at ffffffff806dac71
Fatal trap 12: page fault while in kernel mode
fault virtual address	= 0x0
...
Stopped at      cache_copy+0x11:        movq    (%rdi),%r13
```

(`panic.txt` — captured from the serial console; the run started at
10:43 UTC, the ssh session died and the guest was `down` by 10:46 UTC.)

## Why this is the bug I claimed (not some other crash)

1. `Stopped at cache_copy+0x11: movq (%rdi),%r13` — `cache_copy`'s first
   instruction sequence loads `nch->ncp` (`ncp` is the first member of
   `struct nchandle`, sys/sys/namecache.h); the fault is a **read at
   virtual address 0x0** with `%rdi == NULL`, i.e. the *first argument*
   of `cache_copy()` was NULL.
2. `cache_copy(nd->nl_basench, ...)` is called with a NULL first argument
   from exactly one site reachable in the nfsd process:
   **sys/kern/vfs_nlookup.c:1380** (nlookup's `doretry` reset block).
   The other four call sites (vfs_nlookup.c:150, 160, 171, 242) pass
   `&fd_ncdir` / `&fd_nrdir` / `&fp->f_nchandle` — never NULL.
3. `nfs_namei()` (sys/vfs/nfs/nfs_subs.c:1155) initializes its `nd` with
   `nlookup_init_raw()`, which `bzero()`s the whole structure and never
   sets `nl_basench` (vfs_nlookup.c:265 vs. :280-290).  Every server-side
   name RPC (LOOKUP/CREATE/REMOVE/RENAME/...) goes through it.
4. The doretry fired on a **namecache generation change**: the console
   shows `kern_rename: retry due to race on: "sub" -> "sub2"` immediately
   before the trap — my racer was renaming the looked-up directory
   `sub <-> sub2`, and `_cache_unlink_parent()` + `_cache_link_parent()`
   both `_cache_ncp_gen_enter/exit()` the renamed ncp (sys/kern/
   vfs_cache.c:783/840, 2155), which `nlookup()` detects at
   vfs_nlookup.c:1313-1332 and turns into `doretry = TRUE`.
5. Current process = nfsd (pid 1025) — the NFS **server** thread, i.e.
   the crash was driven by client RPCs racing a concurrent rename, not by
   the local racer's own path (a local rename uses `nlookup_init()` and
   has a valid `nl_basench`).

## Exploit chain / impact

Remote denial of service (kernel panic) of an NFS server by any client
permitted by the exports: hammer LOOKUP RPCs on names inside a directory
while the same (or another) client renames that directory. No
authentication beyond the export ACL. Also reachable as a reliability
crash by ordinary concurrent NFS workloads. The fault is a deterministic
NULL deref — no memory-corruption primitive, no uid0 route (the guest is
an intentionally permissive target, but NULL page mapping is not
attacker-controllable here; this is panic-class only).

## Fix validation

`fix.diff` (git-apply-able against the audit tree; applied with
`patch -p1` inside the guest's `/usr/src`):

* `nlookup_init_raw()` / `nlookup_init_root()` now store a private,
  ref-held copy of the start handle in a new `nl_basench_store` field of
  `struct nlookupdata` and point `nl_basench` at it;
* `nlookup_done()` drops the store.

Baseline (stock kernel): panic in nfsd ≤ 2 minutes into the rig
(`panic.txt`).
Patched (kernel rebuilt with `make nativekernel KERNCONF=X86_64_GENERIC`,
rebooted): the **identical rig** ran to completion twice — full 300 s
race window each, racers verified running, `mount | grep nfs` verified,
no panic, guest stayed up, script printed `NO PANIC` (`run.log`,
`run.2.log`). The previously-observed bad behavior is gone.

## Kernel references

* sys/kern/vfs_nlookup.c:1367-1385 — retry block, `cache_copy(nd->nl_basench, ...)` at :1380
* sys/kern/vfs_nlookup.c:255-291 — `nlookup_init_raw()` never sets `nl_basench`
* sys/kern/vfs_nlookup.c:297-335 — `nlookup_init_root()` same
* sys/kern/vfs_cache.c:996-1000 — `cache_copy()` derefs `nch->ncp` (offset 0)
* sys/vfs/nfs/nfs_subs.c:1155 — `nfs_namei()` uses `nlookup_init_raw()`
* sys/kern/vfs_cache.c:783/840, 2155 — rename bumps `nc_generation` (`_cache_ncp_gen_enter/exit`)
* sys/kern/vfs_nlookup.c:1313-1332 — generation-change → `doretry`

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