Validate that PCI MMIO regions are within the expected range.

Bug: 237249346
Test: Built and ran pVM firmware manually
Change-Id: Ic506486c8961f40fa6f08c602813bf17796be8e7
diff --git a/pvmfw/src/virtio/hal.rs b/pvmfw/src/virtio/hal.rs
index c6c7a99..5f70b33 100644
--- a/pvmfw/src/virtio/hal.rs
+++ b/pvmfw/src/virtio/hal.rs
@@ -1,5 +1,9 @@
+use super::pci::PCI_INFO;
 use crate::memory::{alloc_shared, dealloc_shared, phys_to_virt, virt_to_phys};
-use core::ptr::{copy_nonoverlapping, NonNull};
+use core::{
+    ops::Range,
+    ptr::{copy_nonoverlapping, NonNull},
+};
 use log::debug;
 use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE};
 
@@ -26,7 +30,21 @@
         0
     }
 
-    fn mmio_phys_to_virt(paddr: PhysAddr, _size: usize) -> NonNull<u8> {
+    fn mmio_phys_to_virt(paddr: PhysAddr, size: usize) -> NonNull<u8> {
+        let pci_info = PCI_INFO.get().expect("VirtIO HAL used before PCI_INFO was initialised");
+        // Check that the region is within the PCI MMIO range that we read from the device tree. If
+        // not, the host is probably trying to do something malicious.
+        if !contains_range(
+            &pci_info.bar_range,
+            &(paddr.try_into().expect("PCI MMIO region start was outside of 32-bit address space")
+                ..paddr
+                    .checked_add(size)
+                    .expect("PCI MMIO region end overflowed")
+                    .try_into()
+                    .expect("PCI MMIO region end was outside of 32-bit address space")),
+        ) {
+            panic!("PCI MMIO region was outside of expected BAR range.");
+        }
         phys_to_virt(paddr)
     }
 
@@ -68,3 +86,8 @@
         }
     }
 }
+
+/// Returns true if `inner` is entirely contained within `outer`.
+fn contains_range(outer: &Range<u32>, inner: &Range<u32>) -> bool {
+    inner.start >= outer.start && inner.end <= outer.end
+}