Merge pull request #305 from nix-community/prepare-stub-for-dynamic-initrds

stub(*): support dynamic initrds
This commit is contained in:
Ryan Lahfa 2024-03-01 08:24:07 +00:00 committed by GitHub
commit 614b538f0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 39 additions and 7 deletions

View File

@ -39,14 +39,18 @@ impl EmbeddedConfiguration {
} }
} }
pub fn boot_linux(handle: Handle, mut system_table: SystemTable<Boot>) -> Status { pub fn boot_linux(
handle: Handle,
mut system_table: SystemTable<Boot>,
dynamic_initrds: Vec<Vec<u8>>,
) -> Status {
uefi_services::init(&mut system_table).unwrap(); uefi_services::init(&mut system_table).unwrap();
// SAFETY: We get a slice that represents our currently running // SAFETY: We get a slice that represents our currently running
// image and then parse the PE data structures from it. This is // 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 // safe, because we don't touch any data in the data sections that
// might conceivably change while we look at the slice. // might conceivably change while we look at the slice.
let config = unsafe { let mut config = unsafe {
EmbeddedConfiguration::new( EmbeddedConfiguration::new(
booted_image_file(system_table.boot_services()) booted_image_file(system_table.boot_services())
.unwrap() .unwrap()
@ -62,5 +66,16 @@ pub fn boot_linux(handle: Handle, mut system_table: SystemTable<Boot>) -> Status
secure_boot_enabled, 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()
} }

View File

@ -15,6 +15,7 @@ mod thin;
#[cfg(all(feature = "fat", feature = "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"); 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::efivars::{export_efi_variables, get_loader_features, EfiLoaderFeatures};
use linux_bootloader::measure::measure_image; use linux_bootloader::measure::measure_image;
use linux_bootloader::tpm::tpm_available; use linux_bootloader::tpm::tpm_available;
@ -69,15 +70,18 @@ fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
export_efi_variables(STUB_NAME, &system_table).expect("Failed to export stub EFI variables"); export_efi_variables(STUB_NAME, &system_table).expect("Failed to export stub EFI variables");
let status; let status;
// A list of dynamically assembled initrds, e.g. credential initrds or system extension
// initrds.
let dynamic_initrds: Vec<Vec<u8>> = Vec::new();
#[cfg(feature = "fat")] #[cfg(feature = "fat")]
{ {
status = fat::boot_linux(handle, system_table) status = fat::boot_linux(handle, system_table, dynamic_initrds)
} }
#[cfg(feature = "thin")] #[cfg(feature = "thin")]
{ {
status = thin::boot_linux(handle, system_table).status() status = thin::boot_linux(handle, system_table, dynamic_initrds).status()
} }
status status

View File

@ -1,3 +1,4 @@
use alloc::vec::Vec;
use log::{error, warn}; use log::{error, warn};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use uefi::{fs::FileSystem, prelude::*, CString16, Result}; 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(()) Ok(())
} }
pub fn boot_linux(handle: Handle, mut system_table: SystemTable<Boot>) -> uefi::Result<()> { pub fn boot_linux(
handle: Handle,
mut system_table: SystemTable<Boot>,
dynamic_initrds: Vec<Vec<u8>>,
) -> uefi::Result<()> {
uefi_services::init(&mut system_table).unwrap(); uefi_services::init(&mut system_table).unwrap();
// SAFETY: We get a slice that represents our currently running // SAFETY: We get a slice that represents our currently running
@ -94,7 +99,7 @@ pub fn boot_linux(handle: Handle, mut system_table: SystemTable<Boot>) -> uefi::
let secure_boot_enabled = get_secure_boot_status(system_table.runtime_services()); let secure_boot_enabled = get_secure_boot_status(system_table.runtime_services());
let kernel_data; let kernel_data;
let initrd_data; let mut initrd_data;
{ {
let file_system = system_table let file_system = system_table
@ -130,5 +135,13 @@ pub fn boot_linux(handle: Handle, mut system_table: SystemTable<Boot>) -> uefi::
secure_boot_enabled, 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) boot_linux_unchecked(handle, system_table, kernel_data, &cmdline, initrd_data)
} }