1
0
mirror of https://github.com/containers/bootc.git synced 2026-02-05 15:45:53 +01:00

composefs/uki: Save boot digest

Similar to what we do with Type1 entries, we save the SHA256Sum of
.linux + .initrd sections of the UKI under `boot_digest` key in the
origin file

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
This commit is contained in:
Pragyan Poudyal
2025-12-10 15:15:50 +05:30
committed by Pragyan Poudyal
parent 969dfd438e
commit 13113d8c8f
2 changed files with 61 additions and 43 deletions

View File

@@ -338,6 +338,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())
.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 +797,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 +815,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?
@@ -828,10 +853,13 @@ fn write_pe_to_esp(
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 +1009,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 +1080,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 +1113,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 +1162,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 +1278,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,

View File

@@ -240,18 +240,15 @@ pub(crate) async fn do_upgrade(
)?;
let boot_type = BootType::from(entry);
let mut boot_digest = None;
match boot_type {
BootType::Bls => {
boot_digest = Some(setup_composefs_bls_boot(
BootSetupType::Upgrade((storage, &fs, &host)),
repo,
&id,
entry,
&mounted_fs,
)?)
}
let boot_digest = match boot_type {
BootType::Bls => setup_composefs_bls_boot(
BootSetupType::Upgrade((storage, &fs, &host)),
repo,
&id,
entry,
&mounted_fs,
)?,
BootType::Uki => setup_composefs_uki_boot(
BootSetupType::Upgrade((storage, &fs, &host)),