From aa72caffb540114a0e8635ab2990b9c8b0b8f9db Mon Sep 17 00:00:00 2001 From: Eric Curtin Date: Thu, 8 Jun 2023 12:40:28 +0100 Subject: [PATCH] Add ostree=aboot for signed Android Boot Images 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 | 47 ++++++++++++++++++++++++ src/switchroot/ostree-prepare-root.c | 7 +--- src/switchroot/ostree-system-generator.c | 6 +-- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/switchroot/ostree-mount-util.h b/src/switchroot/ostree-mount-util.h index 9f90dc01c7..4a0367e5be 100644 --- a/src/switchroot/ostree-mount-util.h +++ b/src/switchroot/ostree-mount-util.h @@ -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 @@ read_proc_cmdline (void) 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. */ diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 83f5897fe4..d7b44d9be2 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -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"); diff --git a/src/switchroot/ostree-system-generator.c b/src/switchroot/ostree-system-generator.c index c045c541a2..6dabba6dc3 100644 --- a/src/switchroot/ostree-system-generator.c +++ b/src/switchroot/ostree-system-generator.c @@ -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); }