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 <rbradford@meta.com>
Assisted-by: Claude:claude-opus-4-7
This commit is contained in:
Rob Bradford
2026-04-26 22:12:12 +01:00
parent 8fb4aa61c7
commit 024188cb7f

View File

@@ -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;