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)
PoC verification
Evidence pack
findings/poc/DF-3060 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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.
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_testableConfirmed 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).
No comments yet.