diff --git a/man/ostree-prepare-root.xml b/man/ostree-prepare-root.xml index 9117c340..8a682e73 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 f7ca2dd4..4efaae6e 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 f76db04a..e0a1641a 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 fc6b81ca..6e1d5103 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 c2bee87d..7d1b8ac8 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -290,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); diff --git a/tests/inst/src/composefs.rs b/tests/inst/src/composefs.rs index fa6d3d37..eddccd1d 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}"), } }