From 8268a4fd5b25b310029381f0c2310b8e87d15bbb Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Wed, 29 Jul 2026 10:09:46 +0100 Subject: [PATCH] devices: ivshmem: Don't remap file on BAR reprogramming The ivshmem device was remapping the host file every time the BAR was reprogrammed. This occurs on the vCPU thread and so was falling foul of our improved seccomp filters. Avoid this by maintaining the existing region when the device BARs are changed and just adjust the guest GPA. Assisted-by: Codex:GPT-5.6 Signed-off-by: Rob Bradford --- devices/src/ivshmem.rs | 26 +++++++++++++++----------- vmm/src/device_manager.rs | 19 +++++++++++++------ 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/devices/src/ivshmem.rs b/devices/src/ivshmem.rs index dc85039c7..f1d4c2cc0 100644 --- a/devices/src/ivshmem.rs +++ b/devices/src/ivshmem.rs @@ -49,6 +49,8 @@ pub enum IvshmemError { CreateUserspaceMapping(#[source] anyhow::Error), #[error("Failed to remove old userspace mapping.")] RemoveUserspaceMapping(#[source] anyhow::Error), + #[error("Missing memory region")] + MissingMemoryRegion, } #[derive(Copy, Clone)] @@ -70,6 +72,12 @@ pub trait IvshmemOps: Send + Sync { backing_file: Option, ) -> Result<(Arc, UserspaceMapping), IvshmemError>; + fn create_userspace_mapping( + &mut self, + start_addr: u64, + region: Arc, + ) -> Result; + fn unmap_ram_region(&mut self, mapping: UserspaceMapping) -> Result<(), IvshmemError>; } @@ -94,7 +102,6 @@ pub struct IvshmemDevice { region_size: u64, ivshmem_ops: Arc>, - backend_file: Option, region: Option>, userspace_mapping: Option, } @@ -111,7 +118,6 @@ impl IvshmemDevice { pub fn new( id: String, region_size: u64, - backend_file: Option, ivshmem_ops: Arc>, snapshot: Option<&Snapshot>, ) -> Result { @@ -159,7 +165,6 @@ impl IvshmemDevice { ivshmem_ops, region: None, userspace_mapping: None, - backend_file, } } else { IvshmemDevice { @@ -174,7 +179,6 @@ impl IvshmemDevice { ivshmem_ops, region: None, userspace_mapping: None, - backend_file, } }; Ok(device) @@ -353,6 +357,10 @@ impl PciDevice for IvshmemDevice { fn move_bar(&mut self, old_base: u64, new_base: u64) -> io::Result<()> { if new_base == self.data_bar_addr() { + let region = self + .region + .clone() + .ok_or_else(|| io::Error::other(IvshmemError::MissingMemoryRegion))?; if let Some(old_mapping) = self.userspace_mapping.take() { self.ivshmem_ops .lock() @@ -360,17 +368,13 @@ impl PciDevice for IvshmemDevice { .unmap_ram_region(old_mapping) .map_err(io::Error::other)?; } - let (region, new_mapping) = self + let new_mapping = self .ivshmem_ops .lock() .unwrap() - .map_ram_region( - new_base, - self.region_size as usize, - self.backend_file.clone(), - ) + .create_userspace_mapping(new_base, region) .map_err(io::Error::other)?; - self.set_region(region, new_mapping); + self.userspace_mapping = Some(new_mapping); } for bar in self.bar_regions.iter_mut() { if bar.addr() == old_base { diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 1eda66472..8c0b75244 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -4676,7 +4676,6 @@ impl DeviceManager { devices::IvshmemDevice::new( id.clone(), ivshmem_cfg.size as u64, - Some(ivshmem_cfg.path.clone()), ivshmem_ops.clone(), snapshot, ) @@ -5601,6 +5600,16 @@ impl IvshmemOps for IvshmemHandler { false, ) .map_err(|e| IvshmemError::CreateUserMemoryRegion(e.into()))?; + let region = Arc::new(region); + let mapping = self.create_userspace_mapping(start_addr, region.clone())?; + Ok((region, mapping)) + } + + fn create_userspace_mapping( + &mut self, + start_addr: u64, + region: Arc>, + ) -> Result { let mem_slot = { let mut manager = self.memory_manager.lock().unwrap(); // SAFETY: guaranteed by MmapRegion invariants @@ -5616,14 +5625,12 @@ impl IvshmemOps for IvshmemHandler { } } .map_err(|e| IvshmemError::CreateUserspaceMapping(e.into()))?; - let region = Arc::new(region); - let mapping = UserspaceMapping { - mapping: region.clone(), + Ok(UserspaceMapping { + mapping: region, mem_slot, addr: GuestAddress(start_addr), mergeable: false, - }; - Ok((region, mapping)) + }) } fn unmap_ram_region(&mut self, mapping: UserspaceMapping) -> Result<(), IvshmemError> {