Skip to content

Commit 14e8b37

Browse files
committed
fix: return NO_VECTOR when reading MSI vector for invalid queue
Fix a bug in the common VirtIO configuration for PCI transport where we would use `queue_select` to read the queue's MSI vector without validating it matches a valid queue. This could lead in panics when accessing the `msix_queue` array. The spec states that in such cases we should return `NO_VECTOR` (0xffff), so do that. Signed-off-by: Babis Chalios <[email protected]>
1 parent dfa28a6 commit 14e8b37

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

src/vmm/src/devices/virtio/transport/pci/common_config.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,19 @@ impl VirtioPciCommonConfig {
230230
0x12 => queues.len().try_into().unwrap(), // num_queues
231231
0x16 => self.queue_select,
232232
0x18 => self.with_queue(queues, |q| q.size).unwrap_or(0),
233-
0x1a => self.msix_queues.lock().unwrap()[self.queue_select as usize],
233+
// If `queue_select` points to an invalid queue we should return NO_VECTOR.
234+
// Reading from here
235+
// https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-1280005:
236+
//
237+
// > The device MUST return vector mapped to a given event, (NO_VECTOR if unmapped) on
238+
// > read of config_msix_vector/queue_msix_vector.
239+
0x1a => self
240+
.msix_queues
241+
.lock()
242+
.unwrap()
243+
.get(self.queue_select as usize)
244+
.copied()
245+
.unwrap_or(0xffff),
234246
0x1c => u16::from(self.with_queue(queues, |q| q.ready).unwrap_or(false)),
235247
0x1e => self.queue_select, // notify_off
236248
_ => {
@@ -408,8 +420,13 @@ mod tests {
408420
// 'queue_select' can be read and written.
409421
regs.write(0x16, &[0xaa, 0x55], dev.clone());
410422
let mut read_back = vec![0x00, 0x00];
411-
regs.read(0x16, &mut read_back, dev);
423+
regs.read(0x16, &mut read_back, dev.clone());
412424
assert_eq!(read_back[0], 0xaa);
413425
assert_eq!(read_back[1], 0x55);
426+
427+
// Getting the MSI vector when `queue_select` points to an invalid queue should return
428+
// NO_VECTOR (0xffff)
429+
regs.read(0x1a, &mut read_back, dev);
430+
assert_eq!(read_back, [0xff, 0xff]);
414431
}
415432
}

0 commit comments

Comments
 (0)