From da70509c34d963d2c50206b8b5f27646b501f2f8 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 12 Mar 2024 13:06:30 +0100 Subject: [PATCH] install: manually label {/etc/fstab,tmpfile.d/bootc-root-ssh.conf} Right now bootc supports an experimental install from a non-selinux host when using the `BOOTC_SKIP_SELINUX_HOST_CHECK=1` option. This is nice and works relatively well. However files written during the install like /etc/fstab or the tmpfiles.dfile in /etc/tmpfile.d/bootc-root-ssh.conf must be labeled too. This commit adds a (rather crude) manual way to do this. Closes https://github.com/containers/bootc/issues/362 Signed-off-by: Michael Vogt --- lib/src/install.rs | 11 ++++++++- lib/src/install/osconfig.rs | 45 +++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/src/install.rs b/lib/src/install.rs index 8906ad6c..59d7d19a 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -633,6 +633,7 @@ async fn initialize_ostree_root_from_self( let root = rootfs_dir .open_dir(path.as_str()) .context("Opening deployment dir")?; + let root_path = &rootfs.join(&path.as_str()); let mut f = { let mut opts = cap_std::fs::OpenOptions::new(); root.open_with("etc/fstab", opts.append(true).write(true).create(true)) @@ -644,8 +645,16 @@ async fn initialize_ostree_root_from_self( } f.flush()?; + let fstab_path = root_path.join("etc/fstab"); + state.lsm_label(&fstab_path, "/etc/fstab".into(), false)?; + if let Some(contents) = state.root_ssh_authorized_keys.as_deref() { - osconfig::inject_root_ssh_authorized_keys(&root, contents)?; + osconfig::inject_root_ssh_authorized_keys( + &root, + &root_path, + |target, path, recurse| state.lsm_label(target, path, recurse), + contents, + )?; } let uname = rustix::system::uname(); diff --git a/lib/src/install/osconfig.rs b/lib/src/install/osconfig.rs index 6bddc640..019933c7 100644 --- a/lib/src/install/osconfig.rs +++ b/lib/src/install/osconfig.rs @@ -8,7 +8,15 @@ const ETC_TMPFILES: &str = "etc/tmpfiles.d"; const ROOT_SSH_TMPFILE: &str = "bootc-root-ssh.conf"; #[context("Injecting root authorized_keys")] -pub(crate) fn inject_root_ssh_authorized_keys(root: &Dir, contents: &str) -> Result<()> { +pub(crate) fn inject_root_ssh_authorized_keys( + root: &Dir, + root_path: &Utf8Path, + lsm_label_fn: F, + contents: &str, +) -> Result<()> +where + F: Fn(&Utf8Path, &Utf8Path, bool) -> Result<()>, +{ // While not documented right now, this one looks like it does not newline wrap let b64_encoded = ostree_ext::glib::base64_encode(contents.as_bytes()); // See the example in https://systemd.io/CREDENTIALS/ @@ -18,20 +26,53 @@ pub(crate) fn inject_root_ssh_authorized_keys(root: &Dir, contents: &str) -> Res root.create_dir_all(tmpfiles_dir)?; let target = tmpfiles_dir.join(ROOT_SSH_TMPFILE); root.atomic_write(&target, &tmpfiles_content)?; + + let as_path = Utf8Path::new(ETC_TMPFILES).join(ROOT_SSH_TMPFILE); + lsm_label_fn( + &root_path.join(&as_path), + &Utf8Path::new("/").join(&as_path), + false, + )?; + println!("Injected: {target}"); Ok(()) } #[test] fn test_inject_root_ssh() -> Result<()> { + use camino::Utf8PathBuf; + use std::cell::Cell; + + let fake_lsm_label_called = Cell::new(0); + let fake_lsm_label = |target: &Utf8Path, as_path: &Utf8Path, recurse: bool| -> Result<()> { + assert_eq!( + target, + format!("/root/path/etc/tmpfiles.d/{ROOT_SSH_TMPFILE}") + ); + assert_eq!(as_path, format!("/etc/tmpfiles.d/{ROOT_SSH_TMPFILE}")); + assert_eq!(recurse, false); + + fake_lsm_label_called.set(fake_lsm_label_called.get() + 1); + Ok(()) + }; + + let root_path = &Utf8PathBuf::from("/root/path"); let root = &cap_std_ext::cap_tempfile::TempDir::new(cap_std::ambient_authority())?; - inject_root_ssh_authorized_keys(root, "ssh-ed25519 ABCDE example@demo\n").unwrap(); + inject_root_ssh_authorized_keys( + root, + root_path, + fake_lsm_label, + "ssh-ed25519 ABCDE example@demo\n", + ) + .unwrap(); let content = root.read_to_string(format!("etc/tmpfiles.d/{ROOT_SSH_TMPFILE}"))?; assert_eq!( content, "f~ /root/.ssh/authorized_keys 600 root root - c3NoLWVkMjU1MTkgQUJDREUgZXhhbXBsZUBkZW1vCg==\n" ); + assert_eq!(fake_lsm_label_called, 1.into()); + Ok(()) }