From 6e101f479c04d17d4ca34cb428e8bcfaa8af8df5 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 29 Apr 2022 10:23:07 +0200 Subject: [PATCH] vmm: Ensure hotplugged device identifier is unique Whenever a device (virtio, vfio, vfio-user or vdpa) is hotplugged, we must verify the provided identifier is unique, otherwise we must return an error. Particularly, this will prevent issues with identifiers for serial, console, IOAPIC, balloon, rng, watchdog, iommu and gpio since all of these are hardcoded by the VMM. Signed-off-by: Sebastien Boeuf --- vmm/src/device_manager.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 37a92e864..3c0292715 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -477,6 +477,9 @@ pub enum DeviceManagerError { /// Failed to create UEFI flash CreateUefiFlash(hypervisor::vm::HypervisorVmError), + + /// Invalid identifier as it is not unique. + IdentifierNotUnique(String), } pub type DeviceManagerResult = result::Result; @@ -3707,6 +3710,8 @@ impl DeviceManager { &mut self, device_cfg: &mut DeviceConfig, ) -> DeviceManagerResult { + self.validate_identifier(&device_cfg.id)?; + if device_cfg.iommu && !self.is_iommu_segment(device_cfg.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } @@ -3726,6 +3731,8 @@ impl DeviceManager { &mut self, device_cfg: &mut UserDeviceConfig, ) -> DeviceManagerResult { + self.validate_identifier(&device_cfg.id)?; + let (bdf, device_name) = self.add_vfio_user_device(device_cfg)?; // Update the PCIU bitmap @@ -4035,6 +4042,8 @@ impl DeviceManager { } pub fn add_disk(&mut self, disk_cfg: &mut DiskConfig) -> DeviceManagerResult { + self.validate_identifier(&disk_cfg.id)?; + if disk_cfg.iommu && !self.is_iommu_segment(disk_cfg.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } @@ -4044,11 +4053,15 @@ impl DeviceManager { } pub fn add_fs(&mut self, fs_cfg: &mut FsConfig) -> DeviceManagerResult { + self.validate_identifier(&fs_cfg.id)?; + let device = self.make_virtio_fs_device(fs_cfg)?; self.hotplug_virtio_pci_device(device) } pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult { + self.validate_identifier(&pmem_cfg.id)?; + if pmem_cfg.iommu && !self.is_iommu_segment(pmem_cfg.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } @@ -4058,6 +4071,8 @@ impl DeviceManager { } pub fn add_net(&mut self, net_cfg: &mut NetConfig) -> DeviceManagerResult { + self.validate_identifier(&net_cfg.id)?; + if net_cfg.iommu && !self.is_iommu_segment(net_cfg.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } @@ -4067,6 +4082,8 @@ impl DeviceManager { } pub fn add_vdpa(&mut self, vdpa_cfg: &mut VdpaConfig) -> DeviceManagerResult { + self.validate_identifier(&vdpa_cfg.id)?; + if vdpa_cfg.iommu && !self.is_iommu_segment(vdpa_cfg.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } @@ -4076,6 +4093,8 @@ impl DeviceManager { } pub fn add_vsock(&mut self, vsock_cfg: &mut VsockConfig) -> DeviceManagerResult { + self.validate_identifier(&vsock_cfg.id)?; + if vsock_cfg.iommu && !self.is_iommu_segment(vsock_cfg.pci_segment) { return Err(DeviceManagerError::InvalidIommuHotplug); } @@ -4203,6 +4222,16 @@ impl DeviceManager { pub fn uefi_flash(&self) -> GuestMemoryAtomic { self.uefi_flash.as_ref().unwrap().clone() } + + fn validate_identifier(&self, id: &Option) -> DeviceManagerResult<()> { + if let Some(id) = id { + if self.device_tree.lock().unwrap().contains_key(id) { + return Err(DeviceManagerError::IdentifierNotUnique(id.clone())); + } + } + + Ok(()) + } } fn numa_node_id_from_memory_zone_id(numa_nodes: &NumaNodes, memory_zone_id: &str) -> Option {