prepare-root: Add metadata for composefs to `/run/ostree-booted`
authorColin Walters <walters@verbum.org>
Wed, 12 Jul 2023 20:48:56 +0000 (16:48 -0400)
committerColin Walters <walters@verbum.org>
Thu, 13 Jul 2023 11:28:39 +0000 (07:28 -0400)
Particularly for the signature case, having this metadata
acts as a reliable "proof of execution" of the signature verification
code (as opposed to parsing a log file or so).

Besides that, this is also just a stronger check for "we're using
composefs" instead of checking for "overlayfs on /".

src/libotcore/otcore.h
src/switchroot/ostree-prepare-root.c
tests/inst/src/composefs.rs

index a335fa3db02870bcc4dc3dbe10a4f35eeef03014..7bb6364be992547f20ae33a77043a80159efa7b8 100644 (file)
@@ -45,3 +45,12 @@ gboolean otcore_validate_ed25519_signature (GBytes *data, GBytes *pubkey, GBytes
 
 // The name of the composefs metadata root
 #define OSTREE_COMPOSEFS_NAME ".ostree.cfs"
+
+// The file written in the initramfs which contains an a{sv} of metadata
+// from ostree-prepare-root.
+#define OTCORE_RUN_BOOTED "/run/ostree-booted"
+// This key will be present if composefs was successfully used.
+#define OTCORE_RUN_BOOTED_KEY_COMPOSEFS "composefs"
+// This key if present contains the public key successfully used
+// to verify the signature.
+#define OTCORE_RUN_BOOTED_KEY_COMPOSEFS_SIGNATURE "composefs.signed"
index a0dd1be90dd3ba3f53103bc03c469ff9aecff193..696ace271f45c820728c1307ddde930bf316f117 100644 (file)
@@ -322,6 +322,8 @@ main (int argc, char *argv[])
   if (chdir (deploy_path) < 0)
     err (EXIT_FAILURE, "failed to chdir to deploy_path");
 
+  GVariantBuilder metadata_builder;
+  g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}"));
   bool using_composefs = false;
 
   /* We construct the new sysroot in /sysroot.tmp, which is either the composfs
@@ -362,6 +364,9 @@ main (int argc, char *argv[])
             errx (EXIT_FAILURE, "No valid signatures found for public key");
 
           g_print ("Validated commit signature using '%s'\n", composefs_pubkey);
+          g_variant_builder_add (&metadata_builder, "{sv}",
+                                 OTCORE_RUN_BOOTED_KEY_COMPOSEFS_SIGNATURE,
+                                 g_variant_new_string (composefs_pubkey));
 
           g_autoptr (GVariant) metadata = g_variant_get_child_value (commit, 0);
           g_autoptr (GVariant) cfs_digest_v = g_variant_lookup_value (
@@ -401,6 +406,8 @@ main (int argc, char *argv[])
           (void)close (fd);
 
           using_composefs = 1;
+          g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_COMPOSEFS,
+                                 g_variant_new_boolean (true));
         }
       else
         {
@@ -543,7 +550,13 @@ main (int argc, char *argv[])
     }
 
   /* This can be used by other things to signal ostree is in use */
-  touch_run_ostree ();
+  {
+    g_autoptr (GVariant) metadata = g_variant_ref_sink (g_variant_builder_end (&metadata_builder));
+    const guint8 *buf = g_variant_get_data (metadata) ?: (guint8 *)"";
+    if (!glnx_file_replace_contents_at (AT_FDCWD, OTCORE_RUN_BOOTED, buf,
+                                        g_variant_get_size (metadata), 0, NULL, &error))
+      errx (EXIT_FAILURE, "Writing %s: %s", OTCORE_RUN_BOOTED, error->message);
+  }
 
   if (chdir (TMP_SYSROOT) < 0)
     err (EXIT_FAILURE, "failed to chdir to " TMP_SYSROOT);
index a75af870b483402c8f8745507a733a45173f720b..3a737a3ca0e6583a8d276659319fd3e325f8137c 100644 (file)
@@ -1,4 +1,5 @@
 use anyhow::Result;
+use ostree_ext::glib;
 use xshell::cmd;
 
 pub(crate) fn itest_composefs() -> Result<()> {
@@ -27,5 +28,11 @@ pub(crate) fn itest_composefs() -> Result<()> {
     let fstype = cmd!(sh, "findmnt -n -o FSTYPE /").read()?;
     assert_eq!(fstype.as_str(), "overlay");
 
+    let metadata = std::fs::read("/run/ostree-booted")?;
+    let metadata = glib::Variant::from_bytes::<glib::VariantDict>(&glib::Bytes::from(&metadata));
+    let metadata = glib::VariantDict::new(Some(&metadata));
+
+    assert_eq!(metadata.lookup::<bool>("composefs").unwrap(), Some(true));
+
     Ok(())
 }