From e1a63b41ff9764d1432e4dcdfe65822c55d40b8f Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 15 Jun 2026 21:54:44 +0200 Subject: [PATCH] virtio-devices: block: Reclaim head on malformed descriptor chain When Request::parse failed, for example for a chain containing only the head descriptor, process_queue_submit returned the error via `?`. The caller process_queue_submit_and_signal swallowed Error::RequestParsing with a warn! and returned Ok(()), but queue.iter().next() had already consumed the head from the avail ring. The head was never written to the used ring, so the descriptor slot leaked and the queue could be stalled by a guest that keeps submitting malformed chains. Handle the parse error in line. Log a warning, add the head to the used ring with len 0, reenable notifications, and continue draining the queue. A VIRTIO_BLK_S_IOERR status cannot be written because the status descriptor address is exactly what failed to parse. Signed-off-by: Anatol Belski --- virtio-devices/src/block.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index 726e2d6d5..1df299be9 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -282,8 +282,20 @@ impl BlockEpollHandler { return Err(Error::QueueDuplicatedHeadIndex); } - let mut request = Request::parse(&mut desc_chain, self.access_platform.as_deref()) - .map_err(Error::RequestParsing)?; + let mut request = match Request::parse(&mut desc_chain, self.access_platform.as_deref()) + { + Ok(r) => r, + Err(e) => { + warn!("Failed to parse virtio-blk request at head {head}: {e}"); + queue + .add_used(desc_chain.memory(), head, 0) + .map_err(Error::QueueAddUsed)?; + queue + .enable_notification(desc_chain.memory()) + .map_err(Error::QueueEnableNotification)?; + continue; + } + }; // For virtio spec compliance // "A device MUST set the status byte to VIRTIO_BLK_S_IOERR for a write request