β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3074

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3074 Β· 7 files
FileTypeDescriptionSize
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.

VERDICT.md
↓ download raw

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_testable
↓ fix.diffper-fix-DF-3074

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