misc: return errors from IOMMU address translation instead of panicking

The address that is passed from the guest should be treated as
untrusted. Currently an invalid address will panic the VMM. This only
allows the guest to hurt itself, but we shouldn't have the VMM crashing.
Instead let's return an error if possible or invalidate the queue if it
happen during setup.

The data flow from guest to translate_gva/translate_gpa is:

  1. Guest writes a raw u64 address into a virtio descriptor in the
     shared descriptor table (guest memory).
  2. The virtio-queue crate reads this descriptor via read_obj() and
     returns the addr field as-is in a GuestAddress — no validation.
  3. Device code calls .translate_gva(access_platform, len) on the
     GuestAddress.
  4. With IOMMU (access_platform is Some): the address is an IOVA that
     must be translated to a GPA via the IOMMU mapping table. If the
     guest provides an unmapped IOVA, translation returns Err.
     Previously, .unwrap() here panicked the VMM.
  5. Without IOMMU (access_platform is None): translate_gva is a no-op
     (returns self). The raw address flows to GuestMemory::read_obj()
     which validates it — out-of-range addresses return
     Err(InvalidGuestAddress), so no host memory corruption is possible.

Signed-off-by: Dylan Reid <dgreid@fb.com>
This commit is contained in:
Dylan Reid
2026-04-07 10:43:57 -07:00
committed by Rob Bradford
parent d4fc1d38c8
commit a6d3901f3e
10 changed files with 153 additions and 56 deletions

View File

@@ -312,7 +312,8 @@ impl Request {
let hdr_desc_addr = hdr_desc
.addr()
.translate_gva(access_platform, hdr_desc.len() as usize);
.translate_gva(access_platform, hdr_desc.len() as usize)
.map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?;
let mut req = Request {
request_type: request_type(desc_chain.memory(), hdr_desc_addr)?,
@@ -353,7 +354,8 @@ impl Request {
req.data_descriptors.push((
desc.addr()
.translate_gva(access_platform, desc.len() as usize),
.translate_gva(access_platform, desc.len() as usize)
.map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?,
desc.len(),
));
desc = desc_chain
@@ -384,7 +386,8 @@ impl Request {
req.status_addr = status_desc
.addr()
.translate_gva(access_platform, status_desc.len() as usize);
.translate_gva(access_platform, status_desc.len() as usize)
.map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?;
Ok(req)
}