Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 99 additions & 21 deletions src/libotcore/otcore-prepare-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,51 +278,109 @@ otcore_load_rootfs_config (const char *cmdline, GKeyFile *config, gboolean load_
}

#ifdef HAVE_COMPOSEFS
static GVariant *
static gboolean
load_variant (const char *root_mountpoint, const char *digest, const char *extension,
const GVariantType *type, GError **error)
const GVariantType *type, gboolean allow_noent, GVariant **out, GError **error)
{
g_autofree char *path = g_strdup_printf ("%s/ostree/repo/objects/%.2s/%s.%s", root_mountpoint,
digest, digest + 2, extension);

char *data = NULL;
gsize data_size;
if (!g_file_get_contents (path, &data, &data_size, error))
g_autoptr (GError) local_error = NULL;

if (!g_file_get_contents (path, &data, &data_size, &local_error))
{
if (allow_noent && g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
{
*out = NULL;
return TRUE;
}

g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}

*out = g_variant_ref_sink (g_variant_new_from_data (type, data, data_size, FALSE, g_free, data));
return TRUE;
}

/* For local bootc commit, return the base ostree commit that was used to generate the commit.
*/
static char *
get_base_digest_for_bootc_commit (GVariant *commit)
{
g_autoptr (GVariant) metadata = g_variant_get_child_value (commit, 0);

/* Check for ostree.container.image-config to determine if this is a bootc commit */
const char *image_config = NULL;
if (!g_variant_lookup (metadata, "ostree.container.image-config", "s", &image_config))
return NULL;

/* If so, since https://github.com/bootc-dev/bootc/pull/1600, the
* parent commit will be the base ostree commit. */

g_autoptr (GVariant) parent_commit_v = g_variant_get_child_value (commit, 1);
if (g_variant_n_children (parent_commit_v) != OSTREE_SHA256_DIGEST_LEN)
return NULL;

return g_variant_ref_sink (g_variant_new_from_data (type, data, data_size, FALSE, g_free, data));
const guint8 *parent_commit_bin = ot_variant_get_data (parent_commit_v, NULL);
if (parent_commit_bin == NULL)
return NULL;

char *basecommit_digest = g_malloc (OSTREE_SHA256_STRING_LEN + 1);
ot_bin2hex (basecommit_digest, parent_commit_bin, OSTREE_SHA256_DIGEST_LEN);

return basecommit_digest;
}

// Given a mount point, directly load the .commit object. At the current time this tool
// doesn't link to libostree.
static gboolean
load_commit_for_deploy (const char *root_mountpoint, const char *deploy_path, GVariant **commit_out,
GVariant **commitmeta_out, GError **error)
GVariant **commitmeta_out, GVariant **basecommit_out,
GVariant **basecommitmeta_out, GError **error)
{
g_autoptr (GError) local_error = NULL;
g_autofree char *digest = g_path_get_basename (deploy_path);
char *dot = strchr (digest, '.');
if (dot != NULL)
*dot = 0;

g_autoptr (GVariant) commit_v
= load_variant (root_mountpoint, digest, "commit", OSTREE_COMMIT_GVARIANT_FORMAT, error);
if (commit_v == NULL)
g_autoptr (GVariant) commit_v = NULL;
g_autoptr (GVariant) commitmeta_v = NULL;
g_autoptr (GVariant) basecommit_v = NULL;
g_autoptr (GVariant) basecommitmeta_v = NULL;

if (!load_variant (root_mountpoint, digest, "commit", OSTREE_COMMIT_GVARIANT_FORMAT, FALSE,
&commit_v, error))
return FALSE;

g_autoptr (GVariant) commitmeta_v = load_variant (root_mountpoint, digest, "commitmeta",
G_VARIANT_TYPE ("a{sv}"), &local_error);
if (commitmeta_v == NULL)
if (!load_variant (root_mountpoint, digest, "commitmeta", G_VARIANT_TYPE ("a{sv}"), TRUE,
&commitmeta_v, error))
return FALSE;

/* In case the commit is one created by bootc when importing a container, it will not
* be signed. However, we can still look at the base commit which may be signed.
*/
g_autofree char *basecommit_digest = get_base_digest_for_bootc_commit (commit_v);
if (basecommit_digest)
{
if (g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
glnx_throw (error, "No commitmeta for commit %s", digest);
else
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
if (!load_variant (root_mountpoint, basecommit_digest, "commit",
OSTREE_COMMIT_GVARIANT_FORMAT, TRUE, &basecommit_v, error))
return FALSE;

if (basecommit_v != NULL)
{
if (!load_variant (root_mountpoint, basecommit_digest, "commitmeta",
G_VARIANT_TYPE ("a{sv}"), TRUE, &basecommitmeta_v, error))
return FALSE;
}
}

*commit_out = g_steal_pointer (&commit_v);
*commitmeta_out = g_steal_pointer (&commitmeta_v);
*basecommit_out = g_steal_pointer (&basecommit_v);
*basecommitmeta_out = g_steal_pointer (&basecommitmeta_v);

return TRUE;
}
Expand Down Expand Up @@ -550,12 +608,32 @@ otcore_mount_rootfs (RootConfig *rootfs_config, GVariantBuilder *metadata_builde
if (rootfs_config->is_signed)
{
const char *composefs_pubkey = rootfs_config->signature_pubkey;
g_autoptr (GVariant) commit = NULL;
g_autoptr (GVariant) commitmeta = NULL;

if (!load_commit_for_deploy (root_mountpoint, deploy_path, &commit, &commitmeta, error))
g_autoptr (GVariant) main_commit = NULL;
g_autoptr (GVariant) main_commitmeta = NULL;
g_autoptr (GVariant) base_commit = NULL;
g_autoptr (GVariant) base_commitmeta = NULL;
GVariant *commit = NULL;
GVariant *commitmeta = NULL;

if (!load_commit_for_deploy (root_mountpoint, deploy_path, &main_commit, &main_commitmeta,
&base_commit, &base_commitmeta, error))
return glnx_prefix_error (error, "Error loading signatures from repo");

if (main_commitmeta != NULL)
{
commit = main_commit;
commitmeta = main_commitmeta;
}
else if (base_commitmeta != NULL)
{
ot_journal_print (LOG_INFO,
"composefs+ostree: Validating composefs using bootc base commit");
commit = base_commit;
commitmeta = base_commitmeta;
}
else
return glnx_throw (error, "No commitmeta for deploy %s", deploy_path);

g_autoptr (GVariant) signatures = g_variant_lookup_value (
commitmeta, OSTREE_SIGN_METADATA_ED25519_KEY, G_VARIANT_TYPE ("aay"));
if (signatures == NULL)
Expand Down
Loading