{
 "finding_id": "DF-3213",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "leak",
 "confidence": "certain",
 "verdict": "Stale RC_REPSTATUS survives LRU slot reuse in the NFS server duplicate-reply cache (set at nfs_srvcache.c:337-338, never cleared anywhere; the reuse path :253-262 clears only RC_REPMBUF|RC_NAM and the mbuf-store branch :340-347 does not clear it either). A reused slot that then stores a v3 (or v2-non-repstat) reply mbuf ends up with RC_REPSTATUS|RC_REPMBUF both set, and nfsrv_getcache tests RC_REPSTATUS first (:212), serving retransmissions from rc_status \u2014 which unions rc_reply (nfsrvcache.h:54-65), i.e. the low 32 bits of the cached reply mbuf pointer. nfs_rephead (nfs_socket.c:1614-1620) transmits err & ~0x40000000 raw (31 pointer bits) when bit 30 of the pointer is set, else nfsrv_errmap clamps it to the per-proc default. Reproduced 3x in-guest (192+192+256 poisoned slots, 100%): every retransmission of a non-idempotent v3 REMOVE is answered with a wrong status-only reply whose status is the errmap default (5), not the genuine stale status (13, whitelisted, would map to itself) \u2014 proving the value read was the aliased kernel pointer, not the stored status. Raw pointer bits did not escape on this guest (mbuf zone never had bit 30 set across 640 samples), so the disclosure content is heap-placement-dependent; the duplicate-reply-cache correctness break (wrong replies to retransmissions of non-idempotent ops) reproduces deterministically. Unauthenticated remote (UDP, no creds, no valid fh, no export access). fix.diff (clear RC_REPSTATUS on reuse and on mbuf-store) validated: rebuilt kernel, 0 corruptions, byte-identical resends.",
 "exploit_chain": "unauth LAN/UDP client: (1) send M distinct NFSv2 SYMLINK (wire proc 13, zero fh) requests -> M cache entries with RC_REPSTATUS, rc_status=13; (2) send 2048-M v2 NULL fillers to fill desirednfsrvcache=2048 so the M entries are LRU-oldest; (3) send M distinct NFSv3 REMOVE (wire proc 12, zero fh) requests -> each miss evicts one stale entry and reuses the slot (RC_REPSTATUS retained), completion stores the reply mbuf -> both flags set, union holds mbuf ptr; (4) retransmit each v3 REMOVE -> RC_REPSTATUS branch -> nfs_rephead(0, nd, slp, rc_status=low32(rc_reply)) -> bit30 set: MSG_DENIED + 31 raw pointer bits; bit30 clear: status-only reply with errmap default (observed 192/192+192/192+256/256). Control entry in a clean slot resends byte-identically. No write primitive; escalation not applicable (info leak + integrity).",
 "evidence": [
  "findings/poc/DF-3213/run.log: phase A [0] reply status 0x0d (13/EACCES stored in rc_status); phase D 192/192 CORRUPT ... status=5 with full reply words; control byte-identical",
  "findings/poc/DF-3213/run.2.log, run.3.log: 192/192 and 256/256 reproductions on fresh nfsd restarts",
  "findings/poc/DF-3213/run.fixed.log: patched kernel -> 0 CORRUPT/LEAK, 192 identical resends",
  "findings/poc/DF-3213/fix.diff: clear RC_REPSTATUS in reuse path + mbuf-store branch",
  "VERDICT.md: full discrimination argument (13 whitelisted vs 5 default)"
 ],
 "kernel_refs": [
  "sys/vfs/nfs/nfs_srvcache.c:212-216",
  "sys/vfs/nfs/nfs_srvcache.c:243-263",
  "sys/vfs/nfs/nfs_srvcache.c:334-348",
  "sys/vfs/nfs/nfsrvcache.h:54-65",
  "sys/vfs/nfs/nfs_socket.c:1614-1620",
  "sys/vfs/nfs/nfs_subs.c:1481-1501",
  "sys/vfs/nfs/nfsproto.h:100"
 ],
 "poc_changes": "Original sketch had wrong wire proc numbers (v2 SYMLINK is wire 13 not 10 \u2014 v2 numbering skips 7/WRITECACHE; v3 REMOVE is wire 12 not 10 \u2014 the NFSPROC_* enum is the generic=v3 numbering) and truncated argument tails (missing the 8-word v2 filehandle / 16-word v3 fh), which triggered the NEGREPLYOUT rv==-1 path (nfsmout with mreq==NULL): no reply, no updatecache, entry stuck RC_INPROG dropping retransmits. Fixed arg shapes; added phase-A/C reply capture, the r[6] status-word discrimination print, and the clean-slot control.",
 "attempts": 4,
 "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": 480,
 "guest_dirty": 0,
 "build_cmd": "sh findings/poc/DF-3213/build.sh (in-guest cc -O2 -Wall -o leakforger leakforger.c)",
 "run_cmd": "sh findings/poc/DF-3213/run.sh (in-guest: /sbin/nfsd -u -n 4; su -m nobody -c /tmp/leakforger 192 2048)",
 "code_hash": "4c07d5794314092c6b50e26f19852d40033f392cf3592e771c37a248f9b851ef",
 "notes": "Raw pointer-value escape requires bit 30 of the cached-reply mbuf address (NFSERR_AUTHERR=0x40000000 gate); not observed on this guests mbuf zone (640/640 clamped) \u2014 disclosure content is placement-dependent, mechanism is certain. Deterministic reproduced impact: duplicate-reply cache answers retransmissions of non-idempotent ops with wrong status-only replies derived from a kernel pointer. Guest reset to clean-source snapshot after validation.",
 "recommended_fix": "Clear RC_REPSTATUS when an LRU slot is reused for a new request and before storing a reply mbuf in nfsrv_updatecache (findings/poc/DF-3213/fix.diff).",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Tue Sep 8 15:01:06 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "fix.diff applied to in-guest /usr/src, kernel rebuilt (make nativekernel) and installed as #1. Baseline stock kernel: 192/192 corrupted status-only replies (status=5). Patched kernel: 0 corruptions, 0 leaks, 192/192 byte-identical cached-reply resends; control unchanged. Bad behavior eliminated.",
 "fix_evidence": [
  "findings/poc/DF-3213/run.fixed.log (0 CORRUPT/LEAK, 192 identical)",
  "findings/poc/DF-3213/fix.diff"
 ]
}