pvmfw: Also check alignments against hyp page size

Validate that the virtual platform isn't configured in such a way that
would present the risk to a guest kernel with a (stage-1) page size
smaller than the stage-2 page size used by the hypervisor of
inadvertently sharing more than it expects by (wrongly) aligning against
its own page size.

This works by checking the alignment of

- main memory: ensures that MMIO_GUARD_MAP will never map normal memory
- swiotlb: ensures that MEM_SHARE will never share private memory

Bug: 393095315
Test: m pvmfw
Change-Id: I8c46ad0ce6a10baf556ab6eac64e6c9708938a08
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 4867225..7c888d5 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -29,7 +29,6 @@
 use core::mem::size_of;
 use core::ops::Range;
 use hypervisor_backends::get_device_assigner;
-use hypervisor_backends::get_mem_sharer;
 use libfdt::AddressRange;
 use libfdt::CellIterator;
 use libfdt::Fdt;
@@ -1043,6 +1042,7 @@
     vm_dtbo: Option<&mut [u8]>,
     vm_ref_dt: Option<&[u8]>,
     guest_page_size: usize,
+    hyp_page_size: Option<usize>,
 ) -> Result<DeviceTreeInfo, RebootReason> {
     let vm_dtbo = match vm_dtbo {
         Some(vm_dtbo) => Some(VmDtbo::from_mut_slice(vm_dtbo).map_err(|e| {
@@ -1052,7 +1052,7 @@
         None => None,
     };
 
-    let info = parse_device_tree(fdt, vm_dtbo.as_deref(), guest_page_size)?;
+    let info = parse_device_tree(fdt, vm_dtbo.as_deref(), guest_page_size, hyp_page_size)?;
 
     fdt.clone_from(FDT_TEMPLATE).map_err(|e| {
         error!("Failed to instantiate FDT from the template DT: {e}");
@@ -1109,13 +1109,15 @@
     fdt: &Fdt,
     vm_dtbo: Option<&VmDtbo>,
     guest_page_size: usize,
+    hyp_page_size: Option<usize>,
 ) -> Result<DeviceTreeInfo, RebootReason> {
     let initrd_range = read_initrd_range_from(fdt).map_err(|e| {
         error!("Failed to read initrd range from DT: {e}");
         RebootReason::InvalidFdt
     })?;
 
-    let memory_alignment = guest_page_size;
+    // Ensure that MMIO_GUARD can't be used to inadvertently map some memory as MMIO.
+    let memory_alignment = max(hyp_page_size, Some(guest_page_size)).unwrap();
     let memory_range = read_and_validate_memory_range(fdt, memory_alignment)?;
 
     let bootargs = read_bootargs_from(fdt).map_err(|e| {
@@ -1169,22 +1171,17 @@
             error!("Swiotlb info missing from DT");
             RebootReason::InvalidFdt
         })?;
-    let swiotlb_alignment = guest_page_size;
+    // Ensure that MEM_SHARE won't inadvertently map beyond the shared region.
+    let swiotlb_alignment = max(hyp_page_size, Some(guest_page_size)).unwrap();
     validate_swiotlb_info(&swiotlb_info, &memory_range, swiotlb_alignment)?;
 
     let device_assignment = if let Some(vm_dtbo) = vm_dtbo {
         if let Some(hypervisor) = get_device_assigner() {
-            // TODO(ptosi): Cache the (single?) granule once, in vmbase.
-            let granule = get_mem_sharer()
-                .ok_or_else(|| {
-                    error!("No MEM_SHARE found during device assignment validation");
-                    RebootReason::InternalError
-                })?
-                .granule()
-                .map_err(|e| {
-                    error!("Failed to get granule for device assignment validation: {e}");
-                    RebootReason::InternalError
-                })?;
+            let granule = hyp_page_size.ok_or_else(|| {
+                error!("No granule found during device assignment validation");
+                RebootReason::InternalError
+            })?;
+
             DeviceAssignmentInfo::parse(fdt, vm_dtbo, hypervisor, granule).map_err(|e| {
                 error!("Failed to parse device assignment from DT and VM DTBO: {e}");
                 RebootReason::InvalidFdt
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index afa64e0..68f1d29 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -41,6 +41,7 @@
 use alloc::boxed::Box;
 use bssl_avf::Digester;
 use diced_open_dice::{bcc_handover_parse, DiceArtifacts, DiceContext, Hidden, VM_KEY_ALGORITHM};
+use hypervisor_backends::get_mem_sharer;
 use libfdt::Fdt;
 use log::{debug, error, info, trace, warn};
 use pvmfw_avb::verify_payload;
@@ -98,7 +99,17 @@
     }
 
     let guest_page_size = verified_boot_data.page_size.unwrap_or(SIZE_4KB);
-    let _ = sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt, guest_page_size)?;
+    // TODO(ptosi): Cache the (single?) granule once, in vmbase.
+    let hyp_page_size = if let Some(mem_sharer) = get_mem_sharer() {
+        Some(mem_sharer.granule().map_err(|e| {
+            error!("Failed to get granule size: {e}");
+            RebootReason::InternalError
+        })?)
+    } else {
+        None
+    };
+    let _ =
+        sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt, guest_page_size, hyp_page_size)?;
     let fdt = untrusted_fdt; // DT has now been sanitized.
 
     let next_bcc_size = guest_page_size;