Summary
virtio-blk forwards the guest-supplied starting sector to the disk backend with only an alignment check, never a capacity check. Combined with unchecked u64 range arithmetic in the RAM/layered backends, a guest can (a) read out-of-range LBAs and receive a successful zero-filled completion, (b) write out-of-range LBAs that are accepted and stored, and (c) in checked/debug builds, trigger an integer-overflow panic (panic = "abort") that aborts the VM process.
Root cause
- virtio-blk only alignment-checks the sector; no capacity check —
vm/devices/virtio/virtio_blk/src/lib.rs:485,564-572.
- The RAM backend's bound check adds before comparing, so the add can wrap past the guard:
- read:
let end = sector + count; if end > state.sector_count { … } then state.data.range(sector..end) — vm/devices/storage/disklayer_ram/src/lib.rs:290-300. For sector = u64::MAX, end wraps to 0, the guard passes, the range is empty, and the layered read zero-fills and returns success.
- write:
if sector + count > state.sector_count { … } then state.data.entry(cur).insert(...) — disklayer_ram/src/lib.rs:210-224. A wrapped sum bypasses the guard and the write is stored at an out-of-range key and returns success.
- The layered-disk bitmap computes
start_sector + bits.len() unchecked — vm/devices/storage/disk_layered/src/bitmap.rs:69. With overflow-checks on ([profile.dev]) this panics → abort.
Reproduction
Found by virtio-villain. B0091 (read at sector u64::MAX) and B0002 (read near u64::MAX) return success with zeros; B0081 (write at sector u64::MAX) is accepted and stored. In a checked/debug build these abort the VM process.
Impact
Data-integrity/spec violation (virtio-blk §5.2.6.1: out-of-range requests must fail with S_IOERR) in release; the offending VM aborts in checked builds. Confined to the guest issuing the request.
Suggested fix
Validate start_sector and start_sector + sector_count against the disk capacity in virtio-blk (or the shared request path) using checked arithmetic, returning VIRTIO_BLK_S_IOERR for out-of-range requests; use checked/saturating arithmetic in the RAM and layered backends' bound checks.
Summary
virtio-blk forwards the guest-supplied starting sector to the disk backend with only an alignment check, never a capacity check. Combined with unchecked
u64range arithmetic in the RAM/layered backends, a guest can (a) read out-of-range LBAs and receive a successful zero-filled completion, (b) write out-of-range LBAs that are accepted and stored, and (c) in checked/debug builds, trigger an integer-overflow panic (panic = "abort") that aborts the VM process.Root cause
vm/devices/virtio/virtio_blk/src/lib.rs:485,564-572.let end = sector + count; if end > state.sector_count { … }thenstate.data.range(sector..end)—vm/devices/storage/disklayer_ram/src/lib.rs:290-300. Forsector = u64::MAX,endwraps to0, the guard passes, the range is empty, and the layered read zero-fills and returns success.if sector + count > state.sector_count { … }thenstate.data.entry(cur).insert(...)—disklayer_ram/src/lib.rs:210-224. A wrapped sum bypasses the guard and the write is stored at an out-of-range key and returns success.start_sector + bits.len()unchecked —vm/devices/storage/disk_layered/src/bitmap.rs:69. Withoverflow-checkson ([profile.dev]) this panics → abort.Reproduction
Found by virtio-villain.
B0091(read at sectoru64::MAX) andB0002(read nearu64::MAX) return success with zeros;B0081(write at sectoru64::MAX) is accepted and stored. In a checked/debug build these abort the VM process.Impact
Data-integrity/spec violation (virtio-blk §5.2.6.1: out-of-range requests must fail with
S_IOERR) in release; the offending VM aborts in checked builds. Confined to the guest issuing the request.Suggested fix
Validate
start_sectorandstart_sector + sector_countagainst the disk capacity in virtio-blk (or the shared request path) using checked arithmetic, returningVIRTIO_BLK_S_IOERRfor out-of-range requests; use checked/saturating arithmetic in the RAM and layered backends' bound checks.