DF-3117 / verdict.json
{ "finding_id": "DF-3117", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "Reproduced twice (once attribution-clean on a fresh vm.sh reset with-src guest): 30s of unprivileged racing \u2014 38,661 cross-parent DIRECTORY renames (each running doscheckpath with tdvp unlocked) against ~100k file creates in the target parents, all on a stock FAT32 image \u2014 leaves the msdosfs mount with leaked references (kernel diagnostic showed 2 mount refs still present in the first occurrence). After all racers exit (verified zero leftover processes), umount hangs forever and the guest subsequently goes fully catatonic: sshd stops accepting (banner timeout), serial console freezes, no panic, no DDB; vm.sh reports down while QEMU stays alive. Control run with identical creator churn against same-dir FILE renames (no doscheckpath) unmounts instantly and fscks clean, isolating the trigger to the directory-rename/doscheckpath/deget path. The exact leaking statement is not line-pinned (sequentially-balanced ref protocol on all hand-traced paths, incl. degets clears-*depp-on-error contract); needs refcount-instrumented kernel build upstream.", "exploit_chain": "unprivileged user with write access to one directory on any mounted msdosfs -> run bouncer (cross-parent dir renames into a deep parent) + creator (create churn) for ~30s -> mount/vnode references leak -> umount(2) of the filesystem hangs forever -> system-wide wedge (all userland eventually starves; hard poweroff required).", "evidence": [ "findings/poc/DF-3117/run.10.wedge.log \u2014 decisive attribution-clean run: racers exit, leftover procs: none, umount watchdog never completes, ssh channel dies mid-probe", "findings/poc/DF-3117/run.9.log \u2014 first occurrence: same shape, umount stage hang", "findings/poc/DF-3117/VERDICT.md \u2014 full narrative incl. console diagnostics (unmount ... 2 mount refs still present; kern_rename: retry due to race) and the control run", "findings/poc/DF-3117/wedge.sh \u2014 exact reproducible script" ], "kernel_refs": [ "sys/vfs/msdosfs/msdosfs_vnops.c:916-1294", "sys/vfs/msdosfs/msdosfs_vnops.c:1031-1070", "sys/vfs/msdosfs/msdosfs_lookup.c:792-872", "sys/vfs/msdosfs/msdosfs_denode.c:236-428", "sys/kern/vfs_syscalls.c:4210-4340", "sys/kern/vfs_default.c:953-1069" ], "poc_changes": "Same harness as DF-3116 (trigger.c authored from scratch; see DF-3116 poc_changes). wedge.sh added for attribution-clean single-shot reproduction: fresh guest, fresh image, racers verified dead, umount under 20s watchdog.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 150, "guest_dirty": 0, "build_cmd": "sh build.sh (cc -O2 -Wall -o trigger trigger.c)", "run_cmd": "sh wedge.sh (as root on the guest; racers run as nobody)", "code_hash": "15d8f4155d55924053327ae196acb62fe4a18a8285d0dd0c3a5697e88dc7e1b2", "notes": "Wedge leaves the guest unusable (no panic/dump) \u2014 vm.sh reset with-src required after each repro; guest was reset and is clean. Root-cause pinning requires a VFS-refcount-debug kernel build; suspects: vref(tdvp)+doscheckpath vput pairing under kern_rename EAGAIN retry (vfs_syscalls.c:4330), relookup-found-tvp combinations (vnops:1056-1102), deget error-path denode left hash-resident (msdosfs_denode.c:363-376).", "recommended_fix": "Reproduce under VFS refcount instrumentation on the wedge.sh workload and fix the leaking statement in the msdosfs rename/doscheckpath/compat chain; until then this is an unprivileged full-system availability bug.", "fix_status": "not_testable", "fix_kernel_uname": "", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "No fix authored: the leaking statement is not line-pinned (sequentially-balanced ref protocol on every hand-traced path; leak manifests only under a specific interleaving). Requires refcount-instrumented kernel build upstream.", "fix_evidence": "" } |