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}"), } }