hpfs_cpinit mount-time livelock: 'while (cpicnt > 0)' never terminates when every cpisec carries s_cpicnt == 0 and s_next chains (self-loop)
Summary
cpicnt (from sp_cpinum) is only decremented inside 'for (i=0; i<cpisp->s_cpicnt; i++, cpicnt--)' (:292); s_cpicnt and s_next are raw on-disk fields and CPI_MAGIC is never checked. With sp_cpinum>=1 and a cpisec with s_cpicnt==0/s_next=self, mount(2) breads the same sector forever inside hpfs_cpinit. Mounting a crafted/corrupted HPFS image (root or vfs.usermount=1): mount never completes and cannot be aborted (unkillable), guest degrades. VERIFIED: no MOUNT_RC ever, inner timeout(15) could not kill mount(2), outer ssh killed at 30s, follow-up ssh banner-timeout; guest force-killed. Fix: cap the cpisec-chain iteration count (e.g. 16) -> EINVAL (diff in pack; also fixes DF-3145).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3144 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| craft_img.py | β | 2.2 KB | view raw | |
| run.log | β | 597 B | view raw | |
| env.txt | β | 150 B | view raw | |
| fix.diff | β | 662 B | view raw | |
| build.log | β | 158 B | view raw |
Fix verification
not_testablenot_testable (no patched-kernel run for this finding)
Confirmed kernel references
Detail
Evidence (decisive lines)
['run.log: SSH_RC=124 with no MOUNT_RC ever printed; banner-timeout probe; guest force-killed']
PoC changes
none (first attempt worked)
Verified recommended fix
Bound the cpisec-chain iteration count (fix.diff); also kfree hpm_cpdblk on the error returns (DF-3145)
Verdict
Reproduced on the stock kernel: mounting (as root, via direct mount(2)) an image with sp_cpinum=1 and a cpisec carrying s_cpicnt=0 / s_next=self hangs mount(2) forever inside hpfs_cpinit's bread loop. The inner timeout(15) could not terminate the mount; the outer ssh was killed at 30s; a follow-up ssh hit 'Connection timed out during banner exchange' (same sshd-starvation signature as DF-3143). Mount never completes and cannot be aborted; reboot required. cpisec magic (CPI_MAGIC) is never checked either, but the missing loop bound is the bug.
No comments yet.