pvmfw: Move DT sanitization to main()
Move it so that it can re-use other inputs e.g. VBMeta capabilities.
This should not compromise the integrity of pvmfw as it still happens
before the DT is used to initialize the PCI bus and swiotlb region.
Move the shared memory setup to main(), so that it only happens when
actually needed i.e. when the instance.img is used, requiring a shared
region for the VirtIO transport.
Bug: 339782511
Bug: 377276983
Test: m pvmfw_bin
Change-Id: I6de6e4607d110c2f8fffd9a3d9527716dca92565
diff --git a/guest/pvmfw/src/entry.rs b/guest/pvmfw/src/entry.rs
index 2f0b391..2463984 100644
--- a/guest/pvmfw/src/entry.rs
+++ b/guest/pvmfw/src/entry.rs
@@ -120,13 +120,7 @@
let config_entries = appended.get_entries();
- let slices = memory::MemorySlices::new(
- fdt,
- payload,
- payload_size,
- config_entries.vm_dtbo,
- config_entries.vm_ref_dt,
- )?;
+ let slices = memory::MemorySlices::new(fdt, payload, payload_size)?;
// This wrapper allows main() to be blissfully ignorant of platform details.
let (next_bcc, debuggable_payload) = crate::main(
@@ -135,6 +129,8 @@
slices.ramdisk,
config_entries.bcc,
config_entries.debug_policy,
+ config_entries.vm_dtbo,
+ config_entries.vm_ref_dt,
)?;
// Writable-dirty regions will be flushed when MemoryTracker is dropped.
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index bde03ff..9f9614a 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -35,7 +35,7 @@
use crate::bcc::Bcc;
use crate::dice::PartialInputs;
use crate::entry::RebootReason;
-use crate::fdt::modify_for_next_stage;
+use crate::fdt::{modify_for_next_stage, sanitize_device_tree};
use crate::helpers::GUEST_PAGE_SIZE;
use crate::instance::EntryBody;
use crate::instance::Error as InstanceError;
@@ -54,21 +54,23 @@
use pvmfw_embedded_key::PUBLIC_KEY;
use vmbase::fdt::pci::{PciError, PciInfo};
use vmbase::heap;
-use vmbase::memory::flush;
+use vmbase::memory::{flush, init_shared_pool};
use vmbase::rand;
use vmbase::virtio::pci;
const NEXT_BCC_SIZE: usize = GUEST_PAGE_SIZE;
fn main(
- fdt: &mut Fdt,
+ untrusted_fdt: &mut Fdt,
signed_kernel: &[u8],
ramdisk: Option<&[u8]>,
current_bcc_handover: &[u8],
mut debug_policy: Option<&[u8]>,
+ vm_dtbo: Option<&mut [u8]>,
+ vm_ref_dt: Option<&[u8]>,
) -> Result<(Range<usize>, bool), RebootReason> {
info!("pVM firmware");
- debug!("FDT: {:?}", fdt.as_ptr());
+ debug!("FDT: {:?}", untrusted_fdt.as_ptr());
debug!("Signed kernel: {:?} ({:#x} bytes)", signed_kernel.as_ptr(), signed_kernel.len());
debug!("AVB public key: addr={:?}, size={:#x} ({1})", PUBLIC_KEY.as_ptr(), PUBLIC_KEY.len());
if let Some(rd) = ramdisk {
@@ -97,14 +99,6 @@
debug_policy = None;
}
- // Set up PCI bus for VirtIO devices.
- let pci_info = PciInfo::from_fdt(fdt).map_err(handle_pci_error)?;
- debug!("PCI: {:#x?}", pci_info);
- let mut pci_root = pci::initialize(pci_info).map_err(|e| {
- error!("Failed to initialize PCI: {e}");
- RebootReason::InternalError
- })?;
-
let verified_boot_data = verify_payload(signed_kernel, ramdisk, PUBLIC_KEY).map_err(|e| {
error!("Failed to verify the payload: {e}");
RebootReason::PayloadVerificationError
@@ -115,6 +109,20 @@
info!("Please disregard any previous libavb ERROR about initrd_normal.");
}
+ let fdt_info = sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt)?;
+ let fdt = untrusted_fdt; // DT has now been sanitized.
+ let pci_info = PciInfo::from_fdt(fdt).map_err(handle_pci_error)?;
+ debug!("PCI: {:#x?}", pci_info);
+ // Set up PCI bus for VirtIO devices.
+ let mut pci_root = pci::initialize(pci_info).map_err(|e| {
+ error!("Failed to initialize PCI: {e}");
+ RebootReason::InternalError
+ })?;
+ init_shared_pool(fdt_info.swiotlb_info.fixed_range()).map_err(|e| {
+ error!("Failed to initialize shared pool: {e}");
+ RebootReason::InternalError
+ })?;
+
let next_bcc = heap::aligned_boxed_slice(NEXT_BCC_SIZE, GUEST_PAGE_SIZE).ok_or_else(|| {
error!("Failed to allocate the next-stage BCC");
RebootReason::InternalError
diff --git a/guest/pvmfw/src/memory.rs b/guest/pvmfw/src/memory.rs
index e51a730..d2f63b5 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::{read_initrd_range_from, read_kernel_range_from, sanitize_device_tree};
+use crate::fdt::{read_initrd_range_from, read_kernel_range_from};
use core::num::NonZeroUsize;
use core::slice;
use log::debug;
@@ -24,7 +24,7 @@
use log::warn;
use vmbase::{
layout::crosvm,
- memory::{init_shared_pool, map_data, map_rodata, resize_available_memory},
+ memory::{map_data, map_rodata, resize_available_memory},
};
pub(crate) struct MemorySlices<'a> {
@@ -34,13 +34,7 @@
}
impl<'a> MemorySlices<'a> {
- pub fn new(
- fdt: usize,
- kernel: usize,
- kernel_size: usize,
- vm_dtbo: Option<&mut [u8]>,
- vm_ref_dt: Option<&[u8]>,
- ) -> Result<Self, RebootReason> {
+ pub fn new(fdt: usize, kernel: usize, kernel_size: usize) -> Result<Self, RebootReason> {
let fdt_size = NonZeroUsize::new(crosvm::FDT_MAX_SIZE).unwrap();
// TODO - Only map the FDT as read-only, until we modify it right before jump_to_payload()
// e.g. by generating a DTBO for a template DT in main() and, on return, re-map DT as RW,
@@ -117,15 +111,6 @@
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 })
+ Ok(Self { fdt: untrusted_fdt, kernel, ramdisk })
}
}