virtio-devices: iommu: checked arithmetic for MAP

Catch u64 overflows on map so that later translation requests from the
guest don't have a vector for causing a host panic.

Signed-off-by: Dylan Reid <dgreid@fb.com>
This commit is contained in:
Dylan Reid
2026-04-24 16:56:59 -07:00
committed by Rob Bradford
parent 22eeb3f808
commit 5b199498ff

View File

@@ -494,12 +494,25 @@ impl Request {
.map(|(&e, _)| e)
.collect();
let Some(size) = req
.virt_end
.checked_sub(req.virt_start)
.and_then(|delta| delta.checked_add(1))
else {
status = VIRTIO_IOMMU_S_RANGE;
return Err(Error::InvalidMapRequest);
};
if req.phys_start > u64::MAX - size || req.virt_start > u64::MAX - size {
status = VIRTIO_IOMMU_S_RANGE;
return Err(Error::InvalidMapRequest);
}
// For viommu all endpoints receive their own VFIO container, as a result
// Each endpoint within the domain needs to be separately mapped, as the
// mapping is done on a per-container level, not a per-domain level
for endpoint in endpoints {
if let Some(ext_map) = ext_mapping.get(&endpoint) {
let size = req.virt_end - req.virt_start + 1;
ext_map
.map(req.virt_start, req.phys_start, size)
.map_err(Error::ExternalMapping)?;
@@ -518,7 +531,7 @@ impl Request {
req.virt_start,
Mapping {
gpa: req.phys_start,
size: req.virt_end - req.virt_start + 1,
size,
},
);
}
@@ -558,10 +571,18 @@ impl Request {
.map(|(&e, _)| e)
.collect();
let Some(size) = req
.virt_end
.checked_sub(virt_start)
.and_then(|d| d.checked_add(1))
else {
status = VIRTIO_IOMMU_S_RANGE;
return Err(Error::InvalidUnmapRequest);
};
// Trigger external unmapping if necessary.
for endpoint in endpoints {
if let Some(ext_map) = ext_mapping.get(&endpoint) {
let size = req.virt_end - virt_start + 1;
ext_map
.unmap(virt_start, size)
.map_err(Error::ExternalUnmapping)?;