Skip to content

Commit

Permalink
Merge pull request #3192 from ericcurtin/ostree-impl-system-generator…
Browse files Browse the repository at this point in the history
…-aboot

generator: Fixes for Android Boot environment
  • Loading branch information
ericcurtin authored Feb 22, 2024
2 parents b460d28 + 4a71845 commit e790e79
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 30 deletions.
17 changes: 10 additions & 7 deletions src/libostree/ostree-impl-system-generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ require_internal_units (const char *normal_dir, const char *early_dir, const cha

/* Generate var.mount */
static gboolean
fstab_generator (const char *ostree_cmdline, const char *normal_dir, const char *early_dir,
const char *late_dir, GError **error)
fstab_generator (const char *ostree_target, const bool is_aboot, const char *normal_dir,
const char *early_dir, const char *late_dir, GError **error)
{
#ifdef HAVE_LIBMOUNT
/* Not currently cancellable, but define a var in case we care later */
Expand All @@ -144,7 +144,8 @@ fstab_generator (const char *ostree_cmdline, const char *normal_dir, const char
* mounted yet.
*/
g_autofree char *stateroot = NULL;
if (!_ostree_sysroot_parse_bootlink (ostree_cmdline, NULL, &stateroot, NULL, NULL, error))
if (!_ostree_sysroot_parse_bootlink (ostree_target, is_aboot, NULL, &stateroot, NULL, NULL,
error))
return glnx_prefix_error (error, "Parsing stateroot");

/* Load /etc/fstab if it exists, and look for a /var mount */
Expand Down Expand Up @@ -261,17 +262,19 @@ _ostree_impl_system_generator (const char *normal_dir, const char *early_dir, co
if (!cmdline)
return glnx_throw (error, "Failed to read /proc/cmdline");

g_autofree char *ostree_cmdline = otcore_find_proc_cmdline_key (cmdline, "ostree");

g_autoptr (GError) otcore_get_ostree_target_error = NULL;
g_autofree char *ostree_target = NULL;
bool is_aboot = false;
/* This could happen in CoreOS live environments, where we hackily mock
* the `ostree=` karg for `ostree-prepare-root.service` specifically, but
* otherwise that karg doesn't exist on the real command-line. */
if (!ostree_cmdline)
if (!otcore_get_ostree_target (cmdline, &is_aboot, &ostree_target,
&otcore_get_ostree_target_error))
return TRUE;

if (!require_internal_units (normal_dir, early_dir, late_dir, error))
return FALSE;
if (!fstab_generator (ostree_cmdline, normal_dir, early_dir, late_dir, error))
if (!fstab_generator (ostree_target, is_aboot, normal_dir, early_dir, late_dir, error))
return FALSE;

return TRUE;
Expand Down
9 changes: 6 additions & 3 deletions src/libostree/ostree-sysroot-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#pragma once

#include <stdbool.h>

#include "libglnx.h"
#include "ostree-bootloader.h"
#include "ostree.h"
Expand Down Expand Up @@ -177,8 +179,9 @@ gboolean _ostree_sysroot_parse_bootdir_name (const char *name, char **out_osname
gboolean _ostree_sysroot_list_all_boot_directories (OstreeSysroot *self, char ***out_bootdirs,
GCancellable *cancellable, GError **error);

gboolean _ostree_sysroot_parse_bootlink (const char *bootlink, int *out_entry_bootversion,
char **out_osname, char **out_bootcsum,
int *out_treebootserial, GError **error);
gboolean _ostree_sysroot_parse_bootlink (const char *bootlink, const bool is_aboot,
int *out_entry_bootversion, char **out_osname,
char **out_bootcsum, int *out_treebootserial,
GError **error);

G_END_DECLS
37 changes: 30 additions & 7 deletions src/libostree/ostree-sysroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,24 +724,44 @@ load_origin (OstreeSysroot *self, OstreeDeployment *deployment, GCancellable *ca

// Parse the kernel argument ostree=
gboolean
_ostree_sysroot_parse_bootlink (const char *bootlink, int *out_entry_bootversion, char **out_osname,
char **out_bootcsum, int *out_treebootserial, GError **error)
_ostree_sysroot_parse_bootlink (const char *bootlink, const bool is_aboot,
int *out_entry_bootversion, char **out_osname, char **out_bootcsum,
int *out_treebootserial, GError **error)
{
static gsize regex_initialized;
static GRegex *regex;
const char *to_parse = bootlink;
g_autofree char *symlink_val = NULL;
if (is_aboot)
{
symlink_val = glnx_readlinkat_malloc (-1, bootlink, NULL, error);
if (!symlink_val)
return glnx_throw (error, "Failed to read '%s' symlink", bootlink);

to_parse = symlink_val;
}

if (g_once_init_enter (&regex_initialized))
{
regex = g_regex_new ("^/ostree/boot.([01])/([^/]+)/([^/]+)/([0-9]+)$", 0, 0, NULL);
regex = g_regex_new (is_aboot ? "^deploy/([^/]+)/"
: "^/ostree/boot.([01])/([^/]+)/([^/]+)/([0-9]+)$",
0, 0, NULL);
g_assert (regex);
g_once_init_leave (&regex_initialized, 1);
}

g_autoptr (GMatchInfo) match = NULL;
if (!g_regex_match (regex, bootlink, 0, &match))
if (!g_regex_match (regex, to_parse, 0, &match))
return glnx_throw (error,
"Invalid ostree= argument '%s', expected "
"ostree=/ostree/boot.BOOTVERSION/OSNAME/BOOTCSUM/TREESERIAL",
bootlink);
"ostree=/ostree/boot.BOOTVERSION/OSNAME/BOOTCSUM/TREESERIAL or aboot method",
to_parse);

if (is_aboot)
{
*out_osname = g_match_info_fetch (match, 1);
return TRUE;
}

g_autofree char *bootversion_str = g_match_info_fetch (match, 1);
g_autofree char *treebootserial_str = g_match_info_fetch (match, 4);
Expand Down Expand Up @@ -775,7 +795,10 @@ parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment *
g_autofree char *osname = NULL;
g_autofree char *bootcsum = NULL;
int treebootserial = -1;
if (!_ostree_sysroot_parse_bootlink (boot_link, &entry_boot_version, &osname, &bootcsum,

// Note is_boot should always be false here, this boot_link is taken from BLS file, not
// /proc/cmdline, BLS files are present in aboot images
if (!_ostree_sysroot_parse_bootlink (boot_link, false, &entry_boot_version, &osname, &bootcsum,
&treebootserial, error))
return FALSE;

Expand Down
4 changes: 3 additions & 1 deletion src/libotcore/otcore-prepare-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ otcore_find_proc_cmdline_key (const char *cmdline, const char *key)
//
// If invalid data is found, @error will be set.
gboolean
otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error)
otcore_get_ostree_target (const char *cmdline, bool *is_aboot, char **out_target, GError **error)
{
g_assert (cmdline);
g_assert (out_target && *out_target == NULL);
Expand All @@ -84,8 +84,10 @@ otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error

// First, handle the Android boot case
g_autofree char *slot_suffix = otcore_find_proc_cmdline_key (cmdline, "androidboot.slot_suffix");
*is_aboot = false;
if (slot_suffix)
{
*is_aboot = true;
if (strcmp (slot_suffix, "_a") == 0)
{
*out_target = g_strdup (slot_a);
Expand Down
3 changes: 2 additions & 1 deletion src/libotcore/otcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ gboolean otcore_validate_ed25519_signature (GBytes *data, GBytes *pubkey, GBytes
bool *out_valid, GError **error);

char *otcore_find_proc_cmdline_key (const char *cmdline, const char *key);
gboolean otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error);
gboolean otcore_get_ostree_target (const char *cmdline, bool *is_aboot, char **out_target,
GError **error);

GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error);

Expand Down
3 changes: 2 additions & 1 deletion src/switchroot/ostree-prepare-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ resolve_deploy_path (const char *root_mountpoint)

g_autoptr (GError) error = NULL;
g_autofree char *ostree_target = NULL;
if (!otcore_get_ostree_target (kernel_cmdline, &ostree_target, &error))
bool is_aboot = false;
if (!otcore_get_ostree_target (kernel_cmdline, &is_aboot, &ostree_target, &error))
errx (EXIT_FAILURE, "Failed to determine ostree target: %s", error->message);
if (!ostree_target)
errx (EXIT_FAILURE, "No ostree target found");
Expand Down
22 changes: 12 additions & 10 deletions tests/test-otcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,46 +36,48 @@ test_prepare_root_cmdline (void)
{
g_autoptr (GError) error = NULL;
g_autofree char *target = NULL;
bool is_aboot = false;

static const char *notfound_cases[]
= { "", "foo", "foo=bar baz sometest", "xostree foo", "xostree=blah bar", NULL };
for (const char **iter = notfound_cases; iter && *iter; iter++)
{
const char *tcase = *iter;
g_assert (otcore_get_ostree_target (tcase, &target, &error));
g_assert (otcore_get_ostree_target (tcase, &is_aboot, &target, &error));
g_assert_no_error (error);
g_assert (target == NULL);
}

// Test the default ostree=
g_assert (otcore_get_ostree_target ("blah baz=blah ostree=/foo/bar somearg", &target, &error));
g_assert (otcore_get_ostree_target ("blah baz=blah ostree=/foo/bar somearg", &is_aboot, &target,
&error));
g_assert_no_error (error);
g_assert_cmpstr (target, ==, "/foo/bar");
free (g_steal_pointer (&target));

// Test android boot
g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_b somearg", &target,
&error));
g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_b somearg", &is_aboot,
&target, &error));
g_assert_no_error (error);
g_assert_cmpstr (target, ==, "/ostree/root.b");
free (g_steal_pointer (&target));

g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_a somearg", &target,
&error));
g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_a somearg", &is_aboot,
&target, &error));
g_assert_no_error (error);
g_assert_cmpstr (target, ==, "/ostree/root.a");
free (g_steal_pointer (&target));

// And an expected failure to parse a "c" suffix
g_assert (!otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_c somearg", &target,
&error));
g_assert (!otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_c somearg",
&is_aboot, &target, &error));
g_assert (error);
g_assert (target == NULL);
g_clear_error (&error);

// And non-A/B androidboot
g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.somethingelse somearg", &target,
&error));
g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.somethingelse somearg", &is_aboot,
&target, &error));
g_assert_no_error (error);
g_assert_cmpstr (target, ==, "/ostree/root.a");
free (g_steal_pointer (&target));
Expand Down

0 comments on commit e790e79

Please sign in to comment.