pvmfw: Read kernel/initrd ranges from untrusted DT
Stop relying on the output of the DT sanitization for configuring the
memory region and ranges for the kernel and ramdisk as those will be
validated by the MemoryTracker anyway. This will enable moving the
sanitization to main(), to perform it with more function-level inputs.
Bug: 377276983
Test: atest com.android.pvmfw.test.DebugPolicyHostTests
Change-Id: Id7f24fc6952dcc508aee04da04db9ed15b921036
diff --git a/guest/pvmfw/src/memory.rs b/guest/pvmfw/src/memory.rs
index 35bfd3a..e51a730 100644
--- a/guest/pvmfw/src/memory.rs
+++ b/guest/pvmfw/src/memory.rs
@@ -15,7 +15,7 @@
//! Low-level allocation and tracking of main memory.
use crate::entry::RebootReason;
-use crate::fdt;
+use crate::fdt::{read_initrd_range_from, read_kernel_range_from, sanitize_device_tree};
use core::num::NonZeroUsize;
use core::slice;
use log::debug;
@@ -51,44 +51,39 @@
})?;
// SAFETY: map_data validated the range to be in main memory, mapped, and not overlap.
- let fdt = unsafe { slice::from_raw_parts_mut(fdt as *mut u8, fdt_size.into()) };
-
- let info = fdt::sanitize_device_tree(fdt, vm_dtbo, vm_ref_dt)?;
- let fdt = libfdt::Fdt::from_mut_slice(fdt).map_err(|e| {
- error!("Failed to load sanitized FDT: {e}");
+ let untrusted_fdt = unsafe { slice::from_raw_parts_mut(fdt as *mut u8, fdt_size.into()) };
+ let untrusted_fdt = libfdt::Fdt::from_mut_slice(untrusted_fdt).map_err(|e| {
+ error!("Failed to load input FDT: {e}");
RebootReason::InvalidFdt
})?;
- debug!("Fdt passed validation!");
- let memory_range = info.memory_range;
+ let memory_range = untrusted_fdt.first_memory_range().map_err(|e| {
+ error!("Failed to read memory range from DT: {e}");
+ RebootReason::InvalidFdt
+ })?;
debug!("Resizing MemoryTracker to range {memory_range:#x?}");
resize_available_memory(&memory_range).map_err(|e| {
error!("Failed to use memory range value from DT: {memory_range:#x?}: {e}");
RebootReason::InvalidFdt
})?;
- init_shared_pool(info.swiotlb_info.fixed_range()).map_err(|e| {
- error!("Failed to initialize shared pool: {e}");
- RebootReason::InternalError
+ let kernel_range = read_kernel_range_from(untrusted_fdt).map_err(|e| {
+ error!("Failed to read kernel range: {e}");
+ RebootReason::InvalidFdt
})?;
-
- let (kernel_start, kernel_size) = if let Some(r) = info.kernel_range {
- let size = r.len().try_into().map_err(|_| {
- error!("Invalid kernel size: {:#x}", r.len());
- RebootReason::InternalError
- })?;
- (r.start, size)
+ let (kernel_start, kernel_size) = if let Some(r) = kernel_range {
+ (r.start, r.len())
} else if cfg!(feature = "legacy") {
warn!("Failed to find the kernel range in the DT; falling back to legacy ABI");
- let size = NonZeroUsize::new(kernel_size).ok_or_else(|| {
- error!("Invalid kernel size: {kernel_size:#x}");
- RebootReason::InvalidPayload
- })?;
- (kernel, size)
+ (kernel, kernel_size)
} else {
error!("Failed to locate the kernel from the DT");
return Err(RebootReason::InvalidPayload);
};
+ let kernel_size = kernel_size.try_into().map_err(|_| {
+ error!("Invalid kernel size: {kernel_size:#x}");
+ RebootReason::InvalidPayload
+ })?;
map_rodata(kernel_start, kernel_size).map_err(|e| {
error!("Failed to map kernel range: {e}");
@@ -99,7 +94,11 @@
// SAFETY: map_rodata validated the range to be in main memory, mapped, and not overlap.
let kernel = unsafe { slice::from_raw_parts(kernel, kernel_size.into()) };
- let ramdisk = if let Some(r) = info.initrd_range {
+ let initrd_range = read_initrd_range_from(untrusted_fdt).map_err(|e| {
+ error!("Failed to read initrd range: {e}");
+ RebootReason::InvalidFdt
+ })?;
+ let ramdisk = if let Some(r) = initrd_range {
debug!("Located ramdisk at {r:?}");
let ramdisk_size = r.len().try_into().map_err(|_| {
error!("Invalid ramdisk size: {:#x}", r.len());
@@ -118,6 +117,15 @@
None
};
+ let info = sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt)?;
+ debug!("Fdt passed validation!");
+ let fdt = untrusted_fdt;
+
+ init_shared_pool(info.swiotlb_info.fixed_range()).map_err(|e| {
+ error!("Failed to initialize shared pool: {e}");
+ RebootReason::InternalError
+ })?;
+
Ok(Self { fdt, kernel, ramdisk })
}
}