afd_strategy(): no mediasize bounds check and 32-bit LBA truncation β out-of-range raw I/O wraps onto low LBAs instead of failing
Summary
bio_offset narrows to u32 and rides 32 CDB LBA bits with no clamp on the raw path (unlike ad_strategy which keeps u64) - I/O beyond 2^32 sectors that must EINVAL silently writes to (offset/sectorsize) mod 2^32, clobbering the start of the medium. Data-integrity class (the DF-4798 'size lie' family). Reject-beyond-mediasize fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4877 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.2 KB | β raw | |
| VERDICT.md | β | 2.0 KB | β raw | |
| env.txt | β | 195 B | view raw | |
| fix.diff | β | 827 B | view raw | |
| manifest.json | β | 566 B | view raw | |
| verdict.json | β | 2.1 KB | view raw |
DF-4877 β afd_strategy(): no media-bounds check + 32-bit LBA truncation
sys/dev/disk/nata/atapi-fd.c:258, 277-280:
u_int32_t lba;
...
lba = bp->bio_offset / fdp->sectorsize; /* u64 offset -> u32 lba */
...
ccb[2] = lba >> 24; ccb[3] = lba >> 16; /* 32-bit LBA in the CDB */
ccb[4] = lba >> 8; ccb[5] = lba;
- No bounds check:
afd_strategy()never comparesbio_offset(or the transfer end) againstfdp->mediasize. The raw-cdev path does not do it either:bounds_check_with_mediasize()(sys/kern/subr_disk.c:1458) is only used by device-mapper; a raw read/write on/dev/afd0goes physio βafd_strategywith whatever offset the caller passes. - 32-bit truncation: unlike
ad_strategy()which keeps the LBA in a u_int64 (request->u.ata.lba, ata-disk.c), the afd driver narrows the block number tou_int32_t, and ATAPI_READ_BIG/WRITE_BIG carry only 32 LBA bits.
Net effect: any I/O at bio_offset β₯ 2^32 * sectorsize (2 TiB at 512B) β
which must fail as out-of-range β silently wraps onto low LBAs. A write
the caller intended for beyond-the-end (expecting EINVAL) instead lands at
(offset/sectorsize) mod 2^32 β e.g. LBA 0..N, clobbering the start of
the medium. Floppy-class media can never legitimately reach 2 TiB, so on
an honest device every wrapped access is out-of-bounds by construction.
Threat model
The raw device already grants full-media read/write to its opener (typically root/operator), so this is not a privilege boundary crossing by itself; the security-relevant delta is silent misplacement of I/O that the kernel contractually must reject (correctness β data-integrity), matching the "geometry lie" class of DF-4798.
Status: untested (in situ) β requires an afd device
The audit guest has no ATAPI direct-access device (see DF-4874 pack,
run.log), so the wrap cannot be demonstrated on-target. The trace is
complete in source: no clamp before atapi-fd.c:258, and the CDB fields
hold at most 32 bits (atapi-fd.c:277-280).
Fix
fix.diff: reject any bio that starts at/after mediasize or whose end
passes it (EINVAL) before building the CDB β mirroring
bounds_check_with_mediasize() semantics for the raw path.
DF-4877 VERDICT β afd_strategy missing bounds check + u32 LBA wrap
Status: untested in situ (hardware absent); established by line trace
Root cause
lba = bp->bio_offset / fdp->sectorsize;assigns a 64-bit byte offset (in sectors) intou_int32_t lba(sys/dev/disk/nata/atapi-fd.c:241, 258) β silent truncation.- Nothing between
physioand the CDB build bounds-checks the I/O: -afd_strategy()has nomediasizecomparison (whole function, atapi-fd.c:233-316); - the raw cdev path applies no disk-layer clamp βbounds_check_with_mediasize()exists (sys/kern/subr_disk.c:1458-1478) but its only caller is device-mapper (sys/dev/disk/dm/device-mapper.c:400); - contrast withad_strategy()which at least keeps the LBA 64-bit (sys/dev/disk/nata/ata-disk.c:299). - The CDB carries 32 LBA bits (atapi-fd.c:277-280), so the wrap is not even detectable downstream.
Consequence
I/O that must be rejected as out-of-range instead targets
(bio_offset/sectorsize) mod 2^32: silent wrong-block writes on the raw
device. Not a privilege escalation (the raw device already grants the
medium to its opener) β a kernel contract violation in the same
"geometry/size lie" family as DF-4798.
Why untested
Requires an attached ATAPI direct-access device; the audit guest cannot emulate one (QEMU 7.2: no ATAPI floppy class β DF-4874/run.log records "afd0 device_t is NULL" from the loaded driver). Every element of the trace was verified in source instead.
Fix validation
fix_status: not_testable (same hardware blocker). fix.diff adds the
explicit media-bounds rejection before the CDB build; semantics match
bounds_check_with_mediasize() (reject past-EOF with EINVAL).
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableNo afd hardware on guest; fix adds the missing media-bounds rejection with bounds_check_with_mediasize()-equivalent semantics
fix.diff (git apply --check OK)
Confirmed kernel references
Detail
Exploit chain
raw open /dev/afd0 -> pwrite at offset >= 2 TiB (legitimately out-of-range) -> lba = (offset/sectorsize) mod 2^32 (atapi-fd.c:258) -> ATAPI_WRITE_BIG CDB with wrapped LBA (atapi-fd.c:277-280) -> silent write to low blocks instead of EINVAL
Evidence (decisive lines)
VERDICT.md (trace: no clamp in strategy; dm-only bounds helper; ad keeps u64 lba); README.md
PoC changes
n/a β source-trace finding; hardware blocker shared with DF-4874
Verified recommended fix
reject bio_offset/end beyond mediasize with EINVAL before building the CDB in afd_strategy()
Verdict
afd_strategy() never bounds-checks bio_offset against mediasize (and the raw cdev path applies no clamp β bounds_check_with_mediasize() is dm-only), while narrowing the block number to u_int32_t lba and a 32-bit CDB LBA: any I/O at >= 2^32 sectors (2 TiB @512B) that must fail with EINVAL silently wraps onto low LBAs, so beyond-end writes clobber the start of the medium. Certain by construction; not runnable on a guest without ATAPI direct-access hardware.
No comments yet.