diff --git a/man/ostree-prepare-root.xml b/man/ostree-prepare-root.xml
index 9117c340bd..8a682e7315 100644
--- a/man/ostree-prepare-root.xml
+++ b/man/ostree-prepare-root.xml
@@ -153,6 +153,18 @@ License along with this library. If not, see .
commit must match the target composefs image.
+
+
+ The following kernel commandline parameters are also parsed:
+
+
+
+ ostree.prepare-root.composefs
+ This accepts the same values as composefs.enabled above, and overrides the config file (if present).
+ For example, specifying ostree.prepare-root.composefs=0 will disable composefs, even if it is enabled by default in the initrd config.
+
+
+
diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c
index f7ca2dd4a3..4efaae6e86 100644
--- a/src/libostree/ostree-sysroot-deploy.c
+++ b/src/libostree/ostree-sysroot-deploy.c
@@ -655,7 +655,7 @@ checkout_deployment_tree (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploy
// However, we don't load the keys here, because they may not exist, such
// as in the initial deploy
g_autoptr (ComposefsConfig) composefs_config
- = otcore_load_composefs_config (prepare_root_config, FALSE, error);
+ = otcore_load_composefs_config ("", prepare_root_config, FALSE, error);
if (!composefs_config)
return glnx_prefix_error (error, "Reading composefs config");
diff --git a/src/libotcore/otcore-prepare-root.c b/src/libotcore/otcore-prepare-root.c
index f76db04a33..e0a1641a8f 100644
--- a/src/libotcore/otcore-prepare-root.c
+++ b/src/libotcore/otcore-prepare-root.c
@@ -24,6 +24,8 @@
// in use, the ostree commit metadata will contain the composefs image digest,
// which can be used to fully verify the target filesystem tree.
#define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key"
+// The kernel argument to configure composefs
+#define CMDLINE_KEY_COMPOSEFS "ostree.prepare-root.composefs"
static bool
proc_cmdline_has_key_starting_with (const char *cmdline, const char *key)
@@ -161,8 +163,12 @@ otcore_free_composefs_config (ComposefsConfig *config)
// Parse the [composefs] section of the prepare-root.conf.
ComposefsConfig *
-otcore_load_composefs_config (GKeyFile *config, gboolean load_keys, GError **error)
+otcore_load_composefs_config (const char *cmdline, GKeyFile *config, gboolean load_keys,
+ GError **error)
{
+ g_assert (cmdline);
+ g_assert (config);
+
GLNX_AUTO_PREFIX_ERROR ("Loading composefs config", error);
g_autoptr (ComposefsConfig) ret = g_new0 (ComposefsConfig, 1);
@@ -214,5 +220,22 @@ otcore_load_composefs_config (GKeyFile *config, gboolean load_keys, GError **err
return glnx_null_throw (error, "public key file specified, but no public keys found");
}
+ g_autofree char *ostree_composefs = otcore_find_proc_cmdline_key (cmdline, CMDLINE_KEY_COMPOSEFS);
+ if (ostree_composefs)
+ {
+ if (g_strcmp0 (ostree_composefs, "signed") == 0)
+ {
+ ret->enabled = OT_TRISTATE_YES;
+ ret->is_signed = true;
+ }
+ else
+ {
+ // The other states force off signatures
+ ret->is_signed = false;
+ if (!_ostree_parse_tristate (ostree_composefs, &ret->enabled, error))
+ return glnx_prefix_error (error, "handling karg " CMDLINE_KEY_COMPOSEFS), NULL;
+ }
+ }
+
return g_steal_pointer (&ret);
}
diff --git a/src/libotcore/otcore.h b/src/libotcore/otcore.h
index fc6b81ca1a..6e1d510329 100644
--- a/src/libotcore/otcore.h
+++ b/src/libotcore/otcore.h
@@ -59,8 +59,8 @@ typedef struct
void otcore_free_composefs_config (ComposefsConfig *config);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComposefsConfig, otcore_free_composefs_config)
-ComposefsConfig *otcore_load_composefs_config (GKeyFile *config, gboolean load_keys,
- GError **error);
+ComposefsConfig *otcore_load_composefs_config (const char *cmdline, GKeyFile *config,
+ gboolean load_keys, GError **error);
// Our directory with transient state (eventually /run/ostree-booted should be a link to
// /run/ostree/booted)
diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c
index 2cb9f67ca9..7d1b8ac822 100644
--- a/src/switchroot/ostree-prepare-root.c
+++ b/src/switchroot/ostree-prepare-root.c
@@ -113,14 +113,11 @@ sysroot_is_configured_ro (const char *sysroot)
}
static char *
-resolve_deploy_path (const char *root_mountpoint)
+resolve_deploy_path (const char *kernel_cmdline, const char *root_mountpoint)
{
char destpath[PATH_MAX];
struct stat stbuf;
char *deploy_path;
- g_autofree char *kernel_cmdline = read_proc_cmdline ();
- if (!kernel_cmdline)
- errx (EXIT_FAILURE, "Failed to read kernel cmdline");
g_autoptr (GError) error = NULL;
g_autofree char *ostree_target = NULL;
@@ -268,6 +265,10 @@ main (int argc, char *argv[])
err (EXIT_FAILURE, "usage: ostree-prepare-root SYSROOT");
const char *root_arg = argv[1];
+ g_autofree char *kernel_cmdline = read_proc_cmdline ();
+ if (!kernel_cmdline)
+ errx (EXIT_FAILURE, "Failed to read kernel cmdline");
+
// Since several APIs want to operate in terms of file descriptors, let's
// open the initramfs now. Currently this is just used for the config parser.
glnx_autofd int initramfs_rootfs_fd = -1;
@@ -289,7 +290,7 @@ main (int argc, char *argv[])
// We always parse the composefs config, because we want to detect and error
// out if it's enabled, but not supported at compile time.
g_autoptr (ComposefsConfig) composefs_config
- = otcore_load_composefs_config (config, TRUE, &error);
+ = otcore_load_composefs_config (kernel_cmdline, config, TRUE, &error);
if (!composefs_config)
errx (EXIT_FAILURE, "%s", error->message);
@@ -308,7 +309,7 @@ main (int argc, char *argv[])
const char *root_mountpoint = realpath (root_arg, NULL);
if (root_mountpoint == NULL)
err (EXIT_FAILURE, "realpath(\"%s\")", root_arg);
- g_autofree char *deploy_path = resolve_deploy_path (root_mountpoint);
+ g_autofree char *deploy_path = resolve_deploy_path (kernel_cmdline, root_mountpoint);
const char *deploy_directory_name = glnx_basename (deploy_path);
// Note that realpath() should have stripped any trailing `/` which shouldn't
// be in the karg to start with, but we assert here to be sure we have a non-empty
diff --git a/tests/inst/src/composefs.rs b/tests/inst/src/composefs.rs
index fa6d3d374a..eddccd1d6e 100644
--- a/tests/inst/src/composefs.rs
+++ b/tests/inst/src/composefs.rs
@@ -131,6 +131,19 @@ fn verify_composefs_signed(sh: &xshell::Shell, metadata: &glib::VariantDict) ->
Ok(())
}
+fn verify_disable_composefs(sh: &xshell::Shell, metadata: &glib::VariantDict) -> Result<()> {
+ assert_eq!(
+ metadata
+ .lookup::("composefs")
+ .unwrap()
+ .unwrap_or_default(),
+ false
+ );
+ let fstype = cmd!(sh, "findmnt -n -o FSTYPE /").read()?;
+ assert_ne!(fstype.as_str(), "overlay");
+ Ok(())
+}
+
pub(crate) fn itest_composefs() -> Result<()> {
let sh = &xshell::Shell::new()?;
let mark = match crate::test::get_reboot_mark()? {
@@ -165,7 +178,16 @@ pub(crate) fn itest_composefs() -> Result<()> {
Err(reboot("2"))?;
Ok(())
}
- "2" => verify_composefs_signed(sh, &metadata),
+ "2" => {
+ verify_composefs_signed(sh, &metadata)?;
+ cmd!(
+ sh,
+ "rpm-ostree kargs --append=ostree.prepare-root.composefs=0"
+ )
+ .run()?;
+ Err(reboot("3"))
+ }
+ "3" => verify_disable_composefs(sh, &metadata),
o => anyhow::bail!("Unrecognized reboot mark {o}"),
}
}