vmm: config: Validate provided identifiers are unique

A valid configuration means we can only accept unique identifiers from
the user.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2022-04-28 18:20:39 +02:00
parent 657660e5c2
commit 634c53ea50

View File

@ -8,7 +8,7 @@ use net_util::MacAddr;
use option_parser::{ use option_parser::{
ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, Tuple, ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, Tuple,
}; };
use std::collections::HashMap; use std::collections::{BTreeSet, HashMap};
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
@ -170,6 +170,8 @@ pub enum ValidationError {
OnIommuSegment(u16), OnIommuSegment(u16),
// On a IOMMU segment but IOMMU not suported // On a IOMMU segment but IOMMU not suported
IommuNotSupported(u16), IommuNotSupported(u16),
// Identifier is not unique
IdentifierNotUnique(String),
} }
type ValidationResult<T> = std::result::Result<T, ValidationError>; type ValidationResult<T> = std::result::Result<T, ValidationError>;
@ -256,6 +258,9 @@ impl fmt::Display for ValidationError {
pci_segment pci_segment
) )
} }
IdentifierNotUnique(s) => {
write!(f, "Identifier {} is not unique", s)
}
} }
} }
} }
@ -2325,6 +2330,8 @@ pub struct VmConfig {
impl VmConfig { impl VmConfig {
// Also enables virtio-iommu if the config needs it // Also enables virtio-iommu if the config needs it
pub fn validate(&mut self) -> ValidationResult<()> { pub fn validate(&mut self) -> ValidationResult<()> {
let mut id_list = BTreeSet::new();
#[cfg(not(feature = "tdx"))] #[cfg(not(feature = "tdx"))]
self.kernel.as_ref().ok_or(ValidationError::KernelMissing)?; self.kernel.as_ref().ok_or(ValidationError::KernelMissing)?;
@ -2369,6 +2376,12 @@ impl VmConfig {
} }
disk.validate(self)?; disk.validate(self)?;
self.iommu |= disk.iommu; self.iommu |= disk.iommu;
if let Some(id) = disk.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
@ -2379,6 +2392,12 @@ impl VmConfig {
} }
net.validate(self)?; net.validate(self)?;
self.iommu |= net.iommu; self.iommu |= net.iommu;
if let Some(id) = net.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
@ -2388,6 +2407,12 @@ impl VmConfig {
} }
for fs in fses { for fs in fses {
fs.validate(self)?; fs.validate(self)?;
if let Some(id) = fs.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
@ -2395,6 +2420,12 @@ impl VmConfig {
for pmem in pmems { for pmem in pmems {
pmem.validate(self)?; pmem.validate(self)?;
self.iommu |= pmem.iommu; self.iommu |= pmem.iommu;
if let Some(id) = pmem.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
@ -2440,6 +2471,12 @@ impl VmConfig {
for user_device in user_devices { for user_device in user_devices {
user_device.validate(self)?; user_device.validate(self)?;
if let Some(id) = user_device.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
@ -2447,6 +2484,12 @@ impl VmConfig {
for vdpa_device in vdpa_devices { for vdpa_device in vdpa_devices {
vdpa_device.validate(self)?; vdpa_device.validate(self)?;
self.iommu |= vdpa_device.iommu; self.iommu |= vdpa_device.iommu;
if let Some(id) = vdpa_device.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
@ -2471,12 +2514,24 @@ impl VmConfig {
for device in devices { for device in devices {
device.validate(self)?; device.validate(self)?;
self.iommu |= device.iommu; self.iommu |= device.iommu;
if let Some(id) = device.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
} }
if let Some(vsock) = &self.vsock { if let Some(vsock) = &self.vsock {
vsock.validate(self)?; vsock.validate(self)?;
self.iommu |= vsock.iommu; self.iommu |= vsock.iommu;
if let Some(id) = vsock.id.clone() {
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
} }
if let Some(numa) = &self.numa { if let Some(numa) = &self.numa {
@ -2497,6 +2552,25 @@ impl VmConfig {
} }
} }
if let Some(zones) = &self.memory.zones {
for zone in zones.iter() {
let id = zone.id.clone();
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
}
#[cfg(target_arch = "x86_64")]
if let Some(sgx_epcs) = &self.sgx_epc {
for sgx_epc in sgx_epcs.iter() {
let id = sgx_epc.id.clone();
if !id_list.insert(id.clone()) {
return Err(ValidationError::IdentifierNotUnique(id));
}
}
}
self.platform.as_ref().map(|p| p.validate()).transpose()?; self.platform.as_ref().map(|p| p.validate()).transpose()?;
self.iommu |= self self.iommu |= self
.platform .platform