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

cd9660_ioctl's catch-all ENOTTY hides FIOSEEKDATA/FIOSEEKHOLE from cd9660 (lseek SEEK_DATA returns EINVAL) and leaves cd9660_bmap's alignment-only contract one wiring away from an unprivileged INVARIANTS panic

Summary

cd9660 is the only mainstream filesystem not wired into DragonFly's SEEK_DATA/SEEK_HOLE infrastructure: cd9660_ioctl intercepts every ioctl and returns ENOTTY except FIOGETLBA, so lseek(SEEK_DATA/SEEK_HOLE) on any cd9660 file returns EINVAL while ufs/ext2/hammer2 all dispatch to vn_bmap_seekhole. This gap is today the ONLY thing keeping cd9660_bmap's KKASSERT((loffset & (bsize-1))==0) (:76) unreachable: vn_bmap_seekhole_locked passes the raw user-supplied file offset to VOP_BMAP on its first loop iteration ('noff += bsize - noff % bsize' only aligns subsequent iterations), so wiring cd9660 up the way the other filesystems are wired would make 'lseek(fd, 1, SEEK_DATA)' - unprivileged, needing only read access to any file on a mounted ISO - panic every INVARIANTS/DEBUG kernel instantly. No impact as shipped (unreachability proven by enumeration of all seven VOP_BMAP caller classes + the ENOTTY catch-all). Latent trap + functional gap. Fix (either suffices): make cd9660_bmap tolerant (round loffset down instead of asserting - the mapping is a pure offset shift, so rounding is semantically correct); optionally wire FIOSEEK* through vn_bmap_seekhole for parity. [VERIFIED pass2: reproduced - lseek SEEK_DATA HOLE EINVAL on cd9660 vs ufs working; F40FIX wires FIOSEEKDATA HOLE through vn_bmap_seekhole, aligned and unaligned work no panic]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3257 Β· 6 files
FileTypeDescriptionSize
README.md β€” 261 B ↓ raw
df3257.c β€” 674 B view raw
fix.diff β€” 1.1 KB view raw
manifest.json β€” 395 B view raw
run.log β€” 445 B view raw
verdict.json β€” 1.8 KB view raw

DF-3257 evidence pack

What

cd9660_ioctl ENOTTY hides FIOSEEKDATA/FIOSEEKHOLE (and the bmap KKASSERT is one wiring away)

Verdict

status=reproduced impact=none confidence=certain

See VERDICT.md for the full narrative and fix.diff for the verified fix.

Fix verification

fixed

A/B complete: lseek(SEEK_DATA/SEEK_HOLE) on cd9660 now returns 0/filesize (stock: EINVAL); unaligned lseek(1,SEEK_DATA) also works with no KKASSERT panic, validating the bmap alignment companion fix.

↓ fix.diffper-fix-DF-3257

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md with path:line citations; run.log where a live demo exists; fix.diff

PoC changes

n/a

Verified recommended fix

align loffset down in cd9660_bmap; dispatch FIOSEEKDATA/FIOSEEKHOLE to vn_bmap_seekhole

Verdict

Reproduced on the stock INVARIANTS guest: lseek(fd, 0, SEEK_DATA) and SEEK_HOLE on a cd9660 file both return EINVAL (cd9660_vnops.c:226 catch-all ENOTTY) while the same calls on a UFS file return 0/58 - cd9660 is the only mainstream filesystem not wired into the SEEK_DATA/SEEK_HOLE infrastructure. The findings second half is confirmed from source: vn_bmap_seekhole_locked hands the RAW user offset to VOP_BMAP on its first iteration, so the naive wiring would reach cd9660_bmaps KKASSERT((loffset & (bsize-1))==0) at cd9660_bmap.c:76 with lseek(fd,1,SEEK_DATA). The fix wires both ioctls to vn_bmap_seekhole AND aligns the offset down inside cd9660_bmap; compiled in the F40FIX build; post-fix A/B: lseek SEEK_DATA/SEEK_HOLE on cd9660 return 0 and filesize.