Merge changes I8c46ad0c,I2b98fdc1 into main
* changes:
pvmfw: Also check alignments against hyp page size
pvmfw: Check addr alignment of memory and swiotlb
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 2e34ee8..6716130 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;
@@ -193,6 +192,11 @@
);
}
let base = range.start;
+ if base % alignment != 0 {
+ error!("Memory base address {:#x} is not aligned to {:#x}", base, alignment);
+ return Err(RebootReason::InvalidFdt);
+ }
+ // For simplicity, force a hardcoded memory base, for now.
if base != MEM_START {
error!("Memory base address {:#x} is not {:#x}", base, MEM_START);
return Err(RebootReason::InvalidFdt);
@@ -902,6 +906,10 @@
error!("Invalid swiotlb range: addr:{addr:#x} size:{size:#x}");
return Err(RebootReason::InvalidFdt);
}
+ if (addr % alignment) != 0 {
+ error!("Swiotlb address {:#x} not aligned to {:#x}", addr, alignment);
+ return Err(RebootReason::InvalidFdt);
+ }
}
if let Some(range) = swiotlb_info.fixed_range() {
if !range.is_within(memory) {
@@ -1045,6 +1053,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| {
@@ -1054,7 +1063,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}");
@@ -1111,13 +1120,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| {
@@ -1171,22 +1182,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 9c67be8..9afbcc3 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;