-
Notifications
You must be signed in to change notification settings - Fork 160
Composefs soft reboot #1828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Composefs soft reboot #1828
Changes from all commits
0a67a18
9fbe6f4
fc59c78
ed36245
9e150ae
c59be87
2bbc6d7
3a1faf7
2a9d6d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,11 +79,8 @@ use cap_std_ext::{ | |
| use clap::ValueEnum; | ||
| use composefs::fs::read_file; | ||
| use composefs::tree::RegularFile; | ||
| use composefs_boot::bootloader::{PEType, EFI_ADDON_DIR_EXT, EFI_ADDON_FILE_EXT, EFI_EXT}; | ||
| use composefs_boot::BootOps; | ||
| use composefs_boot::{ | ||
| bootloader::{PEType, EFI_ADDON_DIR_EXT, EFI_ADDON_FILE_EXT, EFI_EXT}, | ||
| uki::UkiError, | ||
| }; | ||
| use fn_error_context::context; | ||
| use ostree_ext::composefs::fsverity::{FsVerityHashValue, Sha512HashValue}; | ||
| use ostree_ext::composefs_boot::bootloader::UsrLibModulesVmlinuz; | ||
|
|
@@ -338,6 +335,30 @@ fn compute_boot_digest( | |
| Ok(hex::encode(digest)) | ||
| } | ||
|
|
||
| /// Compute SHA256Sum of .linux + .initrd section of the UKI | ||
| /// | ||
| /// # Arguments | ||
| /// * entry - BootEntry containing VMlinuz and Initrd | ||
| /// * repo - The composefs repository | ||
| #[context("Computing boot digest")] | ||
| pub(crate) fn compute_boot_digest_uki(uki: &[u8]) -> Result<String> { | ||
| let vmlinuz = composefs_boot::uki::get_section(uki, ".linux") | ||
| .ok_or_else(|| anyhow::anyhow!(".linux not present"))??; | ||
|
|
||
| let initramfs = composefs_boot::uki::get_section(uki, ".initrd") | ||
| .ok_or_else(|| anyhow::anyhow!(".initrd not present"))??; | ||
|
|
||
| let mut hasher = openssl::hash::Hasher::new(openssl::hash::MessageDigest::sha256()) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should perhaps use sha512 just on general principle for stuff like this given the post-quantum crypto stuff. It's not like this logic is seriously performance sensitive anyways. |
||
| .context("Creating hasher")?; | ||
|
|
||
| hasher.update(&vmlinuz).context("hashing vmlinuz")?; | ||
| hasher.update(&initramfs).context("hashing initrd")?; | ||
|
|
||
| let digest: &[u8] = &hasher.finish().context("Finishing digest")?; | ||
|
|
||
| Ok(hex::encode(digest)) | ||
| } | ||
|
|
||
| /// Given the SHA256 sum of current VMlinuz + Initrd combo, find boot entry with the same SHA256Sum | ||
| /// | ||
| /// # Returns | ||
|
|
@@ -773,10 +794,11 @@ pub(crate) fn setup_composefs_bls_boot( | |
| Ok(boot_digest) | ||
| } | ||
|
|
||
| struct UKILabels { | ||
| struct UKIInfo { | ||
| boot_label: String, | ||
| version: Option<String>, | ||
| os_id: Option<String>, | ||
| boot_digest: String, | ||
| } | ||
|
|
||
| /// Writes a PortableExecutable to ESP along with any PE specific or Global addons | ||
|
|
@@ -790,10 +812,10 @@ fn write_pe_to_esp( | |
| is_insecure_from_opts: bool, | ||
| mounted_efi: impl AsRef<Path>, | ||
| bootloader: &Bootloader, | ||
| ) -> Result<Option<UKILabels>> { | ||
| ) -> Result<Option<UKIInfo>> { | ||
| let efi_bin = read_file(file, &repo).context("Reading .efi binary")?; | ||
|
|
||
| let mut boot_label: Option<UKILabels> = None; | ||
| let mut boot_label: Option<UKIInfo> = None; | ||
|
|
||
| // UKI Extension might not even have a cmdline | ||
| // TODO: UKI Addon might also have a composefs= cmdline? | ||
|
|
@@ -823,15 +845,17 @@ fn write_pe_to_esp( | |
| ); | ||
| } | ||
|
|
||
| let osrel = uki::get_text_section(&efi_bin, ".osrel") | ||
| .ok_or(UkiError::PortableExecutableError)??; | ||
| let osrel = uki::get_text_section(&efi_bin, ".osrel")?; | ||
|
|
||
| let parsed_osrel = OsReleaseInfo::parse(osrel); | ||
|
|
||
| boot_label = Some(UKILabels { | ||
| let boot_digest = compute_boot_digest_uki(&efi_bin)?; | ||
|
|
||
| boot_label = Some(UKIInfo { | ||
| boot_label: uki::get_boot_label(&efi_bin).context("Getting UKI boot label")?, | ||
| version: parsed_osrel.get_version(), | ||
| os_id: parsed_osrel.get_value(&["ID"]), | ||
| boot_digest, | ||
| }); | ||
| } | ||
|
|
||
|
|
@@ -981,7 +1005,7 @@ fn write_grub_uki_menuentry( | |
| fn write_systemd_uki_config( | ||
| esp_dir: &Dir, | ||
| setup_type: &BootSetupType, | ||
| boot_label: UKILabels, | ||
| boot_label: UKIInfo, | ||
| id: &Sha512HashValue, | ||
| ) -> Result<()> { | ||
| let os_id = boot_label.os_id.as_deref().unwrap_or("bootc"); | ||
|
|
@@ -1052,7 +1076,7 @@ pub(crate) fn setup_composefs_uki_boot( | |
| repo: crate::store::ComposefsRepository, | ||
| id: &Sha512HashValue, | ||
| entries: Vec<ComposefsBootEntry<Sha512HashValue>>, | ||
| ) -> Result<()> { | ||
| ) -> Result<String> { | ||
| let (root_path, esp_device, bootloader, is_insecure_from_opts, uki_addons) = match setup_type { | ||
| BootSetupType::Setup((root_setup, state, postfetch, ..)) => { | ||
| state.require_no_kargs_for_uki()?; | ||
|
|
@@ -1085,7 +1109,7 @@ pub(crate) fn setup_composefs_uki_boot( | |
|
|
||
| let esp_mount = mount_esp(&esp_device).context("Mounting ESP")?; | ||
|
|
||
| let mut uki_label: Option<UKILabels> = None; | ||
| let mut uki_info: Option<UKIInfo> = None; | ||
|
|
||
| for entry in entries { | ||
| match entry { | ||
|
|
@@ -1134,28 +1158,26 @@ pub(crate) fn setup_composefs_uki_boot( | |
| )?; | ||
|
|
||
| if let Some(label) = ret { | ||
| uki_label = Some(label); | ||
| uki_info = Some(label); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| let uki_label = uki_label | ||
| .ok_or_else(|| anyhow::anyhow!("Failed to get version and boot label from UKI"))?; | ||
| let uki_info = | ||
| uki_info.ok_or_else(|| anyhow::anyhow!("Failed to get version and boot label from UKI"))?; | ||
|
|
||
| let boot_digest = uki_info.boot_digest.clone(); | ||
|
|
||
| match bootloader { | ||
| Bootloader::Grub => write_grub_uki_menuentry( | ||
| root_path, | ||
| &setup_type, | ||
| uki_label.boot_label, | ||
| id, | ||
| &esp_device, | ||
| )?, | ||
| Bootloader::Grub => { | ||
| write_grub_uki_menuentry(root_path, &setup_type, uki_info.boot_label, id, &esp_device)? | ||
| } | ||
|
|
||
| Bootloader::Systemd => write_systemd_uki_config(&esp_mount.fd, &setup_type, uki_label, id)?, | ||
| Bootloader::Systemd => write_systemd_uki_config(&esp_mount.fd, &setup_type, uki_info, id)?, | ||
| }; | ||
|
|
||
| Ok(()) | ||
| Ok(boot_digest) | ||
| } | ||
|
|
||
| pub struct SecurebootKeys { | ||
|
|
@@ -1252,20 +1274,15 @@ pub(crate) async fn setup_composefs_boot( | |
| }; | ||
|
|
||
| let boot_type = BootType::from(entry); | ||
| let mut boot_digest: Option<String> = None; | ||
|
|
||
| match boot_type { | ||
| BootType::Bls => { | ||
| let digest = setup_composefs_bls_boot( | ||
| BootSetupType::Setup((&root_setup, &state, &postfetch, &fs)), | ||
| repo, | ||
| &id, | ||
| entry, | ||
| &mounted_fs, | ||
| )?; | ||
|
|
||
| boot_digest = Some(digest); | ||
| } | ||
| let boot_digest = match boot_type { | ||
| BootType::Bls => setup_composefs_bls_boot( | ||
| BootSetupType::Setup((&root_setup, &state, &postfetch, &fs)), | ||
| repo, | ||
| &id, | ||
| entry, | ||
| &mounted_fs, | ||
| )?, | ||
| BootType::Uki => setup_composefs_uki_boot( | ||
| BootSetupType::Setup((&root_setup, &state, &postfetch, &fs)), | ||
| repo, | ||
|
|
@@ -1276,7 +1293,7 @@ pub(crate) async fn setup_composefs_boot( | |
|
|
||
| write_composefs_state( | ||
| &root_setup.physical_root_path, | ||
| id, | ||
| &id, | ||
| &crate::spec::ImageReference::from(state.target_imgref.clone()), | ||
| false, | ||
| boot_type, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker but I wonder if we should hard require an initrd? In theory some use cases could probably go without.
OK for us we obviously hard require it to mount composefs, but since this is a generic interface; per the spec https://uapi-group.org/specifications/specs/unified_kernel_image/#uki-file-format