From 024188cb7f6b1792487a32a10da90b6dc9913207 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Sun, 26 Apr 2026 22:12:12 +0100 Subject: [PATCH] virtio-devices: iommu: Validate ATTACH reserved field and flags The virtio spec requires the device to reject ATTACH with a non-zero reserved field, an unknown flag bit, or a bypass flag that conflicts with an existing domain. The current handler silently accepts all three. Signed-off-by: Rob Bradford Assisted-by: Claude:claude-opus-4-7 --- virtio-devices/src/iommu.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/virtio-devices/src/iommu.rs b/virtio-devices/src/iommu.rs index de03bbc46..efb071273 100644 --- a/virtio-devices/src/iommu.rs +++ b/virtio-devices/src/iommu.rs @@ -150,7 +150,7 @@ struct VirtioIommuReqAttach { domain: u32, endpoint: u32, flags: u32, - _reserved: [u8; 4], + reserved: [u8; 4], } const VIRTIO_IOMMU_ATTACH_F_BYPASS: u32 = 1; @@ -404,12 +404,26 @@ impl Request { .map_err(Error::GuestMemory)?; debug!("Attach request 0x{req:x?}"); + if req.reserved.iter().any(|&b| b != 0) + || (req.flags & !VIRTIO_IOMMU_ATTACH_F_BYPASS) != 0 + { + status = VIRTIO_IOMMU_S_INVAL; + return Err(Error::InvalidAttachRequest); + } + // Copy the value to use it as a proper reference. let domain_id = req.domain; let endpoint = req.endpoint; let bypass = (req.flags & VIRTIO_IOMMU_ATTACH_F_BYPASS) == VIRTIO_IOMMU_ATTACH_F_BYPASS; + if let Some(d) = mapping.domains.read().unwrap().get(&domain_id) + && d.bypass != bypass + { + status = VIRTIO_IOMMU_S_INVAL; + return Err(Error::InvalidAttachRequest); + } + let mut old_domain_id = domain_id; if let Some(&id) = mapping.endpoints.read().unwrap().get(&endpoint) { old_domain_id = id;