mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: block: cap submit-loop iterations to virtqueue size
process_queue_submit's drain loop builds a fresh queue.iter() per iteration, which re-reads the guest avail index on every call and has no per-call cap (the per-iter gap check in virtio-queue only protects against avail_idx jumping more than queue_size between two reads). In theory, a malicous or buggy guest could keep adding descriptors and cause this loop to overflow the iouring submit queue. Cap a single drain at queue_size. A spec-compliant driver never produces more than queue_size outstanding entries simultaneously, so the cap is invisible to well-behaved guests. Signed-off-by: Dylan Reid <dgreid@fb.com>
This commit is contained in:
@@ -235,10 +235,18 @@ Setting device status to 'NEEDS_RESET' and stopping processing queues until rese
|
||||
return Ok(());
|
||||
}
|
||||
let queue = &mut self.queue;
|
||||
let queue_size = queue.size();
|
||||
let mut batch_requests = Vec::new();
|
||||
let mut batch_inflight_requests = Vec::new();
|
||||
let mut processed = 0;
|
||||
|
||||
loop {
|
||||
// Cap a single drain at the virtqueue size. A compliant driver won't submit more that
|
||||
// queue_size, but a buggy or malicious one can keep adding as the VMM is reading.
|
||||
if processed >= queue_size {
|
||||
break;
|
||||
}
|
||||
processed += 1;
|
||||
let mut desc_chain = match queue.iter(self.mem.memory()) {
|
||||
Ok(mut iter) => match iter.next() {
|
||||
Some(c) => c,
|
||||
|
||||
Reference in New Issue
Block a user