Skip to content

Commit 7a5ce1e

Browse files
Johan-Liebert1cgwalters
authored andcommitted
composefs/install: Store the entire UKI cmdline
Instead of only getting the "insecure" bit from the composefs parameter in the UKI kernel commandline, store the entire thing Tests written by Claude Assisted-by: Claude Code (Opus) Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent e42d10d commit 7a5ce1e

4 files changed

Lines changed: 85 additions & 27 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/lib/src/bootc_composefs/status.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ impl ComposefsCmdline {
7777
digest: digest_str.into(),
7878
}
7979
}
80+
81+
/// Search for the `composefs=` parameter in the passed in kernel command line
82+
pub(crate) fn find_in_cmdline(cmdline: &Cmdline) -> Option<Self> {
83+
match cmdline.find(COMPOSEFS_CMDLINE) {
84+
Some(param) => {
85+
let value = param.value()?;
86+
Some(Self::new(value))
87+
}
88+
None => None,
89+
}
90+
}
8091
}
8192

8293
impl std::fmt::Display for ComposefsCmdline {
@@ -935,4 +946,56 @@ mod tests {
935946

936947
Ok(())
937948
}
949+
950+
#[test]
951+
fn test_find_in_cmdline() {
952+
const DIGEST: &str = "8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52";
953+
954+
// Test case: cmdline contains composefs parameter
955+
let cmdline = Cmdline::from(format!("root=UUID=abc123 rw composefs={}", DIGEST));
956+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
957+
assert!(result.is_some());
958+
let cfs = result.unwrap();
959+
assert_eq!(cfs.digest.as_ref(), DIGEST);
960+
assert!(!cfs.allow_missing_fsverity);
961+
962+
// Test case: cmdline contains composefs parameter with allow_missing_fsverity
963+
let cmdline = Cmdline::from(format!("root=UUID=abc123 rw composefs=?{}", DIGEST));
964+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
965+
assert!(result.is_some());
966+
let cfs = result.unwrap();
967+
assert_eq!(cfs.digest.as_ref(), DIGEST);
968+
assert!(cfs.allow_missing_fsverity);
969+
970+
// Test case: cmdline does not contain composefs parameter
971+
let cmdline = Cmdline::from("root=UUID=abc123 rw quiet");
972+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
973+
assert!(result.is_none());
974+
975+
// Test case: empty cmdline
976+
let cmdline = Cmdline::from("");
977+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
978+
assert!(result.is_none());
979+
980+
// Test case: cmdline with other parameters and composefs at different positions
981+
let cmdline = Cmdline::from(format!("quiet composefs={} loglevel=3", DIGEST));
982+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
983+
assert!(result.is_some());
984+
let cfs = result.unwrap();
985+
assert_eq!(cfs.digest.as_ref(), DIGEST);
986+
assert!(!cfs.allow_missing_fsverity);
987+
988+
// Test case: cmdline with composefs at the beginning
989+
let cmdline = Cmdline::from(format!("composefs=?{} root=UUID=abc123 quiet", DIGEST));
990+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
991+
assert!(result.is_some());
992+
let cfs = result.unwrap();
993+
assert_eq!(cfs.digest.as_ref(), DIGEST);
994+
assert!(cfs.allow_missing_fsverity);
995+
996+
// Test case: cmdline with similar parameter names (should not match)
997+
let cmdline = Cmdline::from(format!("composefs_backup={} root=UUID=abc123", DIGEST));
998+
let result = ComposefsCmdline::find_in_cmdline(&cmdline);
999+
assert!(result.is_none());
1000+
}
9381001
}

crates/lib/src/install.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ use serde::{Deserialize, Serialize};
187187

188188
#[cfg(feature = "install-to-disk")]
189189
use self::baseline::InstallBlockDeviceOpts;
190+
use crate::bootc_composefs::status::ComposefsCmdline;
190191
use crate::bootc_composefs::{boot::setup_composefs_boot, repo::initialize_composefs_repository};
191192
use crate::boundimage::{BoundImage, ResolvedBoundImage};
192193
use crate::containerenv::ContainerExecutionInfo;
@@ -1679,10 +1680,12 @@ async fn prepare_install(
16791680
// NOTE: This isn't really 100% accurate 100% of the time as the cmdline can be in an addon
16801681
match kernel {
16811682
Some(k) => match k.k_type {
1682-
crate::kernel::KernelType::Uki {
1683-
allow_missing_fsverity,
1684-
..
1685-
} => {
1683+
crate::kernel::KernelType::Uki { cmdline, .. } => {
1684+
let allow_missing_fsverity = cmdline.is_some_and(|cmd| {
1685+
ComposefsCmdline::find_in_cmdline(&cmd)
1686+
.is_some_and(|cfs_cmdline| cfs_cmdline.allow_missing_fsverity)
1687+
});
1688+
16861689
if !allow_missing_fsverity {
16871690
anyhow::ensure!(
16881691
root_filesystem.supports_fsverity(),
@@ -1703,14 +1706,14 @@ async fn prepare_install(
17031706
// If `--allow-missing-verity` is already passed via CLI, don't modify
17041707
if composefs_options.composefs_backend && !composefs_options.allow_missing_verity && !is_uki {
17051708
composefs_options.allow_missing_verity = !root_filesystem.supports_fsverity();
1706-
1707-
tracing::info!(
1708-
allow_missing_fsverity = composefs_options.allow_missing_verity,
1709-
uki = is_uki,
1710-
"ComposeFS install prep",
1711-
);
17121709
}
17131710

1711+
tracing::info!(
1712+
allow_missing_fsverity = composefs_options.allow_missing_verity,
1713+
uki = is_uki,
1714+
"ComposeFS install prep",
1715+
);
1716+
17141717
if let Some(crate::spec::Bootloader::None) = config_opts.bootloader {
17151718
if cfg!(target_arch = "s390x") {
17161719
anyhow::bail!("Bootloader set to none is not supported for the s390x architecture");

crates/lib/src/kernel.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ use cap_std_ext::dirext::CapStdExtDirExt;
1414
use serde::Serialize;
1515

1616
use crate::bootc_composefs::boot::EFI_LINUX;
17-
use crate::bootc_composefs::status::ComposefsCmdline;
18-
use crate::composefs_consts::COMPOSEFS_CMDLINE;
1917

2018
/// Information about the kernel in a container image.
2119
#[derive(Debug, Serialize)]
@@ -37,7 +35,9 @@ pub(crate) struct Kernel {
3735
pub(crate) enum KernelType {
3836
Uki {
3937
path: Utf8PathBuf,
40-
allow_missing_fsverity: bool,
38+
/// The commandline we found in the UKI
39+
/// Again due to UKI Addons, we may or may not have it in the UKI itself
40+
cmdline: Option<Cmdline<'static>>,
4141
},
4242
Vmlinuz {
4343
path: Utf8PathBuf,
@@ -79,31 +79,23 @@ pub(crate) fn find_kernel(root: &Dir) -> Result<Option<KernelInternal>> {
7979
// Best effort to check for composefs=?verity in the UKI cmdline
8080
let cmdline = composefs_boot::uki::get_section(&uki, ".cmdline");
8181

82-
let allow_missing_fsverity = match cmdline {
82+
let cmdline = match cmdline {
8383
Some(Ok(cmdline)) => {
8484
let cmdline_str = std::str::from_utf8(cmdline)?;
85-
86-
let cmdline = Cmdline::from(cmdline_str);
87-
88-
match cmdline.find(COMPOSEFS_CMDLINE) {
89-
Some(param) => ComposefsCmdline::new(&param).allow_missing_fsverity,
90-
91-
// The cmdline might be in an addon, so don't allow missing verity
92-
None => false,
93-
}
85+
Some(Cmdline::from(cmdline_str.to_owned()))
9486
}
9587

9688
Some(Err(uki_error)) => match uki_error {
9789
composefs_boot::uki::UkiError::MissingSection(_) => {
9890
// TODO(Johan-Liebert1): Check this when we have full UKI Addons support
9991
// The cmdline might be in an addon, so don't allow missing verity
100-
false
92+
None
10193
}
10294

10395
e => anyhow::bail!("Failed to read UKI cmdline: {e:?}"),
10496
},
10597

106-
None => false,
98+
None => None,
10799
};
108100

109101
return Ok(Some(KernelInternal {
@@ -113,7 +105,7 @@ pub(crate) fn find_kernel(root: &Dir) -> Result<Option<KernelInternal>> {
113105
},
114106
k_type: KernelType::Uki {
115107
path: uki_path,
116-
allow_missing_fsverity,
108+
cmdline,
117109
},
118110
}));
119111
}

0 commit comments

Comments
 (0)