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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let queue = &mut self.queue;
|
let queue = &mut self.queue;
|
||||||
|
let queue_size = queue.size();
|
||||||
let mut batch_requests = Vec::new();
|
let mut batch_requests = Vec::new();
|
||||||
let mut batch_inflight_requests = Vec::new();
|
let mut batch_inflight_requests = Vec::new();
|
||||||
|
let mut processed = 0;
|
||||||
|
|
||||||
loop {
|
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()) {
|
let mut desc_chain = match queue.iter(self.mem.memory()) {
|
||||||
Ok(mut iter) => match iter.next() {
|
Ok(mut iter) => match iter.next() {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
|
|||||||
Reference in New Issue
Block a user