mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: Check MSI-X vector bounds before table access
A malicious or buggy guest can write an out-of-bounds value to queue_msix_vector or msix_config. When the device later triggers an interrupt, it indexes into table_entries with the unchecked vector, causing a panic. Validate the vector against the MSI-X table size in both trigger() and notifier() paths, logging a warning and returning early when the vector exceeds the table bounds. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
376434a695
commit
3b431afba4
@@ -15,7 +15,7 @@ use std::sync::{Arc, Barrier, Mutex};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use libc::EFD_NONBLOCK;
|
||||
use log::{error, info};
|
||||
use log::{error, info, warn};
|
||||
use pci::{
|
||||
BarReprogrammingParams, MaybeMutInterruptSourceGroup, MsixCap, MsixConfig, PciBarConfiguration,
|
||||
PciBarRegionType, PciCapability, PciCapabilityId, PciClassCode, PciConfiguration, PciDevice,
|
||||
@@ -860,6 +860,7 @@ pub struct VirtioInterruptMsix {
|
||||
config_vector: Arc<AtomicU16>,
|
||||
queues_vectors: Arc<Mutex<Vec<u16>>>,
|
||||
interrupt_source_group: MaybeMutInterruptSourceGroup,
|
||||
msix_table_size: usize,
|
||||
}
|
||||
|
||||
impl VirtioInterruptMsix {
|
||||
@@ -869,11 +870,13 @@ impl VirtioInterruptMsix {
|
||||
queues_vectors: Arc<Mutex<Vec<u16>>>,
|
||||
interrupt_source_group: MaybeMutInterruptSourceGroup,
|
||||
) -> Self {
|
||||
let msix_table_size = msix_config.lock().unwrap().table_entries.len();
|
||||
VirtioInterruptMsix {
|
||||
msix_config,
|
||||
config_vector,
|
||||
queues_vectors,
|
||||
interrupt_source_group,
|
||||
msix_table_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -891,6 +894,11 @@ impl VirtioInterrupt for VirtioInterruptMsix {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if vector as usize >= self.msix_table_size {
|
||||
warn!("MSI-X vector {vector} out of range, ignoring interrupt");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let config = &mut self.msix_config.lock().unwrap();
|
||||
let entry = &config.table_entries[vector as usize];
|
||||
// In case the vector control register associated with the entry
|
||||
@@ -915,6 +923,15 @@ impl VirtioInterrupt for VirtioInterruptMsix {
|
||||
}
|
||||
};
|
||||
|
||||
if vector == VIRTQ_MSI_NO_VECTOR {
|
||||
return None;
|
||||
}
|
||||
|
||||
if vector as usize >= self.msix_table_size {
|
||||
warn!("MSI-X vector {vector} out of range, notifier unavailable");
|
||||
return None;
|
||||
}
|
||||
|
||||
self.interrupt_source_group
|
||||
.notifier(vector as InterruptIndex)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user