Files
cloud-hypervisor/block/src/formats/vhd/worker/common.rs
Alexander Lvov e0801bda3b block: vhd: fix incomplete bounds check in sync I/O worker
The sync I/O worker only checked that the operation offset did
not start past the end of the virtual disk (offset >= size) -
did not verify that the operation end (offset + len) stays
within bounds.

A read or write that started inside the image but extended
beyond the logical size was silently passed to the raw backend.

The async io_uring worker already had the correct check
(offset + len > size with overflow protection). I extracted it
into a shared helper in worker/common.rs and reused inside the
sync path to eliminate duplication and close the gap.

Fixes #8311

Signed-off-by: Alexander Lvov <alexander.lvov.git@gmail.com>
2026-06-17 14:26:25 +00:00

39 lines
1.1 KiB
Rust

// Copyright 2026 The Cloud Hypervisor Authors. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
use std::io;
use crate::async_io::{AsyncIoError, AsyncIoOperation, AsyncIoResult};
pub(super) fn validate_operation_bounds(op: &AsyncIoOperation, size: u64) -> AsyncIoResult<()> {
let offset = u64::try_from(op.offset()).map_err(|_| bounds_error(op, size))?;
let len = u64::try_from(op.total_len()).map_err(|_| bounds_error(op, size))?;
let end = offset
.checked_add(len)
.ok_or_else(|| bounds_error(op, size))?;
if end > size {
return Err(bounds_error(op, size));
}
Ok(())
}
fn bounds_error(op: &AsyncIoOperation, size: u64) -> AsyncIoError {
let error = io::Error::new(
io::ErrorKind::InvalidData,
format!(
"Invalid request offset {} and length {}, can't exceed file size {}",
op.offset(),
op.total_len(),
size
),
);
if op.is_read() {
AsyncIoError::ReadVectored(error)
} else {
AsyncIoError::WriteVectored(error)
}
}