mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Validate PCI device ID
Validate the PCI device ID are within range and not using the reserved value. We need this option to ensure that invalid device IDs received via an API call result in an error as soon as possible. In this case, this would be after deserialization. On this code path, validation via `parse` is skipped and must be invoked by calling `validate`. Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de> On-behalf-of: SAP pascal.scholz@sap.com Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
committed by
Rob Bradford
parent
4e247cf91d
commit
7315a38a02
@@ -17,6 +17,7 @@ use log::{debug, warn};
|
||||
use option_parser::{
|
||||
ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, Tuple,
|
||||
};
|
||||
use pci::NUM_DEVICE_IDS;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use virtio_bindings::virtio_blk::VIRTIO_BLK_ID_BYTES;
|
||||
@@ -402,6 +403,13 @@ pub enum ValidationError {
|
||||
/// Invalid NUMA Configuration
|
||||
#[error("NUMA Configuration is invalid")]
|
||||
InvalidNumaConfig(String),
|
||||
/// The supplied PCI ID was greater then the max. supported number
|
||||
/// of devices per Bus
|
||||
#[error("Given PCI device ID ({0}) is out of the supported range of 0..{NUM_DEVICE_IDS}")]
|
||||
InvalidPciDeviceId(u8),
|
||||
/// The supplied PCI ID is reserved
|
||||
#[error("Given PCI device ID ({0}) is reserved")]
|
||||
ReservedPciDeviceId(u8),
|
||||
}
|
||||
|
||||
type ValidationResult<T> = std::result::Result<T, ValidationError>;
|
||||
@@ -414,6 +422,21 @@ pub fn add_to_config<T>(items: &mut Option<Vec<T>>, item: T) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the PCI device supplied is neither out of range nor does
|
||||
/// it use any reserved device ID.
|
||||
fn validate_pci_device_id(device_id: u8) -> ValidationResult<()> {
|
||||
if device_id >= pci::NUM_DEVICE_IDS {
|
||||
// Check the given ID is not out of range
|
||||
return Err(ValidationError::InvalidPciDeviceId(device_id));
|
||||
} else if device_id == pci::PCI_ROOT_DEVICE_ID {
|
||||
// Check the ID isn't any reserved one. Currently, only the device ID
|
||||
// for the root device is reserved.
|
||||
return Err(ValidationError::ReservedPciDeviceId(device_id));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
pub struct VmParams<'a> {
|
||||
@@ -1243,6 +1266,10 @@ impl PciDeviceCommonConfig {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(device_id) = self.pci_device_id {
|
||||
validate_pci_device_id(device_id)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -5643,7 +5670,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
|
||||
}]);
|
||||
still_valid_config.validate().unwrap();
|
||||
|
||||
let mut still_valid_config = valid_config;
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
// SAFETY: Safe as the file was just opened
|
||||
let fd1 = unsafe { libc::dup(File::open("/dev/null").unwrap().as_raw_fd()) };
|
||||
// SAFETY: Safe as the file was just opened
|
||||
@@ -5653,6 +5680,45 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
|
||||
still_valid_config.add_preserved_fds(vec![fd1, fd2]);
|
||||
}
|
||||
let _still_valid_config = still_valid_config.clone();
|
||||
|
||||
// Valid BDF test
|
||||
let mut still_valid_config = valid_config.clone();
|
||||
still_valid_config.disks = Some(vec![DiskConfig {
|
||||
pci_common: PciDeviceCommonConfig {
|
||||
pci_device_id: Some(8),
|
||||
..Default::default()
|
||||
},
|
||||
..disk_fixture()
|
||||
}]);
|
||||
still_valid_config.validate().unwrap();
|
||||
// Invalid BDF - Same ID as Root device
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.disks = Some(vec![DiskConfig {
|
||||
pci_common: PciDeviceCommonConfig {
|
||||
pci_device_id: Some(pci::PCI_ROOT_DEVICE_ID),
|
||||
..Default::default()
|
||||
},
|
||||
..disk_fixture()
|
||||
}]);
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::ReservedPciDeviceId(
|
||||
pci::PCI_ROOT_DEVICE_ID
|
||||
))
|
||||
);
|
||||
// Invalid BDF - Out of range
|
||||
let mut invalid_config = valid_config.clone();
|
||||
invalid_config.disks = Some(vec![DiskConfig {
|
||||
pci_common: PciDeviceCommonConfig {
|
||||
pci_device_id: Some(pci::NUM_DEVICE_IDS + 1),
|
||||
..Default::default()
|
||||
},
|
||||
..disk_fixture()
|
||||
}]);
|
||||
assert_eq!(
|
||||
invalid_config.validate(),
|
||||
Err(ValidationError::InvalidPciDeviceId(pci::NUM_DEVICE_IDS + 1))
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_landlock_parsing() -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user