240 lines
10 KiB
Diff
240 lines
10 KiB
Diff
From d9a8f9d8ccc0b7c1135d0ecde006a75d25f66aee Mon Sep 17 00:00:00 2001
|
|
From: Alexander Larsson <alexl@redhat.com>
|
|
Date: Mon, 10 Jan 2022 16:43:08 +0100
|
|
Subject: [PATCH] Transaction: Fail the resolve if xa.metadata invalid or
|
|
missing
|
|
|
|
If we fail to parse xa.metadata from the summary cache or the commit
|
|
xa.metadata we fail the resolve.
|
|
|
|
If xa.metadata is missing in the commit we fail the resolve (it is
|
|
always set in the summary cache, because summary update converts
|
|
missing xa.metadata to "", so we either get that, or cache miss which
|
|
leads to resolving from the commit.
|
|
|
|
This means that op->resolved_metadata is always set during install and
|
|
updates, which means we will show the app permissions. The transaction
|
|
will also always make sure that this data actually matches what gets
|
|
deployed.
|
|
|
|
Before this change an invalid metadata in the summary cache could lead
|
|
to a NULL resolved_metadata, which means we wouldn't print the app
|
|
permissions, yet we would still deploy some metadata file that could
|
|
have permissions. (NOTE: It would fail to deploy unless the
|
|
xa.metadata in the commit matched the metadata file, but in this
|
|
corner case we would't compare the summary and commit metadata, so
|
|
they may differ.)
|
|
|
|
Conflict:NA
|
|
Reference:https://github.com/flatpak/flatpak/commit/d9a8f9d8ccc0b7c1135d0ecde006a75d25f66aee
|
|
|
|
---
|
|
common/flatpak-transaction.c | 84 +++++++++++++++++++++++-------------
|
|
1 file changed, 55 insertions(+), 29 deletions(-)
|
|
|
|
diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c
|
|
index 721da14..b0908c3 100644
|
|
--- a/common/flatpak-transaction.c
|
|
+++ b/common/flatpak-transaction.c
|
|
@@ -2957,12 +2957,13 @@ emit_eol_and_maybe_skip (FlatpakTransaction *self,
|
|
g_signal_emit (self, signals[END_OF_LIFED_WITH_REBASE], 0, op->remote, flatpak_decomposed_get_ref (op->ref), op->eol, op->eol_rebase, previous_ids, &op->skip);
|
|
}
|
|
|
|
-static void
|
|
+static gboolean
|
|
mark_op_resolved (FlatpakTransactionOperation *op,
|
|
const char *commit,
|
|
GFile *sideload_path,
|
|
GBytes *metadata,
|
|
- GBytes *old_metadata)
|
|
+ GBytes *old_metadata,
|
|
+ GError **error)
|
|
{
|
|
g_debug ("marking op %s:%s resolved to %s", kind_to_str (op->kind), flatpak_decomposed_get_ref (op->ref), commit ? commit : "-");
|
|
|
|
@@ -2980,13 +2981,12 @@ mark_op_resolved (FlatpakTransactionOperation *op,
|
|
if (metadata)
|
|
{
|
|
g_autoptr(GKeyFile) metakey = g_key_file_new ();
|
|
- if (g_key_file_load_from_bytes (metakey, metadata, G_KEY_FILE_NONE, NULL))
|
|
- {
|
|
- op->resolved_metadata = g_bytes_ref (metadata);
|
|
- op->resolved_metakey = g_steal_pointer (&metakey);
|
|
- }
|
|
- else
|
|
- g_message ("Warning: Failed to parse metadata for %s\n", flatpak_decomposed_get_ref (op->ref));
|
|
+ if (!g_key_file_load_from_bytes (metakey, metadata, G_KEY_FILE_NONE, NULL))
|
|
+ return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA,
|
|
+ "Metadata for %s is invalid", flatpak_decomposed_get_ref (op->ref));
|
|
+
|
|
+ op->resolved_metadata = g_bytes_ref (metadata);
|
|
+ op->resolved_metakey = g_steal_pointer (&metakey);
|
|
}
|
|
if (old_metadata)
|
|
{
|
|
@@ -2997,31 +2997,40 @@ mark_op_resolved (FlatpakTransactionOperation *op,
|
|
op->resolved_old_metakey = g_steal_pointer (&metakey);
|
|
}
|
|
else
|
|
- g_message ("Warning: Failed to parse old metadata for %s\n", flatpak_decomposed_get_ref (op->ref));
|
|
+ {
|
|
+ /* This shouldn't happen, but a NULL old metadata is safe (all permisssions are considered new) */
|
|
+ g_message ("Warning: Failed to parse old metadata for %s\n", flatpak_decomposed_get_ref (op->ref));
|
|
+ }
|
|
}
|
|
+
|
|
+ return TRUE;
|
|
}
|
|
|
|
-static void
|
|
+static gboolean
|
|
resolve_op_end (FlatpakTransaction *self,
|
|
FlatpakTransactionOperation *op,
|
|
const char *checksum,
|
|
GFile *sideload_path,
|
|
- GBytes *metadata_bytes)
|
|
+ GBytes *metadata_bytes,
|
|
+ GError **error)
|
|
{
|
|
g_autoptr(GBytes) old_metadata_bytes = NULL;
|
|
|
|
old_metadata_bytes = load_deployed_metadata (self, op->ref, NULL, NULL);
|
|
- mark_op_resolved (op, checksum, sideload_path, metadata_bytes, old_metadata_bytes);
|
|
+ if (!mark_op_resolved (op, checksum, sideload_path, metadata_bytes, old_metadata_bytes, error))
|
|
+ return FALSE;
|
|
emit_eol_and_maybe_skip (self, op);
|
|
+ return TRUE;
|
|
}
|
|
|
|
|
|
-static void
|
|
+static gboolean
|
|
resolve_op_from_commit (FlatpakTransaction *self,
|
|
FlatpakTransactionOperation *op,
|
|
const char *checksum,
|
|
GFile *sideload_path,
|
|
- GVariant *commit_data)
|
|
+ GVariant *commit_data,
|
|
+ GError **error)
|
|
{
|
|
g_autoptr(GBytes) metadata_bytes = NULL;
|
|
g_autoptr(GVariant) commit_metadata = NULL;
|
|
@@ -3032,9 +3041,11 @@ resolve_op_from_commit (FlatpakTransaction *self,
|
|
commit_metadata = g_variant_get_child_value (commit_data, 0);
|
|
g_variant_lookup (commit_metadata, "xa.metadata", "&s", &xa_metadata);
|
|
if (xa_metadata == NULL)
|
|
- g_message ("Warning: No xa.metadata in local commit %s ref %s", checksum, flatpak_decomposed_get_ref (op->ref));
|
|
- else
|
|
- metadata_bytes = g_bytes_new (xa_metadata, strlen (xa_metadata));
|
|
+ return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA,
|
|
+ "No xa.metadata in local commit %s ref %s",
|
|
+ checksum, flatpak_decomposed_get_ref (op->ref));
|
|
+
|
|
+ metadata_bytes = g_bytes_new (xa_metadata, strlen (xa_metadata));
|
|
|
|
if (g_variant_lookup (commit_metadata, "xa.download-size", "t", &download_size))
|
|
op->download_size = GUINT64_FROM_BE (download_size);
|
|
@@ -3044,15 +3055,19 @@ resolve_op_from_commit (FlatpakTransaction *self,
|
|
g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_ENDOFLIFE, "s", &op->eol);
|
|
g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_ENDOFLIFE_REBASE, "s", &op->eol_rebase);
|
|
|
|
- resolve_op_end (self, op, checksum, sideload_path, metadata_bytes);
|
|
+ return resolve_op_end (self, op, checksum, sideload_path, metadata_bytes, error);
|
|
}
|
|
|
|
+/* NOTE: In case of non-available summary this returns FALSE with a
|
|
+ * NULL error, but for other error cases it will be set.
|
|
+ */
|
|
static gboolean
|
|
try_resolve_op_from_metadata (FlatpakTransaction *self,
|
|
FlatpakTransactionOperation *op,
|
|
const char *checksum,
|
|
GFile *sideload_path,
|
|
- FlatpakRemoteState *state)
|
|
+ FlatpakRemoteState *state,
|
|
+ GError **error)
|
|
{
|
|
g_autoptr(GBytes) metadata_bytes = NULL;
|
|
guint64 download_size = 0;
|
|
@@ -3092,8 +3107,7 @@ try_resolve_op_from_metadata (FlatpakTransaction *self,
|
|
op->token_type = GINT32_FROM_LE (var_metadata_lookup_int32 (sparse_cache, FLATPAK_SPARSE_CACHE_KEY_TOKEN_TYPE, op->token_type));
|
|
}
|
|
|
|
- resolve_op_end (self, op, checksum, sideload_path, metadata_bytes);
|
|
- return TRUE;
|
|
+ return resolve_op_end (self, op, checksum, sideload_path, metadata_bytes, error);
|
|
}
|
|
|
|
static gboolean
|
|
@@ -3136,7 +3150,8 @@ resolve_ops (FlatpakTransaction *self,
|
|
* checksum we got was the version already installed.
|
|
*/
|
|
g_assert (op->resolved_commit != NULL);
|
|
- mark_op_resolved (op, op->resolved_commit, NULL, NULL, NULL);
|
|
+ if (!mark_op_resolved (op, op->resolved_commit, NULL, NULL, NULL, error))
|
|
+ return FALSE;
|
|
continue;
|
|
}
|
|
|
|
@@ -3145,14 +3160,16 @@ resolve_ops (FlatpakTransaction *self,
|
|
/* We resolve to the deployed metadata, because we need it to uninstall related ops */
|
|
|
|
metadata_bytes = load_deployed_metadata (self, op->ref, &checksum, NULL);
|
|
- mark_op_resolved (op, checksum, NULL, metadata_bytes, NULL);
|
|
+ if (!mark_op_resolved (op, checksum, NULL, metadata_bytes, NULL, error))
|
|
+ return FALSE;
|
|
continue;
|
|
}
|
|
|
|
if (op->kind == FLATPAK_TRANSACTION_OPERATION_INSTALL_BUNDLE)
|
|
{
|
|
g_assert (op->commit != NULL);
|
|
- mark_op_resolved (op, op->commit, NULL, op->external_metadata, NULL);
|
|
+ if (!mark_op_resolved (op, op->commit, NULL, op->external_metadata, NULL, error))
|
|
+ return FALSE;
|
|
continue;
|
|
}
|
|
|
|
@@ -3183,7 +3200,8 @@ resolve_ops (FlatpakTransaction *self,
|
|
if (commit_data == NULL)
|
|
return FALSE;
|
|
|
|
- resolve_op_from_commit (self, op, checksum, NULL, commit_data);
|
|
+ if (!resolve_op_from_commit (self, op, checksum, NULL, commit_data, error))
|
|
+ return FALSE;
|
|
}
|
|
else
|
|
{
|
|
@@ -3242,9 +3260,16 @@ resolve_ops (FlatpakTransaction *self,
|
|
}
|
|
|
|
/* First try to resolve via metadata (if remote is available and its metadata matches the commit version) */
|
|
- if (!try_resolve_op_from_metadata (self, op, checksum, sideload_path, state))
|
|
+ if (!try_resolve_op_from_metadata (self, op, checksum, sideload_path, state, &local_error))
|
|
{
|
|
- /* Else try to load the commit object.
|
|
+ if (local_error)
|
|
+ {
|
|
+ /* Actual error, not just missing from summary */
|
|
+ g_propagate_error (error, g_steal_pointer (&local_error));
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ /* Missing from summary, try to load the commit object.
|
|
* Note, we don't have a token here, so this will not work for authenticated apps.
|
|
* We handle this by catching the 401 http status and retrying. */
|
|
g_autoptr(GVariant) commit_data = NULL;
|
|
@@ -3280,7 +3305,8 @@ resolve_ops (FlatpakTransaction *self,
|
|
return FALSE;
|
|
}
|
|
|
|
- resolve_op_from_commit (self, op, checksum, sideload_path, commit_data);
|
|
+ if (!resolve_op_from_commit (self, op, checksum, sideload_path, commit_data, error))
|
|
+ return FALSE;
|
|
}
|
|
}
|
|
}
|
|
--
|
|
2.27.0
|
|
|