mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
@@ -150,7 +150,7 @@ struct VirtioIommuReqAttach {
|
|||||||
domain: u32,
|
domain: u32,
|
||||||
endpoint: u32,
|
endpoint: u32,
|
||||||
flags: u32,
|
flags: u32,
|
||||||
_reserved: [u8; 4],
|
reserved: [u8; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
const VIRTIO_IOMMU_ATTACH_F_BYPASS: u32 = 1;
|
const VIRTIO_IOMMU_ATTACH_F_BYPASS: u32 = 1;
|
||||||
@@ -404,12 +404,26 @@ impl Request {
|
|||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
debug!("Attach request 0x{req:x?}");
|
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.
|
// Copy the value to use it as a proper reference.
|
||||||
let domain_id = req.domain;
|
let domain_id = req.domain;
|
||||||
let endpoint = req.endpoint;
|
let endpoint = req.endpoint;
|
||||||
let bypass =
|
let bypass =
|
||||||
(req.flags & VIRTIO_IOMMU_ATTACH_F_BYPASS) == VIRTIO_IOMMU_ATTACH_F_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;
|
let mut old_domain_id = domain_id;
|
||||||
if let Some(&id) = mapping.endpoints.read().unwrap().get(&endpoint) {
|
if let Some(&id) = mapping.endpoints.read().unwrap().get(&endpoint) {
|
||||||
old_domain_id = id;
|
old_domain_id = id;
|
||||||
|
|||||||
Reference in New Issue
Block a user