DF-3038 / verdict.json
{ "finding_id": "DF-3038", "status": "untested", "reproduced": 0, "impact": "dos", "confidence": "likely", "verdict": "Not executed on the guest (Low severity; Phase V skipped per audit policy). Line-traced: a crafted FAT32 directory entry with deStartCluster|deHighClust == pm_rootdirblk is remapped to MSDOSFSROOT by lookup.c:411-418, so lookup returns THE VROOT root denode (deget denode.c:327-347) for an ordinary subdirectory entry. rmdir() of that alias passes dosdirempty() on a crafted-empty root, and detrunc()'s root guard (denode.c:502) is 'VROOT && !FAT32(pmp)' so on FAT32 it proceeds to freeclusterchain() the live mount's ROOT directory chain (denode.c:523-524,602 via vnops.c:1469). rename() of the alias dodges doscheckpath's ancestor check because top-level FAT32 '..' entries report cluster 0, which early-exits the walk (lookup.c:847) before the source comparison (:843, source StartCluster is rootdirblk not 0), and the rename then overwrites root-directory entry 1 with a '..' to the new parent (vnops.c:1238-1251), clobbering a live entry and creating a namespace cycle. All effects are confined to the attacker's own crafted volume: no kernel memory-safety violation, hence Low.", "exploit_chain": "", "evidence": [ "alias.c: crafted-image recipe + full code-path trace with path:line", "VERDICT.md: root-cause narrative and 3-part fix sketch" ], "kernel_refs": [ "sys/vfs/msdosfs/msdosfs_lookup.c:411", "sys/vfs/msdosfs/msdosfs_denode.c:327", "sys/vfs/msdosfs/msdosfs_denode.c:502", "sys/vfs/msdosfs/msdosfs_vnops.c:1469", "sys/vfs/msdosfs/msdosfs_vnops.c:1230" ], "poc_changes": "n/a (analysis-only)", "attempts": 0, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64", "runtime_sec": 0, "guest_dirty": 0, "build_cmd": "n/a", "run_cmd": "n/a (see alias.c header comment for the manual recipe)", "code_hash": "n/a", "notes": "Low severity => Phase V skipped by policy (status 'untested', not 'skipped', per persist_poc.py enum). The FAT12/16 sibling variant (entry startcluster 0 -> same root alias) is blocked for rename by doscheckpath returning EINVAL (scn==0 matches source StartCluster 0 at lookup.c:843) and for rmdir by detrunc's !FAT32 VROOT guard; the FAT32 variant is the live one.", "recommended_fix": "Stop aliasing non-root dir entries to the root denode (lookup.c:411-418), make detrunc/deextend reject VROOT on all FAT types, and compare both root representations in doscheckpath.", "fix_status": "not_testable", "fix_kernel_uname": null, "fix_baseline_reproduced": null, "fix_patched_reproduced": null, "fix_verdict": "No fix kernel built: Low severity, Phase V skipped by policy. Fix sketch (3 parts) in VERDICT.md/alias.c.", "fix_evidence": "alias.c, VERDICT.md" } |