Skip to content

Commit 2f9d914

Browse files
croissanneallisonkarlitskaya
authored andcommitted
composefs-setup-root: support insecure mounting
Looks for a "?" prepended to the `composefs=` cmdline parameter. If it is prepended, it will allow a composefs image without fs-verity. Signed-off-by: Sanne Raymaekers <[email protected]>
1 parent b65db21 commit 2f9d914

File tree

3 files changed

+28
-22
lines changed

3 files changed

+28
-22
lines changed

crates/composefs-boot/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ version.workspace = true
1313
[dependencies]
1414
anyhow = { version = "1.0.87", default-features = false }
1515
composefs = { workspace = true }
16+
hex = { version = "0.4.0", default-features = false, features = ["std"] }
1617
regex-automata = { version = "0.4.4", default-features = false, features=["hybrid", "std", "syntax"] }
1718
thiserror = { version = "2.0.0", default-features = false }
1819
zerocopy = { version = "0.8.0", default-features = false, features = ["derive"] }

crates/composefs-boot/src/cmdline.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use anyhow::{Context, Result};
2+
use composefs::fsverity::FsVerityHashValue;
3+
14
/// Perform kernel command line splitting.
25
///
36
/// The way this works in the kernel is to split on whitespace with an extremely simple quoting
@@ -24,3 +27,14 @@ pub(crate) fn split_cmdline(cmdline: &str) -> impl Iterator<Item = &str> {
2427
pub fn get_cmdline_value<'a>(cmdline: &'a str, prefix: &str) -> Option<&'a str> {
2528
split_cmdline(cmdline).find_map(|item| item.strip_prefix(prefix))
2629
}
30+
31+
pub fn get_cmdline_composefs<ObjectID: FsVerityHashValue>(
32+
cmdline: &str,
33+
) -> Result<(ObjectID, bool)> {
34+
let id = get_cmdline_value(cmdline, "composefs=").context("composefs= value not found")?;
35+
if let Some(stripped) = id.strip_prefix('?') {
36+
Ok((ObjectID::from_hex(stripped)?, true))
37+
} else {
38+
Ok((ObjectID::from_hex(id)?, false))
39+
}
40+
}

crates/composefs-setup-root/src/main.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55
path::{Path, PathBuf},
66
};
77

8-
use anyhow::{bail, Context, Result};
8+
use anyhow::{Context, Result};
99
use clap::Parser;
1010
use rustix::{
1111
fs::{major, minor, mkdirat, openat, stat, symlink, Mode, OFlags, CWD},
@@ -23,7 +23,7 @@ use composefs::{
2323
mountcompat::{overlayfs_set_fd, overlayfs_set_lower_and_data_fds, prepare_mount},
2424
repository::Repository,
2525
};
26-
use composefs_boot::cmdline::get_cmdline_value;
26+
use composefs_boot::cmdline::get_cmdline_composefs;
2727

2828
// Config file
2929
#[derive(Clone, Copy, Debug, Deserialize)]
@@ -164,9 +164,10 @@ fn open_root_fs(path: &Path) -> Result<OwnedFd> {
164164
Ok(rootfs)
165165
}
166166

167-
fn mount_composefs_image(sysroot: &OwnedFd, name: &str) -> Result<OwnedFd> {
168-
let repo = Repository::<Sha256HashValue>::open_path(sysroot, "composefs")?;
169-
repo.mount(name)
167+
fn mount_composefs_image(sysroot: &OwnedFd, name: &str, insecure: bool) -> Result<OwnedFd> {
168+
let mut repo = Repository::<Sha256HashValue>::open_path(sysroot, "composefs")?;
169+
repo.set_insecure(insecure);
170+
repo.mount(name).context("Failed to mount composefs image")
170171
}
171172

172173
fn mount_subdir(
@@ -196,15 +197,6 @@ fn mount_subdir(
196197
}
197198
}
198199

199-
// Implementation
200-
fn parse_composefs_cmdline<H: FsVerityHashValue>(cmdline: &str) -> Result<H> {
201-
let Some(digest) = get_cmdline_value(cmdline, "composefs=") else {
202-
bail!("Unable to find composefs= cmdline parameter");
203-
};
204-
205-
H::from_hex(digest).context("Parsing composefs=")
206-
}
207-
208200
fn gpt_workaround() -> Result<()> {
209201
// https://github.com/systemd/systemd/issues/35017
210202
let rootdev = stat("/dev/gpt-auto-root")?;
@@ -231,11 +223,11 @@ fn setup_root(args: Args) -> Result<()> {
231223
Some(cmdline) => cmdline,
232224
None => &std::fs::read_to_string("/proc/cmdline")?,
233225
};
234-
let image = parse_composefs_cmdline::<Sha256HashValue>(cmdline)?.to_hex();
226+
let (image, insecure) = get_cmdline_composefs::<Sha256HashValue>(cmdline)?;
235227

236228
let new_root = match args.root_fs {
237229
Some(path) => open_root_fs(&path).context("Failed to clone specified root fs")?,
238-
None => mount_composefs_image(&sysroot, &image)?,
230+
None => mount_composefs_image(&sysroot, &image.to_hex(), insecure)?,
239231
};
240232

241233
// we need to clone this before the next step to make sure we get the old one
@@ -258,7 +250,7 @@ fn setup_root(args: Args) -> Result<()> {
258250
}
259251

260252
// etc + var
261-
let state = open_dir(open_dir(&sysroot, "state")?, &image)?;
253+
let state = open_dir(open_dir(&sysroot, "state")?, image.to_hex())?;
262254
mount_subdir(&new_root, &state, "etc", config.etc, MountType::Overlay)?;
263255
mount_subdir(&new_root, &state, "var", config.var, MountType::Bind)?;
264256

@@ -285,12 +277,11 @@ mod test {
285277
fn test_parse() {
286278
let failing = ["", "foo", "composefs", "composefs=foo"];
287279
for case in failing {
288-
assert!(parse_composefs_cmdline::<Sha256HashValue>(case).is_err());
280+
assert!(get_cmdline_composefs::<Sha256HashValue>(case).is_err());
289281
}
290282
let digest = "8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52";
291-
similar_asserts::assert_eq!(
292-
parse_composefs_cmdline::<Sha256HashValue>(&format!("composefs={digest}")).unwrap(),
293-
Sha256HashValue::from_hex(digest).unwrap()
294-
);
283+
let cmdline = &format!("composefs={digest}");
284+
let (digest_cmdline, _) = get_cmdline_composefs::<Sha256HashValue>(cmdline).unwrap();
285+
similar_asserts::assert_eq!(digest_cmdline, Sha256HashValue::from_hex(digest).unwrap());
295286
}
296287
}

0 commit comments

Comments
 (0)