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

hpfs_validateparent: no depth bound / cycle guard on the DE_DOWNLSN dive β€” unkillable kernel livelock and system-wide wedge via cyclic dirblk down-pointers

Summary

The dive loop follows raw on-disk DE_DOWNLSN values (:600/:615) incrementing 'level' with nothing limiting it; 'level' only decremented on the undive path (:624). Two dirblks whose DE_END|DE_DOWN entries point at each other make the walk dive forever - bread/brelse each iteration in the stat(2) syscall context. Beyond DF-0865 (the de_reclen OOB walk in the same function), this is the LSN-discipline defect, same class as DF-0858/DF-0927 but a distinct sink. Crafted image mount (root/vfs.usermount); any unpriv user stats the mountpoint (VFS_ROOT path - no dirblk name walk, so DF-0927 cannot fire first): stat never returns, SIGKILL undeliverable, ps/mount/getfsstat hang system-wide, sshd starves, clean shutdown never completes - reboot required. VERIFIED uid 1001: stat hung past timeout 25 (inner timeout(15) could not kill), ps ax rc=124, mount rc=124, banner timeouts, guest force-killed. Fix: bound dive depth at 20 -> EINVAL (diff in pack; not_testable).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3143 Β· 5 files
FileTypeDescriptionSize
craft_img.py β€” 3.4 KB view raw
run.log β€” 871 B view raw
env.txt β€” 150 B view raw
fix.diff β€” 661 B view raw
build.log β€” 160 B view raw

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

not_testable (no patched-kernel run for this finding)

↓ fix.diffper-fix-DF-3143

Confirmed kernel references

Detail

Evidence (decisive lines)

['run.log: trigger hung past timeout 25 (RC 124); post-hang probes: ps ax rc=124, mount rc=124, dmesg banner timeout; guest force-killed']

PoC changes

First run.sh died early on set -e + timeout 124; evidence re-collected with separate hard-timeout probes. Trigger is stat <mountpoint> (VFS_ROOT path) so the known DF-0927 lookup-walk cycle cannot fire first.

Verified recommended fix

Cap the dive depth in hpfs_validateparent (level > 20 -> EINVAL); see fix.diff

Verdict

Reproduced on the stock kernel: stat(2) of the mountpoint as unprivileged uid 1001 on an image whose two dirblks carry DE_END|DE_DOWN entries pointing at each other drives hpfs_validateparent into an infinite dive loop (level++ forever, bread each iteration). The stat process could not be terminated (inner timeout(15) failed; outer ssh killed at 25s), ps ax / mount / getfsstat hung system-wide, later ssh logins hit banner timeouts, and the guest could not be shut down cleanly - force-kill required. Distinct from DF-0865 (de_reclen OOB walk in the same loop): this is the missing depth bound / cycle guard on the LSN walk.