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)
PoC verification
Evidence pack
findings/poc/DF-3143 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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_testablenot_testable (no patched-kernel run for this finding)
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.
No comments yet.