From 534160b56aad72b314accb9c332cb0ae90f8a689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Mon, 6 Oct 2025 16:57:14 +0200 Subject: [PATCH 1/4] esp: Fix shim/grub typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shim was being assigned to the grub attribute and viceversa. It worked correctly because the shim function would return the based on the grub path attribute (that is shim) and viceversa. This commit fixes the typos. Signed-off-by: Beñat Gartzia Arruabarrena --- lib/src/esp.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/esp.rs b/lib/src/esp.rs index 3eeef3f..c70fabb 100644 --- a/lib/src/esp.rs +++ b/lib/src/esp.rs @@ -56,20 +56,20 @@ impl Esp { let esp_vendor_path = esp_vendor_path(&path_pb)?; Ok(Esp { - grub: bin_path_from_esp_vendor(&esp_vendor_path, "shimx64.efi")?, - shim: bin_path_from_esp_vendor(&esp_vendor_path, "grubx64.efi")?, + grub: bin_path_from_esp_vendor(&esp_vendor_path, "grubx64.efi")?, + shim: bin_path_from_esp_vendor(&esp_vendor_path, "shimx64.efi")?, }) } /// Tries loading the shim binary pub fn shim(&self) -> pefile::PeFile { - pefile::PeFile::load_from_file(&self.grub.to_string_lossy(), false) + pefile::PeFile::load_from_file(&self.shim.to_string_lossy(), false) .expect("Can't open shim binary") } /// Tries loading the grub binary pub fn grub(&self) -> pefile::PeFile { - pefile::PeFile::load_from_file(&self.shim.to_string_lossy(), false) + pefile::PeFile::load_from_file(&self.grub.to_string_lossy(), false) .expect("Can't open grub binary") } } From 3f692e745ea4774f145189b7949f942df9ee2b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Tue, 9 Sep 2025 16:30:00 +0200 Subject: [PATCH 2/4] justfile: Parametrize target container image mountpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit defines a variable with a default value pointing into the path in which the target container image will be mounted. This will allow us to avoid copying and pasting the path around. Signed-off-by: Beñat Gartzia Arruabarrena --- justfile | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/justfile b/justfile index d92794a..a903f05 100644 --- a/justfile +++ b/justfile @@ -7,6 +7,7 @@ image := "https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/42. target_container_ociarchive_path := absolute_path(join("/tmp", file_name(image))) target_container_name := without_extension(file_name(image)) target_container_osinfo_path := "/tmp/compute-pcrs-osinfo" +target_container_mount_point := "/var/srv/image" container_image_name := "compute-pcrs" skip_build := "false" @@ -49,11 +50,11 @@ test-container: prepare-test-deps podman run --rm \ --security-opt label=disable \ -v $PWD/test-data/:/var/srv/test-data \ - --mount=type=image,source={{target_container_name}},destination=/var/srv/image,rw=false \ + --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs all \ - --kernels /var/srv/image/usr/lib/modules \ - --esp /var/srv/image/usr/lib/bootupd/updates \ + --kernels {{target_container_mount_point}}/usr/lib/modules \ + --esp {{target_container_mount_point}}/usr/lib/bootupd/updates \ --efivars /var/srv/test-data/efivars/qemu-ovmf/${ID}-${VERSION_ID} \ --mok-variables /var/srv/test-data/mok-variables/${ID}-${VERSION_ID} \ > test/result.json 2>/dev/null @@ -95,11 +96,11 @@ test-vmlinuz: prepare-test-deps podman run --rm \ --security-opt label=disable \ -v $PWD/test-data/:/var/srv/test-data \ - --mount=type=image,source={{target_container_name}},destination=/var/srv/image,rw=false \ + --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr4 \ - --kernels /var/srv/image/usr/lib/modules \ - --esp /var/srv/image/usr/lib/bootupd/updates + --kernels {{target_container_mount_point}}/usr/lib/modules \ + --esp {{target_container_mount_point}}/usr/lib/bootupd/updates test-uki: prepare-test-deps #!/bin/bash @@ -108,7 +109,7 @@ test-uki: prepare-test-deps podman run --rm \ --security-opt label=disable \ -v $PWD/test-data/:/var/srv/test-data \ - --mount=type=image,source={{target_container_name}},destination=/var/srv/image,rw=false \ + --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr11 uki \ @@ -121,10 +122,10 @@ test-secureboot-enabled: prepare-test-deps podman run --rm \ --security-opt label=disable \ -v $PWD/test-data/:/var/srv/test-data \ - --mount=type=image,source={{target_container_name}},destination=/var/srv/image,rw=false \ + --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr7 \ - --esp /var/srv/image/usr/lib/bootupd/updates \ + --esp {{target_container_mount_point}}/usr/lib/bootupd/updates \ --efivars /var/srv/test-data/efivars/qemu-ovmf/${ID}-${VERSION_ID} \ > test/result.json 2>/dev/null diff test-fixtures/${ID}-${OSTREE_VERSION}/pcr7-sb-enabled.json test/result.json || (echo "FAILED" && exit 1) @@ -140,10 +141,10 @@ test-secureboot-disabled: prepare-test-deps podman run --rm \ --security-opt label=disable \ -v $PWD/test-data/:/var/srv/test-data \ - --mount=type=image,source={{target_container_name}},destination=/var/srv/image,rw=false \ + --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr7 \ - --esp /var/srv/image/usr/lib/bootupd/updates \ + --esp {{target_container_mount_point}}/usr/lib/bootupd/updates \ --efivars /var/srv/test-data/efivars/qemu-ovmf/${ID}-${VERSION_ID}-sb-disabled \ --secureboot-disabled \ > test/result.json 2>/dev/null @@ -159,7 +160,7 @@ test-default-mok-keys: prepare-test-deps podman run --rm \ --security-opt label=disable \ -v $PWD/test-data/:/var/srv/test-data \ - --mount=type=image,source={{target_container_name}},destination=/var/srv/image,rw=false \ + --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr14 \ --mok-variables /var/srv/test-data/mok-variables/${ID}-${VERSION_ID} \ From ef7664df6bd4f1b127e3e92defc66c48e6a25ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Mon, 6 Oct 2025 16:16:38 +0200 Subject: [PATCH 3/4] rootfs: Add submodule modelling relevant paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This submodule models where relevant files such as the shim, grub or kernel binaries are, and tries to locate them given the path to the rootfs of the target container image. Signed-off-by: Beñat Gartzia Arruabarrena --- lib/src/lib.rs | 1 + lib/src/rootfs.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 lib/src/rootfs.rs diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 1c1fa90..b634426 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -16,6 +16,7 @@ mod esp; mod linux; mod mok; pub mod pefile; +pub mod rootfs; pub mod shim; pub mod uefi; diff --git a/lib/src/rootfs.rs b/lib/src/rootfs.rs new file mode 100644 index 0000000..693b4e0 --- /dev/null +++ b/lib/src/rootfs.rs @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Timothée Ravier +// SPDX-FileCopyrightText: Beñat Gartzia Arruabarrena +// +// SPDX-License-Identifier: MIT + +use std::io; +use std::path; + +const RELATIVE_KERNELS_PATH: &str = "usr/lib/modules/"; +const RELATIVE_ESP_PATH: &str = "usr/lib/bootupd/updates/"; + +pub struct RootFSTree { + esp_path: String, + kernels_path: String, +} + +impl RootFSTree { + pub fn new(rootfs_path: &str) -> io::Result { + let rootfs_path = path::absolute(rootfs_path)?; + let kernels_path = rootfs_path.join(RELATIVE_KERNELS_PATH); + let esp_path = rootfs_path.join(RELATIVE_ESP_PATH); + Ok(RootFSTree { + esp_path: esp_path.to_str().unwrap().into(), + kernels_path: kernels_path.to_str().unwrap().into(), + }) + } + + pub fn esp(&self) -> &str { + self.esp_path.as_str() + } + + pub fn vmlinuz(&self) -> &str { + self.kernels_path.as_str() + } +} From dcd11f3f173c6b99b4088d28b1e01316cf09beb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Mon, 6 Oct 2025 17:24:50 +0200 Subject: [PATCH 4/4] cli: Only accept path to target rootfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Paths to the kernel directory and the ESP (containing both grub and shim binaries) were received as separate arguments. However, this tool is run against a single container image at a time, meaning that we could easily compute the paths to the kernel dir and the ESP dir just by knowing were the rootfs of that container image is. This commit introduces the simple logic that makes that possible, and introduces the new --rootfs argument to the CLI. Note that this commit only changes the CLI, not the library interface. Now, users of the library can use the RootFSTree abstraction added in a previous commit to compute the vmlinuz and esp paths, and then call the predict functions. This is done as it provides greater flexibility for library consumers (in favour of comfort) and changing it to only accepting the rootfs path would have meant a breaking change instead. Signed-off-by: Beñat Gartzia Arruabarrena --- cli/src/main.rs | 59 ++++++++++++++++++++++--------------------------- justfile | 10 ++++----- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 998268d..e68bf46 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -41,17 +41,10 @@ enum Command { #[arg( long, short, - default_value = "/usr/lib/modules/", - help = "Path to the kernel modules directory. This helps finding the vmlinuz image" + default_value = "/", + help = "Path to the target container image root filesystem" )] - kernels: String, - #[arg( - long, - short, - default_value = "/usr/lib/bootupd/updates/", - help = "Path to the ESP directory" - )] - esp: String, + rootfs: String, #[command(flatten)] secureboot_variables: SecureBootVarStores, #[arg( @@ -78,17 +71,10 @@ enum Command { #[arg( long, short, - default_value = "/usr/lib/modules/", - help = "Path to the kernel modules directory. This helps finding the vmlinuz image" + default_value = "/", + help = "Path to the target container image root filesystem" )] - kernels: String, - #[arg( - long, - short, - default_value = "/usr/lib/bootupd/updates/", - help = "Path to the ESP directory" - )] - esp: String, + rootfs: String, #[arg( long, default_value_t = false, @@ -107,10 +93,10 @@ enum Command { #[arg( long, short, - default_value = "/usr/lib/bootupd/updates/", - help = "Path to the ESP directory" + default_value = "/", + help = "Path to the target container image root filesystem" )] - esp: String, + rootfs: String, #[command(flatten)] secureboot_variables: SecureBootVarStores, #[arg( @@ -158,16 +144,20 @@ fn main() -> Result<()> { match &cli.command { Command::All { - kernels, - esp, + rootfs, secureboot_variables, uki, no_secureboot, mok_variables, } => { + let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); let pcrs = vec![ - compute_pcr4(kernels, esp, *uki, !no_secureboot), - compute_pcr7(secureboot_variables.efivars.as_deref(), esp, !no_secureboot), + compute_pcr4(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot), + compute_pcr7( + secureboot_variables.efivars.as_deref(), + rfs.esp(), + !no_secureboot, + ), /* compute_pcr11(), */ compute_pcr14(mok_variables), ]; @@ -178,21 +168,26 @@ fn main() -> Result<()> { Ok(()) } Command::Pcr4 { - kernels, - esp, + rootfs, uki, no_secureboot, } => { - let pcr = compute_pcr4(kernels, esp, *uki, !no_secureboot); + let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); + let pcr = compute_pcr4(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot); println!("{}", serde_json::to_string_pretty(&pcr).unwrap()); Ok(()) } Command::Pcr7 { - esp, + rootfs, secureboot_variables, no_secureboot, } => { - let pcr = compute_pcr7(secureboot_variables.efivars.as_deref(), esp, !no_secureboot); + let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); + let pcr = compute_pcr7( + secureboot_variables.efivars.as_deref(), + rfs.esp(), + !no_secureboot, + ); println!("{}", serde_json::to_string_pretty(&pcr).unwrap()); Ok(()) } diff --git a/justfile b/justfile index a903f05..1bc9509 100644 --- a/justfile +++ b/justfile @@ -53,8 +53,7 @@ test-container: prepare-test-deps --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs all \ - --kernels {{target_container_mount_point}}/usr/lib/modules \ - --esp {{target_container_mount_point}}/usr/lib/bootupd/updates \ + --rootfs {{target_container_mount_point}} \ --efivars /var/srv/test-data/efivars/qemu-ovmf/${ID}-${VERSION_ID} \ --mok-variables /var/srv/test-data/mok-variables/${ID}-${VERSION_ID} \ > test/result.json 2>/dev/null @@ -99,8 +98,7 @@ test-vmlinuz: prepare-test-deps --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr4 \ - --kernels {{target_container_mount_point}}/usr/lib/modules \ - --esp {{target_container_mount_point}}/usr/lib/bootupd/updates + --rootfs {{target_container_mount_point}} \ test-uki: prepare-test-deps #!/bin/bash @@ -125,7 +123,7 @@ test-secureboot-enabled: prepare-test-deps --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr7 \ - --esp {{target_container_mount_point}}/usr/lib/bootupd/updates \ + --rootfs {{target_container_mount_point}} \ --efivars /var/srv/test-data/efivars/qemu-ovmf/${ID}-${VERSION_ID} \ > test/result.json 2>/dev/null diff test-fixtures/${ID}-${OSTREE_VERSION}/pcr7-sb-enabled.json test/result.json || (echo "FAILED" && exit 1) @@ -144,7 +142,7 @@ test-secureboot-disabled: prepare-test-deps --mount=type=image,source={{target_container_name}},destination={{target_container_mount_point}},rw=false \ {{container_image_name}} \ compute-pcrs pcr7 \ - --esp {{target_container_mount_point}}/usr/lib/bootupd/updates \ + --rootfs {{target_container_mount_point}} \ --efivars /var/srv/test-data/efivars/qemu-ovmf/${ID}-${VERSION_ID}-sb-disabled \ --secureboot-disabled \ > test/result.json 2>/dev/null