Skip to content

Commit 7f2ebd8

Browse files
rbradfordretrage
authored andcommitted
block: Error out on write/flush if device is read-only
TEST=Boot cloud-hypervisor with read-only block device and observe that writes generate errors in the EFI/boot loader code but the OS continues to boot. Fixes: #209 Signed-off-by: Rob Bradford <[email protected]>
1 parent a7bc284 commit 7f2ebd8

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

src/block.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct UsedElem {
6363
pub struct VirtioBlockDevice<'a> {
6464
transport: &'a mut dyn VirtioTransport,
6565
state: RefCell<DriverState>,
66+
read_only: bool,
6667
}
6768

6869
#[repr(C)]
@@ -147,12 +148,14 @@ impl<'a> VirtioBlockDevice<'a> {
147148
VirtioBlockDevice {
148149
transport,
149150
state: RefCell::new(DriverState::default()),
151+
read_only: false,
150152
}
151153
}
152154

153155
pub fn init(&mut self) -> Result<(), VirtioError> {
154156
const VIRTIO_SUBSYSTEM_BLOCK: u32 = 0x2;
155157
const VIRTIO_F_VERSION_1: u64 = 1 << 32;
158+
const VIRTIO_BLK_F_RO: u64 = 1 << 5;
156159

157160
const VIRTIO_STATUS_RESET: u32 = 0;
158161
const VIRTIO_STATUS_ACKNOWLEDGE: u32 = 1;
@@ -181,8 +184,11 @@ impl<'a> VirtioBlockDevice<'a> {
181184
return Err(VirtioError::LegacyOnly);
182185
}
183186

187+
// Detect if device is read-only
188+
self.read_only = (device_features & VIRTIO_BLK_F_RO) == VIRTIO_BLK_F_RO;
189+
184190
// Don't support any advanced features for now
185-
let supported_features = VIRTIO_F_VERSION_1;
191+
let supported_features = VIRTIO_F_VERSION_1 | VIRTIO_BLK_F_RO;
186192

187193
// Report driver features
188194
self.transport
@@ -329,10 +335,16 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
329335

330336
impl<'a> SectorWrite for VirtioBlockDevice<'a> {
331337
fn write(&self, sector: u64, data: &mut [u8]) -> Result<(), Error> {
338+
if self.read_only {
339+
return Err(Error::BlockNotSupported);
340+
}
332341
self.request(sector, Some(data), RequestType::Write)
333342
}
334343

335344
fn flush(&self) -> Result<(), Error> {
345+
if self.read_only {
346+
return Err(Error::BlockNotSupported);
347+
}
336348
self.request(0, None, RequestType::Flush)
337349
}
338350
}

0 commit comments

Comments
 (0)