mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
@@ -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)?;
|
||||
|
||||
Reference in New Issue
Block a user