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 <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-06-15 21:54:44 +02:00
committed by Rob Bradford
parent 4491a3e412
commit e1a63b41ff

View File

@@ -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