From bc6acb842f1ebb263245cd95fe5a92fe5f350bd3 Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Fri, 12 Jul 2024 22:54:12 -0700 Subject: [PATCH] block: fix `status` value size As per VirtIO spec 1.2 section 5.2.6, the `status` field is a byte, not u32. cloud-hypervisor writes an `u32` to guest memory, which accidentally zeros out the following 3 bytes, and may corrupt guest OS internal state. Signed-off-by: Changyuan Lyu --- block/src/lib.rs | 7 ++++--- vhost_user_block/src/lib.rs | 2 +- virtio-devices/src/block.rs | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/block/src/lib.rs b/block/src/lib.rs index 8fb2e91a8..d512aae85 100644 --- a/block/src/lib.rs +++ b/block/src/lib.rs @@ -164,8 +164,8 @@ pub enum ExecuteError { } impl ExecuteError { - pub fn status(&self) -> u32 { - match *self { + pub fn status(&self) -> u8 { + let status = match *self { ExecuteError::BadRequest(_) => VIRTIO_BLK_S_IOERR, ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR, ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR, @@ -180,7 +180,8 @@ impl ExecuteError { ExecuteError::AsyncWrite(_) => VIRTIO_BLK_S_IOERR, ExecuteError::AsyncFlush(_) => VIRTIO_BLK_S_IOERR, ExecuteError::TemporaryBufferAllocation(_) => VIRTIO_BLK_S_IOERR, - } + }; + status as u8 } } diff --git a/vhost_user_block/src/lib.rs b/vhost_user_block/src/lib.rs index 8f70bc678..f779fb222 100644 --- a/vhost_user_block/src/lib.rs +++ b/vhost_user_block/src/lib.rs @@ -148,7 +148,7 @@ impl VhostUserBlkThread { ) { Ok(l) => { len = l; - VIRTIO_BLK_S_OK + VIRTIO_BLK_S_OK as u8 } Err(e) => { len = 1; diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index b8302bbe2..95411bb4d 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -215,7 +215,7 @@ impl BlockEpollHandler { } else { desc_chain .memory() - .write_obj(VIRTIO_BLK_S_OK, request.status_addr) + .write_obj(VIRTIO_BLK_S_OK as u8, request.status_addr) .map_err(Error::RequestStatus)?; // If no asynchronous operation has been submitted, we can @@ -361,7 +361,7 @@ impl BlockEpollHandler { .write_latency_avg .store(write_avg, Ordering::Relaxed); - (VIRTIO_BLK_S_OK, result as u32) + (VIRTIO_BLK_S_OK as u8, result as u32) } else { error!( "Request failed: {:x?} {:?}",