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)
|
.map(|(&e, _)| e)
|
||||||
.collect();
|
.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
|
// For viommu all endpoints receive their own VFIO container, as a result
|
||||||
// Each endpoint within the domain needs to be separately mapped, as the
|
// 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
|
// mapping is done on a per-container level, not a per-domain level
|
||||||
for endpoint in endpoints {
|
for endpoint in endpoints {
|
||||||
if let Some(ext_map) = ext_mapping.get(&endpoint) {
|
if let Some(ext_map) = ext_mapping.get(&endpoint) {
|
||||||
let size = req.virt_end - req.virt_start + 1;
|
|
||||||
ext_map
|
ext_map
|
||||||
.map(req.virt_start, req.phys_start, size)
|
.map(req.virt_start, req.phys_start, size)
|
||||||
.map_err(Error::ExternalMapping)?;
|
.map_err(Error::ExternalMapping)?;
|
||||||
@@ -518,7 +531,7 @@ impl Request {
|
|||||||
req.virt_start,
|
req.virt_start,
|
||||||
Mapping {
|
Mapping {
|
||||||
gpa: req.phys_start,
|
gpa: req.phys_start,
|
||||||
size: req.virt_end - req.virt_start + 1,
|
size,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -558,10 +571,18 @@ impl Request {
|
|||||||
.map(|(&e, _)| e)
|
.map(|(&e, _)| e)
|
||||||
.collect();
|
.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.
|
// Trigger external unmapping if necessary.
|
||||||
for endpoint in endpoints {
|
for endpoint in endpoints {
|
||||||
if let Some(ext_map) = ext_mapping.get(&endpoint) {
|
if let Some(ext_map) = ext_mapping.get(&endpoint) {
|
||||||
let size = req.virt_end - virt_start + 1;
|
|
||||||
ext_map
|
ext_map
|
||||||
.unmap(virt_start, size)
|
.unmap(virt_start, size)
|
||||||
.map_err(Error::ExternalUnmapping)?;
|
.map_err(Error::ExternalUnmapping)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user