diff --git a/rust/uefi/stub/src/fat.rs b/rust/uefi/stub/src/fat.rs index db3b416..c852f91 100644 --- a/rust/uefi/stub/src/fat.rs +++ b/rust/uefi/stub/src/fat.rs @@ -39,14 +39,18 @@ impl EmbeddedConfiguration { } } -pub fn boot_linux(handle: Handle, mut system_table: SystemTable) -> Status { +pub fn boot_linux( + handle: Handle, + mut system_table: SystemTable, + dynamic_initrds: Vec>, +) -> Status { uefi_services::init(&mut system_table).unwrap(); // SAFETY: We get a slice that represents our currently running // image and then parse the PE data structures from it. This is // safe, because we don't touch any data in the data sections that // might conceivably change while we look at the slice. - let config = unsafe { + let mut config = unsafe { EmbeddedConfiguration::new( booted_image_file(system_table.boot_services()) .unwrap() @@ -62,5 +66,16 @@ pub fn boot_linux(handle: Handle, mut system_table: SystemTable) -> Status secure_boot_enabled, ); - boot_linux_unchecked(handle, system_table, config.kernel, &cmdline, config.initrd).status() + let mut final_initrd = Vec::new(); + final_initrd.append(&mut config.initrd); + + // Correctness: dynamic initrds are supposed to be validated by caller, + // i.e. they are system extension images or credentials + // that are supposedly measured in TPM2. + // Therefore, it is normal to not verify their hashes against a configuration. + for mut extra_initrd in dynamic_initrds { + final_initrd.append(&mut extra_initrd); + } + + boot_linux_unchecked(handle, system_table, config.kernel, &cmdline, final_initrd).status() } diff --git a/rust/uefi/stub/src/main.rs b/rust/uefi/stub/src/main.rs index bc5c6de..ff00113 100644 --- a/rust/uefi/stub/src/main.rs +++ b/rust/uefi/stub/src/main.rs @@ -15,6 +15,7 @@ mod thin; #[cfg(all(feature = "fat", feature = "thin"))] compile_error!("A thin and fat stub cannot be produced at the same time, disable either `thin` or `fat` feature"); +use alloc::vec::Vec; use linux_bootloader::efivars::{export_efi_variables, get_loader_features, EfiLoaderFeatures}; use linux_bootloader::measure::measure_image; use linux_bootloader::tpm::tpm_available; @@ -69,15 +70,18 @@ fn main(handle: Handle, mut system_table: SystemTable) -> Status { export_efi_variables(STUB_NAME, &system_table).expect("Failed to export stub EFI variables"); let status; + // A list of dynamically assembled initrds, e.g. credential initrds or system extension + // initrds. + let dynamic_initrds: Vec> = Vec::new(); #[cfg(feature = "fat")] { - status = fat::boot_linux(handle, system_table) + status = fat::boot_linux(handle, system_table, dynamic_initrds) } #[cfg(feature = "thin")] { - status = thin::boot_linux(handle, system_table).status() + status = thin::boot_linux(handle, system_table, dynamic_initrds).status() } status diff --git a/rust/uefi/stub/src/thin.rs b/rust/uefi/stub/src/thin.rs index f83e65a..aeb82a5 100644 --- a/rust/uefi/stub/src/thin.rs +++ b/rust/uefi/stub/src/thin.rs @@ -1,3 +1,4 @@ +use alloc::vec::Vec; use log::{error, warn}; use sha2::{Digest, Sha256}; use uefi::{fs::FileSystem, prelude::*, CString16, Result}; @@ -75,7 +76,11 @@ fn check_hash(data: &[u8], expected_hash: Hash, name: &str, secure_boot: bool) - Ok(()) } -pub fn boot_linux(handle: Handle, mut system_table: SystemTable) -> uefi::Result<()> { +pub fn boot_linux( + handle: Handle, + mut system_table: SystemTable, + dynamic_initrds: Vec>, +) -> uefi::Result<()> { uefi_services::init(&mut system_table).unwrap(); // SAFETY: We get a slice that represents our currently running @@ -94,7 +99,7 @@ pub fn boot_linux(handle: Handle, mut system_table: SystemTable) -> uefi:: let secure_boot_enabled = get_secure_boot_status(system_table.runtime_services()); let kernel_data; - let initrd_data; + let mut initrd_data; { let file_system = system_table @@ -130,5 +135,13 @@ pub fn boot_linux(handle: Handle, mut system_table: SystemTable) -> uefi:: secure_boot_enabled, )?; + // Correctness: dynamic initrds are supposed to be validated by caller, + // i.e. they are system extension images or credentials + // that are supposedly measured in TPM2. + // Therefore, it is normal to not verify their hashes against a configuration. + for mut extra_initrd in dynamic_initrds { + initrd_data.append(&mut extra_initrd); + } + boot_linux_unchecked(handle, system_table, kernel_data, &cmdline, initrd_data) }