Add ostree=aboot for signed Android Boot Images
authorEric Curtin <ecurtin@redhat.com>
Thu, 8 Jun 2023 11:40:28 +0000 (12:40 +0100)
committerEric Curtin <ecurtin@redhat.com>
Thu, 8 Jun 2023 14:27:07 +0000 (15:27 +0100)
Some kernel images are delivered in a signed kernel + cmdline +
initramfs + dtb blob. When this is added to the commit server side, only
after this do you know what the cmdline is, this creates a recursion
issue. To avoid this, in the case where we have ostree=aboot karg
set, create a symlink after deploy to the correct ostree target in the
rootfs, as the cmdline can't be malleable and secured client-side at
the same time.

src/switchroot/ostree-mount-util.h
src/switchroot/ostree-prepare-root.c
src/switchroot/ostree-system-generator.c

index 9f90dc01c7b72012969da1bfd5ed37124c8f82f4..4a0367e5befe17903c207ef0877b8b842a590f49 100644 (file)
@@ -40,6 +40,9 @@
 #define _OSTREE_SYSROOT_READONLY_STAMP "/run/ostree-sysroot-ro.stamp"
 #define _OSTREE_COMPOSEFS_ROOT_STAMP "/run/ostree-composefs-root.stamp"
 
+#define autofree __attribute__ ((cleanup (cleanup_free)))
+#define steal_pointer(pp) steal_pointer_impl ((void **)pp)
+
 static inline int
 path_is_on_readonly_fs (const char *path)
 {
@@ -79,6 +82,22 @@ out:
   return cmdline;
 }
 
+static inline void
+cleanup_free (void *p)
+{
+  void **pp = (void **)p;
+  free (*pp);
+}
+
+static inline void *
+steal_pointer_impl (void **to_steal)
+{
+  void *ret = *to_steal;
+  *to_steal = NULL;
+
+  return ret;
+}
+
 static inline char *
 read_proc_cmdline_key (const char *key)
 {
@@ -114,6 +133,34 @@ read_proc_cmdline_key (const char *key)
   return ret;
 }
 
+static inline char *
+get_aboot_root_slot (void)
+{
+  autofree char *slot_suffix = read_proc_cmdline_key ("androidboot.slot_suffix");
+  if (strcmp (slot_suffix, "_a") == 0)
+    return strdup ("/ostree/root.a");
+  else if (strcmp (slot_suffix, "_b") == 0)
+    return strdup ("/ostree/root.b");
+
+  errx (EXIT_FAILURE, "androidboot.slot_suffix invalid: %s", slot_suffix);
+
+  return NULL;
+}
+
+static inline char *
+get_ostree_target (void)
+{
+  autofree char *ostree_cmdline = read_proc_cmdline_key ("ostree");
+
+  if (!ostree_cmdline)
+    errx (EXIT_FAILURE, "No ostree= cmdline");
+
+  if (strcmp (ostree_cmdline, "aboot") == 0)
+    return get_aboot_root_slot ();
+
+  return steal_pointer (&ostree_cmdline);
+}
+
 /* This is an API for other projects to determine whether or not the
  * currently running system is ostree-controlled.
  */
index 83f5897fe41f865fc652566f358f280212e5057f..d7b44d9be2669e4fbb2a713a68caf20012c062c2 100644 (file)
@@ -154,11 +154,8 @@ resolve_deploy_path (const char *root_mountpoint)
 {
   char destpath[PATH_MAX];
   struct stat stbuf;
-  char *ostree_target, *deploy_path;
-
-  ostree_target = read_proc_cmdline_key ("ostree");
-  if (!ostree_target)
-    errx (EXIT_FAILURE, "No OSTree target; expected ostree=/ostree/boot.N/...");
+  char *deploy_path;
+  autofree char *ostree_target = get_ostree_target ();
 
   if (snprintf (destpath, sizeof (destpath), "%s/%s", root_mountpoint, ostree_target) < 0)
     err (EXIT_FAILURE, "failed to assemble ostree target path");
index c045c541a2b12f78e58d61481ed9cd71629cd226..6dabba6dc3816108a8e054f54ccd791edebdf474 100644 (file)
@@ -63,9 +63,7 @@ main (int argc, char *argv[])
    * exit so that we don't error, but at the same time work where switchroot
    * is PID 1 (and so hasn't created /run/ostree-booted).
    */
-  char *ostree_cmdline = read_proc_cmdline_key ("ostree");
-  if (!ostree_cmdline)
-    exit (EXIT_SUCCESS);
+  autofree char *ostree_target = get_ostree_target ();
 
   /* See comments in ostree-prepare-root.c for this.
    *
@@ -77,7 +75,7 @@ main (int argc, char *argv[])
 
   {
     g_autoptr (GError) local_error = NULL;
-    if (!ostree_cmd__private__ ()->ostree_system_generator (ostree_cmdline, arg_dest, NULL,
+    if (!ostree_cmd__private__ ()->ostree_system_generator (ostree_target, arg_dest, NULL,
                                                             arg_dest_late, &local_error))
       errx (EXIT_FAILURE, "%s", local_error->message);
   }