{
  "finding_id": "DF-3009",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Malicious NFS-over-TCP server replies to any kernel RPC with a 4-byte zero-length LASTFRAG record mark (0x80000000). nfs_receive() only checks len > NFS_MAXPACKET (nfs_socket.c:653), so len==0 is accepted; the body receive returns success with an empty mbuf chain because sorecvtcp() takes the resid==0 fast path (uipc_socket.c:1723) and the short-receive guard 0!=0 does not fire (nfs_socket.c:672). nfs_reply() then executes info.dpos = mtod(info.mrep == NULL, caddr_t) at nfs_socket.c:862 - a kernel load from VA 0x10 (offsetof m_hdr.mh_data) - and panics the client. Reproduced on the stock guest: Fatal trap 12, fault VA 0x10, Stopped at nfs_reply+0x622: movq 0x10(%rax),%rax, guest down, triggered by stat on the mounted filesystem. Fixed by rejecting len==0 (mirroring the server-side ns_reclen<=0 check at nfs_socket.c:2743) plus an sb_mb==NULL guard; on the patched kernel the same PoC logs 'impossible packet length (0) from nfs server' and reconnects cleanly with no panic.",
  "exploit_chain": "malicious TCP NFS server -> honest rpcbind/mountd/NULL-ping handshake -> mount_nfs -o tcp succeeds -> stat /mnt issues first kernel GETATTR -> server replies 80 00 00 00 -> nfs_receive returns success with NULL mbuf -> nfs_reply mtod(NULL) load at VA 0x10 -> page fault -> kernel panic. Primitive is a fixed-address kernel read of unmapped memory: reliable DoS/panic, no offset control, no write, no path to uid=0.",
  "evidence": [
    "panic.txt: fault virtual address = 0x10, Stopped at nfs_reply+0x622: movq 0x10(%rax),%rax (from stat)",
    "run.log: MOUNT_OK then guest death",
    "run.fixed.log + fixed.console.txt: 30x 'impossible packet length (0) from nfs server' + 'receive error 27', guest stayed up on patched kernel",
    "fix.diff: len==0 rejection + sb_mb==NULL guard"
  ],
  "kernel_refs": [
    "sys/vfs/nfs/nfs_socket.c:648",
    "sys/vfs/nfs/nfs_socket.c:653",
    "sys/vfs/nfs/nfs_socket.c:665",
    "sys/vfs/nfs/nfs_socket.c:672",
    "sys/vfs/nfs/nfs_socket.c:861",
    "sys/vfs/nfs/nfs_socket.c:862",
    "sys/kern/uipc_socket.c:1723",
    "sys/vfs/nfs/nfs_socket.c:2743"
  ],
  "poc_changes": "n/a - pack authored fresh in this run (fakesrv.c speaks rpcbind/UDP + mountd/TCP + NFS/TCP, answers userland NULL-pings honestly so mount_nfs -o tcp succeeds, replies 80 00 00 00 to every kernel RPC); run.sh needed rpcbind-free port 111 (no third-party rpcbind running)",
  "attempts": 2,
  "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": 95,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o fakesrv fakesrv.c",
  "run_cmd": "(./fakesrv &) ; mount_nfs -o tcp,port=2049 127.0.0.1:/P /mnt ; stat /mnt",
  "code_hash": "d2c8d33f324c481545251dd524adebb05d867db900968e50e59c8e6fac7af987",
  "notes": "Also reachable via the nfsiod reader thread (nfs_iod.c:96) for async bio replies. Server-side twin hypothesis (zero-length record vs nfsd) was killed: nfsrv_getstream rejects ns_reclen<=0 at nfs_socket.c:2743 - verified on guest ('impossible packet length (0) from nfs client'), pack findings/poc/DF-3010 documents the false positive. Fix build: make nativekernel + installkernel in guest; baseline panic gone on patched kernel; guest reset to clean snapshot afterwards.",
  "recommended_fix": "In nfs_receive() stream path reject zero-length record marks (len == 0 || len > NFS_MAXPACKET -> EFBIG, mirroring nfsrv_getstream's ns_reclen <= 0 check) and convert an empty body chain to EPIPE",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Sat Sep  5 05:04:56 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 guest /usr/src; make nativekernel KERNCONF=X86_64_GENERIC + make installkernel + reboot; identical PoC run: mount OK, stat did not panic, console logged the new 'impossible packet length (0)' rejection followed by normal reconnect/retry (hard-mount semantics); guest remained up.",
  "fix_evidence": [
    "run.fixed.log",
    "fixed.console.txt (30x rejection lines, zero Fatal traps)",
    "build via /root/build_fixed.log BUILD_RC=0 (in-guest)"
  ]
}