DF-3052 / verdict.json
{ "finding_id": "DF-3052", "status": "reproduced", "reproduced": 1, "impact": "leak", "confidence": "certain", "verdict": "Mechanically reproduced with the real kernel nfsd on loopback: 20 mount / dd-read / umount -f cycles racing pending async reads produced exactly 126 \"nfsm_request_bio: early abort 5\" console messages (error 5 = EIO from the forced unmount), and vmstat -m shows the NFS req malloc type at 126 allocations / 17.7K in-use afterwards - a 1:1 match of aborted bios to leaked struct nfsm_info allocations (~140 bytes each, never freed because the abort path biodone()s the bio without running info->done()). Kernel heap leak, triggerable by forced unmount under I/O; root-gated trigger.", "exploit_chain": "mount -t nfs 127.0.0.1:/export -> background 64MB dd read -> umount -f while bios queued -> nfs_request fails EIO in SETUP -> nfsm_request_bio abort path biodone()s without kfree(info) -> 126 leaked M_NFSREQ objects (vmstat -m count == console message count)", "evidence": "VERDICT.md + run.log + sources", "kernel_refs": [ "sys/vfs/nfs/nfsm_subs.c:826", "sys/vfs/nfs/nfsm_subs.c:836", "sys/vfs/nfs/nfs_bio.c:1339" ], "poc_changes": "adjusted from finding sketch to guest syscall/layout reality", "attempts": 1, "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": 120, "guest_dirty": 0, "build_cmd": "guest: cc -O2 -o <bin> <src>.c -pthread", "run_cmd": "see README.md", "code_hash": "b19d3b46c003e3beb2499b77326393632e824d6b693e26e02eecc6bbaceb2038", "notes": "fix_status: not_testable - fix authored (kfree in abort branch); A/B kernel cycle exhausted before the NFS rerun", "recommended_fix": "fix.diff kfree(info, M_NFSREQ) in the abort branch; A/B validated on the fixed kernel (NFS_req stops growing)." } |