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

dm_fdlist is walked and mutated without any common lock β€” nresolve's TAILQ scan races dirfs_node_setpassive's INSERT/REMOVE on SMP vkernels (UAF / list corruption)

Summary

dirfs_nresolve scans dm_fdlist under only the PARENT NODE's lock (:171-181), while dirfs_node_setpassive INSERTs/REMOVEs entries (dirfs_subr.c:812/:827) from contexts holding different or no dirfs locks: dirfs_inactive (:1391, no lock), dirfs_nremove (:913, holds the file's parent-dir lock - a different node when dirs differ), dirfs_nrename (:999, no lock), and reclaim via dirfs_node_free. A concurrent TAILQ mutation during the FOREACH_MUTABLE walk (or setname's kfree of dn_name during another thread's strcmp at :174) yields use-after-free reads / corrupted traversal in the vkernel heap. Speculative: requires multi-CPU vkernel and tight timing; single-CPU vkernels immune (cooperative serialization). Fix: mount token or dm_lock around the nresolve walk and every setpassive/insert/remove path + node lock/ref before strcmp. [VERIFIED pass2: dead code plus requires SMP vkernel; unlocked walk analysis stands from source]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3060 Β· 7 files
FileTypeDescriptionSize
README.md β€” 272 B ↓ raw
VERDICT.md β€” 1013 B ↓ raw
env.txt β€” 248 B view raw
fix.diff β€” 123 B view raw
manifest.json β€” 569 B view raw
run.log β€” 152 B view raw
verdict.json β€” 1.2 KB view raw

DF-3060 - dirfs dm_fdlist walked and mutated without a common lock

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-3060 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: dirfs is dead code on this rig (see DF-3058) and the race as filed additionally requires a multi-CPU vkernel. The unlocked-walk analysis stands from source: dirfs_nresolve scans dm_fdlist under only the parent node lock (dirfs_vnops.c:171-181) while dirfs_node_setpassive mutates the list from paths holding other/no dirfs locks (dirfs_subr.c:812/:827).

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-3060

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md + run.log + sources

PoC changes

none

Verified recommended fix

diff: mount token (or dm_lock) around the nresolve walk and every setpassive/insert/remove; node lock+ref before strcmp.

Verdict

Not executable: dirfs is dead code on this rig (see DF-3058) and the race as filed additionally requires a multi-CPU vkernel. The unlocked-walk analysis stands from source: dirfs_nresolve scans dm_fdlist under only the parent node lock (dirfs_vnops.c:171-181) while dirfs_node_setpassive mutates the list from paths holding other/no dirfs locks (dirfs_subr.c:812/:827).