nfs_mountdiskless() double-frees the dup_sockaddr() on mountnfs() failure (mountnfs's bad: path frees nm_nam via nfs_free_mount, then haderror kfrees it again)
Summary
nfs_mountdiskless() dup_sockaddr()'s nam (:745) and passes ownership to mountnfs(), which stores it as nmp->nm_nam (:1077). On failure mountnfs()'s bad: label runs nfs_free_mount(nmp) (:1167-1171), which kfrees nmp->nm_nam (:1255-1257). Control returns to nfs_mountdiskless(), whose haderror path kfrees the same nam again (:775). Source-certain double free; reachability diskless-boot only (nfs_mountroot -> nfs_mountdiskless for root or swap, e.g. NFS server unreachable or nfs_nget ENOMEM) - attacker must control the PXE/BOOTP/NFS boot environment. LAN attacker controlling the boot environment (or a merely dead NFS server) during diskless boot gets a slab double-free during an already-failing boot; realistic impact crash-of-a-crashing-boot, heap-corruption potential only in a PXE-groomed scenario. Not verified (boot-time; Low per contract). Fix: drop the kfree(nam) in the haderror path (ownership transferred). [VERIFIED pass2: diskless PXE path unreachable via harness; double-free source-certain]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3074 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 289 B | β raw | |
| VERDICT.md | β | 1.2 KB | β raw | |
| env.txt | β | 248 B | view raw | |
| fix.diff | β | 136 B | view raw | |
| manifest.json | β | 578 B | view raw | |
| run.log | β | 150 B | view raw | |
| verdict.json | β | 1.4 KB | view raw |
DF-3074 - nfs_mountdiskless() double-frees dup_sockaddr() nam on mountnfs() failure
Severity Low | verdict: not_reproduced | impact: none
Reproduce
No runnable PoC on this rig (see VERDICT.md for why).
See VERDICT.md for the full narrative and run.log for the decisive output.
DF-3074 verification
Kernel: 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
Not executable on this rig: the path is diskless-boot only (nfs_mountroot -> nfs_mountdiskless for root/swap), requiring PXE/BOOTP control of the boot environment - the vm.sh lifecycle cannot reconfigure the guest to diskless boot. Code-certain: mountnfs() takes ownership of nam (stored as nmp->nm_nam at nfs_vfsops.c:1077) and its bad: label already frees it via nfs_free_mount (:1167-1171 -> kfree nmp->nm_nam :1255-1257), then nfs_mountdiskless kfrees the same pointer again at :775. Source-certain double free; impact crash-of-an-already-failing-boot or PXE-groomed heap corruption.
Kernel references
Fix
See fix.diff.
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.
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md + run.log + sources
PoC changes
none
Verified recommended fix
diff --git a/sys/vfs/nfs/nfs_vfsops.c: drop kfree(nam) in the haderror path of nfs_mountdiskless (ownership transferred to mountnfs).
Verdict
Not executable on this rig: the path is diskless-boot only (nfs_mountroot -> nfs_mountdiskless for root/swap), requiring PXE/BOOTP control of the boot environment - the vm.sh lifecycle cannot reconfigure the guest to diskless boot. Code-certain: mountnfs() takes ownership of nam (stored as nmp->nm_nam at nfs_vfsops.c:1077) and its bad: label already frees it via nfs_free_mount (:1167-1171 -> kfree nmp->nm_nam :1255-1257), then nfs_mountdiskless kfrees the same pointer again at :775. Source-certain double free; impact crash-of-an-already-failing-boot or PXE-groomed heap corruption.
No comments yet.