prepare-root: Add `ostree.prepare-root.composefs`
authorColin Walters <walters@verbum.org>
Wed, 10 Jul 2024 20:38:48 +0000 (16:38 -0400)
committerColin Walters <walters@verbum.org>
Thu, 11 Jul 2024 21:04:09 +0000 (17:04 -0400)
We have a use case for overriding the composefs state via
the kernel commandline; see e.g.
https://gitlab.com/fedora/bootc/tracker/-/issues/27

Signed-off-by: Colin Walters <walters@verbum.org>
man/ostree-prepare-root.xml
src/libostree/ostree-sysroot-deploy.c
src/libotcore/otcore-prepare-root.c
src/libotcore/otcore.h
src/switchroot/ostree-prepare-root.c
tests/inst/src/composefs.rs

index 9117c340bd44576d9744dd8039bbd9fc5ee209d1..8a682e73154a57c08548412c4ab708b75014031c 100644 (file)
@@ -153,6 +153,18 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
                 commit must match the target composefs image.</para></listitem>
             </varlistentry>
         </variablelist>
+
+        <para>
+            The following kernel commandline parameters are also parsed:
+        </para>
+        <variablelist>
+            <varlistentry>
+                <term><varname>ostree.prepare-root.composefs</varname></term>
+                <listitem><para>This accepts the same values as <literal>composefs.enabled</literal> above, and overrides the config file (if present).
+                    For example, specifying <literal>ostree.prepare-root.composefs=0</literal> will disable composefs, even if it is enabled by default in the initrd config.</para></listitem>
+            </varlistentry>
+        </variablelist>
+
     </refsect1>
 
 
index f7ca2dd4a3403d1d388e514d03b0fddd9068bccc..4efaae6e86bd8e9c36b5d075206ab507860a6805 100644 (file)
@@ -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");
 
index f76db04a336378beffb4cdbe04c24330e67667c7..e0a1641a8fe68218e686dca84ee6c468795f4858 100644 (file)
@@ -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);
 }
index fc6b81ca1a0d58084e5c460bc29edce9b2a29803..6e1d5103299044efe05aad67a22f89083cc64cc4 100644 (file)
@@ -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)
index c2bee87d5cc4b58212931c3b4de346277b172107..7d1b8ac8224a276e4a5ae241b6f3bc6585daa975 100644 (file)
@@ -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);
 
index fa6d3d374a7b3d8dfd5888e6424926b3d7d16959..eddccd1d6e3d73c3992e5d540d92f19d7115c5c9 100644 (file)
@@ -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::<bool>("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}"),
     }
 }