diff options
author | Daniel Verkamp <dverkamp@chromium.org> | 2018-09-06 10:09:31 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-21 00:51:15 -0700 |
commit | a40cbb4a948ea826f69cb83728c31a5a253a3b1c (patch) | |
tree | cbfa493a310fbf54b98957222aa9e85ed10b56cf /devices/src/virtio/block.rs | |
parent | a0408258e09c406324ddae0aa5c30a7b75d04e31 (diff) | |
download | crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.tar crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.tar.gz crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.tar.bz2 crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.tar.lz crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.tar.xz crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.tar.zst crosvm-a40cbb4a948ea826f69cb83728c31a5a253a3b1c.zip |
devices: block: enforce read-only in execute()
To fully meet the requirements laid out by the virtio specification, we need to fail write commands for devices that expose VIRTIO_BLK_F_RO with a specific error code of VIRTIO_BLK_S_IOERR. Pipe the read_only status down into the worker and the request execute function so that it can be checked and return the correct error code. BUG=chromium:872973 TEST=Attempt to write to read-only /dev/vda in termina Change-Id: I98c8ad17fde497e5a529d9e65096fb4ef022fd65 Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1211062 Reviewed-by: Stephen Barber <smbarber@chromium.org>
Diffstat (limited to 'devices/src/virtio/block.rs')
-rw-r--r-- | devices/src/virtio/block.rs | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs index 43e81e0..4b62932 100644 --- a/devices/src/virtio/block.rs +++ b/devices/src/virtio/block.rs @@ -111,7 +111,7 @@ unsafe impl DataInit for virtio_blk_discard_write_zeroes {} pub trait DiskFile: Read + Seek + Write + WriteZeroes {} impl<D: Read + Seek + Write + WriteZeroes> DiskFile for D {} -#[derive(PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] enum RequestType { In, Out, @@ -199,6 +199,9 @@ enum ExecuteError { num_sectors: u32, flags: u32, }, + ReadOnly { + request_type: RequestType, + }, Unsupported(u32), } @@ -212,6 +215,7 @@ impl ExecuteError { &ExecuteError::TimerFd(_) => VIRTIO_BLK_S_IOERR, &ExecuteError::Write{ .. } => VIRTIO_BLK_S_IOERR, &ExecuteError::DiscardWriteZeroes{ .. } => VIRTIO_BLK_S_IOERR, + &ExecuteError::ReadOnly{ .. } => VIRTIO_BLK_S_IOERR, &ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP, } } @@ -359,6 +363,7 @@ impl Request { fn execute<T: DiskFile>( &self, + read_only: bool, disk: &mut T, flush_timer: &mut TimerFd, mem: &GuestMemory, @@ -366,6 +371,12 @@ impl Request { // Delay after a write when the file is auto-flushed. let flush_delay = Duration::from_secs(60); + if read_only && self.request_type != RequestType::In { + return Err(ExecuteError::ReadOnly { + request_type: self.request_type, + }); + } + disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT)) .map_err(|e| ExecuteError::Seek{ ioerr: e, sector: self.sector })?; match self.request_type { @@ -437,6 +448,7 @@ struct Worker<T: DiskFile> { queues: Vec<Queue>, mem: GuestMemory, disk_image: T, + read_only: bool, interrupt_status: Arc<AtomicUsize>, interrupt_evt: EventFd, } @@ -451,8 +463,12 @@ impl<T: DiskFile> Worker<T> { let len; match Request::parse(&avail_desc, &self.mem) { Ok(request) => { - let status = match request.execute(&mut self.disk_image, flush_timer, &self.mem) - { + let status = match request.execute( + self.read_only, + &mut self.disk_image, + flush_timer, + &self.mem, + ) { Ok(l) => { len = l; VIRTIO_BLK_S_OK @@ -682,6 +698,7 @@ impl<T: 'static + AsRawFd + DiskFile + Send> VirtioDevice for Block<T> { }; self.kill_evt = Some(self_kill_evt); + let read_only = self.read_only; if let Some(disk_image) = self.disk_image.take() { let worker_result = thread::Builder::new() .name("virtio_blk".to_string()) @@ -690,6 +707,7 @@ impl<T: 'static + AsRawFd + DiskFile + Send> VirtioDevice for Block<T> { queues: queues, mem: mem, disk_image: disk_image, + read_only: read_only, interrupt_status: status, interrupt_evt: interrupt_evt, }; |