Skip to content

virtio-blk: guest LBA is not bounds-checked before the disk backend, causing out-of-range reads/writes (and a panic in checked builds) #4046

Description

@jstarks

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions