From 2fbac5e96bdb6706fe8ec320a494d2a1d7e5d3cd Mon Sep 17 00:00:00 2001 From: dongyuzhen Date: Mon, 7 Feb 2022 15:11:42 +0800 Subject: [PATCH] Fix CVE-2021-43860 --- backport-0001-CVE-2021-43860.patch | 210 +++++++++++++++++++++++++ backport-0002-CVE-2021-43860.patch | 36 +++++ backport-0003-CVE-2021-43860.patch | 210 +++++++++++++++++++++++++ backport-0004-CVE-2021-43860.patch | 76 +++++++++ backport-0005-CVE-2021-43860.patch | 239 +++++++++++++++++++++++++++++ flatpak.spec | 10 +- 6 files changed, 780 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2021-43860.patch create mode 100644 backport-0002-CVE-2021-43860.patch create mode 100644 backport-0003-CVE-2021-43860.patch create mode 100644 backport-0004-CVE-2021-43860.patch create mode 100644 backport-0005-CVE-2021-43860.patch diff --git a/backport-0001-CVE-2021-43860.patch b/backport-0001-CVE-2021-43860.patch new file mode 100644 index 0000000..da1537b --- /dev/null +++ b/backport-0001-CVE-2021-43860.patch @@ -0,0 +1,210 @@ +From 54ec1a482dfc668127eaae57f135e6a8e0bc52da Mon Sep 17 00:00:00 2001 +From: Phaedrus Leeds +Date: Tue, 28 Dec 2021 11:48:16 -0800 +Subject: [PATCH] Add test for metadata validation + +This tests for invalid metadata, missing xa.metadata and mismatched +values in xa.metadata and the real metadata, including the embedded +null leading to the hidden permissions of CVE-2021-43860. + +Conflict:NA +Reference:https://github.com/flatpak/flatpak/commit/54ec1a482dfc668127eaae57f135e6a8e0bc52da + +--- + tests/Makefile-test-matrix.am.inc | 1 + + tests/Makefile.am.inc | 1 + + tests/test-metadata-validation.sh | 158 ++++++++++++++++++++++++++++++ + 3 files changed, 160 insertions(+) + create mode 100644 tests/test-metadata-validation.sh + +diff --git a/tests/Makefile-test-matrix.am.inc b/tests/Makefile-test-matrix.am.inc +index 30b402d..eef5a7e 100644 +--- a/tests/Makefile-test-matrix.am.inc ++++ b/tests/Makefile-test-matrix.am.inc +@@ -36,6 +36,7 @@ TEST_MATRIX_DIST= \ + tests/test-build-update-repo.sh \ + tests/test-http-utils.sh \ + tests/test-default-remotes.sh \ ++ tests/test-metadata-validation.sh \ + tests/test-extensions.sh \ + tests/test-oci.sh \ + tests/test-override.sh \ +diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc +index 2458445..53d6403 100644 +--- a/tests/Makefile.am.inc ++++ b/tests/Makefile.am.inc +@@ -216,6 +216,7 @@ TEST_MATRIX_SOURCE = \ + tests/test-repo.sh{{user+system+system-norevokefs}+{{user+system},oldsummary}} \ + tests/test-sideload.sh{user+system} \ + tests/test-default-remotes.sh \ ++ tests/test-metadata-validation.sh \ + tests/test-extensions.sh \ + tests/test-bundle.sh{user+system+system-norevokefs} \ + tests/test-oci.sh \ +diff --git a/tests/test-metadata-validation.sh b/tests/test-metadata-validation.sh +new file mode 100644 +index 0000000..7e3efcc +--- /dev/null ++++ b/tests/test-metadata-validation.sh +@@ -0,0 +1,158 @@ ++#!/bin/bash ++# ++# Copyright (C) 2021 Matthew Leeds ++# ++# SPDX-License-Identifier: LGPL-2.0-or-later ++ ++set -euo pipefail ++ ++. $(dirname $0)/libtest.sh ++ ++echo "1..7" ++ ++setup_repo ++ ++COUNTER=1 ++ ++create_app () { ++ local OPTIONS="$1" ++ local DIR=`mktemp -d` ++ ++ mkdir ${DIR}/files ++ echo $COUNTER > ${DIR}/files/counter ++ let COUNTER=COUNTER+1 ++ ++ local INVALID="" ++ if [[ $OPTIONS =~ "invalid" ]]; then ++ INVALID=invalidkeyfileline ++ fi ++ cat > ${DIR}/metadata <> ${DIR}/metadata ++ fi ++ if [[ $OPTIONS =~ "hidden" ]]; then ++ echo -ne "\0" >> ${DIR}/metadata ++ echo -e "\nfilesystems=home;" >> ${DIR}/metadata ++ fi ++ local XA_METADATA=--add-metadata-string=xa.metadata="$(head -n6 ${DIR}/metadata)"$'\n' ++ if [[ $OPTIONS =~ "no-xametadata" ]]; then ++ XA_METADATA="--add-metadata-string=xa.nometadata=1" ++ fi ++ ostree commit --repo=repos/test --branch=app/org.test.Malicious/${ARCH}/master ${FL_GPGARGS} "$XA_METADATA" ${DIR}/ ++ if [[ $OPTIONS =~ "no-cache-in-summary" ]]; then ++ ostree --repo=repos/test ${FL_GPGARGS} summary -u ++ # force use of legacy summary format ++ rm -rf repos/test/summary.idx repos/test/summaries ++ else ++ update_repo ++ fi ++ rm -rf ${DIR} ++} ++ ++cleanup_repo () { ++ ostree refs --repo=repos/test --delete app/org.test.Malicious/${ARCH}/master ++ update_repo ++} ++ ++create_app "hidden" ++ ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with hidden permissions" ++fi ++ ++assert_file_has_content install-error-log "not matching expected metadata" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with hidden permissions can't be installed (CVE-2021-43860)" ++ ++create_app no-xametadata ++ ++# The install will fail because the metadata in the summary doesn't match the metadata on the commit ++# The missing xa.metadata in the commit got turned into "" in the xa.cache ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with missing xa.metadata" ++fi ++ ++assert_file_has_content install-error-log "not matching expected metadata" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with no xa.metadata can't be installed" ++ ++create_app "no-xametadata no-cache-in-summary" ++ ++# The install will fail because there's no metadata in the summary or on the commit ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with missing metadata" ++fi ++assert_file_has_content install-error-log "No xa.metadata in local commit" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with no xa.metadata and no metadata in summary can't be installed" ++ ++create_app "invalid" ++ ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with invalid metadata" ++fi ++assert_file_has_content install-error-log "Metadata for .* is invalid" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with invalid metadata (in summary) can't be installed" ++ ++create_app "invalid no-cache-in-summary" ++ ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with invalid metadata" ++fi ++assert_file_has_content install-error-log "Metadata for .* is invalid" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with invalid metadata (in commit) can't be installed" ++ ++create_app "mismatch no-cache-in-summary" ++ ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with non-matching metadata" ++fi ++assert_file_has_content install-error-log "Commit metadata for .* not matching expected metadata" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with mismatched metadata (in commit) can't be installed" ++ ++create_app "mismatch" ++ ++if ${FLATPAK} ${U} install -y test-repo org.test.Malicious 2>install-error-log; then ++ assert_not_reached "Should not be able to install app with non-matching metadata" ++fi ++assert_file_has_content install-error-log "Commit metadata for .* not matching expected metadata" ++ ++assert_not_has_dir $FL_DIR/app/org.test.Malicious/current/active ++ ++cleanup_repo ++ ++ok "app with mismatched metadata (in summary) can't be installed" +-- +2.27.0 + diff --git a/backport-0002-CVE-2021-43860.patch b/backport-0002-CVE-2021-43860.patch new file mode 100644 index 0000000..b90c9d5 --- /dev/null +++ b/backport-0002-CVE-2021-43860.patch @@ -0,0 +1,36 @@ +From 65cbfac982cb1c83993a9e19aa424daee8e9f042 Mon Sep 17 00:00:00 2001 +From: Alexander Larsson +Date: Wed, 12 Jan 2022 11:00:56 +0100 +Subject: [PATCH] Ensure that bundles have metadata on install + +If we have a bundle without metadata we wouldn't properly present +the permissions in the transaction. + +Conflict:NA +Reference:https://github.com/flatpak/flatpak/commit/65cbfac982cb1c83993a9e19aa424daee8e9f042 + +--- + common/flatpak-dir.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c +index 94a86f4..ddc5ee9 100644 +--- a/common/flatpak-dir.c ++++ b/common/flatpak-dir.c +@@ -9295,6 +9295,13 @@ flatpak_dir_ensure_bundle_remote (FlatpakDir *self, + if (metadata == NULL) + return NULL; + ++ /* If we rely on metadata (to e.g. print permissions), check it exists before creating the remote */ ++ if (out_metadata && fp_metadata == NULL) ++ { ++ flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, "No metadata in bundler header"); ++ return NULL; ++ } ++ + gpg_data = extra_gpg_data ? extra_gpg_data : included_gpg_data; + + deploy_data = flatpak_dir_get_deploy_data (self, ref, FLATPAK_DEPLOY_VERSION_ANY, cancellable, NULL); +-- +2.27.0 + diff --git a/backport-0003-CVE-2021-43860.patch b/backport-0003-CVE-2021-43860.patch new file mode 100644 index 0000000..f6ee0a6 --- /dev/null +++ b/backport-0003-CVE-2021-43860.patch @@ -0,0 +1,210 @@ +From ba818f504c926baaf6e362be8159cfacf994310e Mon Sep 17 00:00:00 2001 +From: Ryan Gonzalez +Date: Thu, 23 Dec 2021 18:30:17 -0600 +Subject: [PATCH] Fix metadata file contents after null terminators being + ignored + +In particular, if a null terminator is placed inside the metadata file, +Flatpak will only compare the text *before* it to the value of +xa.metadata, but the full file will be parsed when permissions are set +at runtime. This means that any app can include a null terminator in its +permissions metadata, and Flatpak will only show the user the +permissions *preceding* the terminator during install, but the +permissions *after* the terminator are applied at runtime. + +Fixes GHSA-qpjc-vq3c-572j / CVE-2021-43860 + +Signed-off-by: Ryan Gonzalez + +Conflict:NA +Reference:https://github.com/flatpak/flatpak/commit/ba818f504c926baaf6e362be8159cfacf994310e + +--- + common/flatpak-dir.c | 36 +++++++++++++++++++++++++++--------- + common/flatpak-transaction.c | 8 ++++---- + common/flatpak-utils.c | 9 +++++---- + 3 files changed, 36 insertions(+), 17 deletions(-) + +diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c +index ddc5ee9..e6c8046 100644 +--- a/common/flatpak-dir.c ++++ b/common/flatpak-dir.c +@@ -1762,19 +1762,29 @@ static gboolean + validate_commit_metadata (GVariant *commit_data, + const char *ref, + const char *required_metadata, ++ gsize required_metadata_size, + gboolean require_xa_metadata, + GError **error) + { + g_autoptr(GVariant) commit_metadata = NULL; ++ g_autoptr(GVariant) xa_metadata_v = NULL; + const char *xa_metadata = NULL; ++ gsize xa_metadata_size = 0; + + commit_metadata = g_variant_get_child_value (commit_data, 0); + + if (commit_metadata != NULL) +- g_variant_lookup (commit_metadata, "xa.metadata", "&s", &xa_metadata); ++ { ++ xa_metadata_v = g_variant_lookup_value (commit_metadata, ++ "xa.metadata", ++ G_VARIANT_TYPE_STRING); ++ if (xa_metadata_v) ++ xa_metadata = g_variant_get_string (xa_metadata_v, &xa_metadata_size); ++ } + + if ((xa_metadata == NULL && require_xa_metadata) || +- (xa_metadata != NULL && g_strcmp0 (required_metadata, xa_metadata) != 0)) ++ (xa_metadata != NULL && (xa_metadata_size != required_metadata_size || ++ memcmp (xa_metadata, required_metadata, xa_metadata_size) != 0))) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, + _("Commit metadata for %s not matching expected metadata"), ref); +@@ -3478,6 +3488,7 @@ upgrade_deploy_data (GBytes *deploy_data, + g_autoptr(GKeyFile) keyfile = NULL; + g_autoptr(GFile) metadata_file = NULL; + g_autofree char *metadata_contents = NULL; ++ gsize metadata_size = 0; + g_autofree char *id = flatpak_decomposed_dup_id (ref); + + /* Add fields from commit metadata to deploy */ +@@ -3491,9 +3502,9 @@ upgrade_deploy_data (GBytes *deploy_data, + keyfile = g_key_file_new (); + metadata_file = g_file_resolve_relative_path (deploy_dir, "metadata"); + if (!g_file_load_contents (metadata_file, cancellable, +- &metadata_contents, NULL, NULL, error)) ++ &metadata_contents, &metadata_size, NULL, error)) + return NULL; +- if (!g_key_file_load_from_data (keyfile, metadata_contents, -1, 0, error)) ++ if (!g_key_file_load_from_data (keyfile, metadata_contents, metadata_size, 0, error)) + return NULL; + add_metadata_to_deploy_data (&metadata_dict, keyfile); + +@@ -5799,8 +5810,13 @@ flatpak_dir_pull (FlatpakDir *self, + { + g_autoptr(GVariant) commit_data = NULL; + if (!ostree_repo_load_commit (repo, rev, &commit_data, NULL, error) || +- !validate_commit_metadata (commit_data, ref, (const char *)g_bytes_get_data (require_metadata, NULL), TRUE, error)) +- return FALSE; ++ !validate_commit_metadata (commit_data, ++ ref, ++ (const char *)g_bytes_get_data (require_metadata, NULL), ++ g_bytes_get_size (require_metadata), ++ TRUE, ++ error)) ++ goto out; + } + + if (!flatpak_dir_pull_extra_data (self, repo, +@@ -8111,6 +8127,7 @@ flatpak_dir_deploy (FlatpakDir *self, + g_auto(GLnxLockFile) lock = { 0, }; + g_autoptr(GFile) metadata_file = NULL; + g_autofree char *metadata_contents = NULL; ++ gsize metadata_size = 0; + gboolean is_oci; + + if (!flatpak_dir_ensure_repo (self, cancellable, error)) +@@ -8320,11 +8337,12 @@ flatpak_dir_deploy (FlatpakDir *self, + keyfile = g_key_file_new (); + metadata_file = g_file_resolve_relative_path (checkoutdir, "metadata"); + if (g_file_load_contents (metadata_file, NULL, +- &metadata_contents, NULL, NULL, NULL)) ++ &metadata_contents, ++ &metadata_size, NULL, NULL)) + { + if (!g_key_file_load_from_data (keyfile, + metadata_contents, +- -1, ++ metadata_size, + 0, error)) + return FALSE; + +@@ -8340,7 +8358,7 @@ flatpak_dir_deploy (FlatpakDir *self, + */ + is_oci = flatpak_dir_get_remote_oci (self, origin); + if (!validate_commit_metadata (commit_data, flatpak_decomposed_get_ref (ref), +- metadata_contents, !is_oci, error)) ++ metadata_contents, metadata_size, !is_oci, error)) + return FALSE; + + dotref = g_file_resolve_relative_path (checkoutdir, "files/.ref"); +diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c +index 1927498..721da14 100644 +--- a/common/flatpak-transaction.c ++++ b/common/flatpak-transaction.c +@@ -2520,7 +2520,7 @@ flatpak_transaction_add_ref (FlatpakTransaction *self, + return FALSE; + + if (external_metadata) +- op->external_metadata = g_bytes_new (external_metadata, strlen (external_metadata) + 1); ++ op->external_metadata = g_bytes_new (external_metadata, strlen (external_metadata)); + + return TRUE; + } +@@ -2937,7 +2937,7 @@ load_deployed_metadata (FlatpakTransaction *self, FlatpakDecomposed *ref, char * + return NULL; + } + +- return g_bytes_new_take (g_steal_pointer (&metadata_contents), metadata_contents_length + 1); ++ return g_bytes_new_take (g_steal_pointer (&metadata_contents), metadata_contents_length); + } + + static void +@@ -3034,7 +3034,7 @@ resolve_op_from_commit (FlatpakTransaction *self, + 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) + 1); ++ 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); +@@ -3074,7 +3074,7 @@ try_resolve_op_from_metadata (FlatpakTransaction *self, + &download_size, &installed_size, &metadata, NULL)) + return FALSE; + +- metadata_bytes = g_bytes_new (metadata, strlen (metadata) + 1); ++ metadata_bytes = g_bytes_new (metadata, strlen (metadata)); + + if (flatpak_remote_state_lookup_ref (state, flatpak_decomposed_get_ref (op->ref), + NULL, NULL, &info, NULL, NULL)) +diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c +index 6901a62..9eedbfa 100644 +--- a/common/flatpak-utils.c ++++ b/common/flatpak-utils.c +@@ -6604,6 +6604,7 @@ flatpak_pull_from_bundle (OstreeRepo *repo, + GCancellable *cancellable, + GError **error) + { ++ gsize metadata_size = 0; + g_autofree char *metadata_contents = NULL; + g_autofree char *to_checksum = NULL; + g_autoptr(GFile) root = NULL; +@@ -6620,6 +6621,8 @@ flatpak_pull_from_bundle (OstreeRepo *repo, + if (metadata == NULL) + return FALSE; + ++ metadata_size = strlen (metadata_contents); ++ + if (!ostree_repo_get_remote_option (repo, remote, "collection-id", NULL, + &remote_collection_id, NULL)) + remote_collection_id = NULL; +@@ -6689,12 +6692,10 @@ flatpak_pull_from_bundle (OstreeRepo *repo, + cancellable, error) < 0) + return FALSE; + +- /* Null terminate */ +- g_output_stream_write (G_OUTPUT_STREAM (data_stream), "\0", 1, NULL, NULL); +- + metadata_valid = + metadata_contents != NULL && +- strcmp (metadata_contents, g_memory_output_stream_get_data (data_stream)) == 0; ++ metadata_size == g_memory_output_stream_get_data_size (data_stream) && ++ memcmp (metadata_contents, g_memory_output_stream_get_data (data_stream), metadata_size) == 0; + } + else + { +-- +2.27.0 + diff --git a/backport-0004-CVE-2021-43860.patch b/backport-0004-CVE-2021-43860.patch new file mode 100644 index 0000000..67aab69 --- /dev/null +++ b/backport-0004-CVE-2021-43860.patch @@ -0,0 +1,76 @@ +From 93357d357119093804df05acc32ff335839c6451 Mon Sep 17 00:00:00 2001 +From: Alexander Larsson +Date: Tue, 11 Jan 2022 10:27:46 +0100 +Subject: [PATCH] Require metadata in commit also for OCI remotes + +This was disables a long time ago because the fedora remotes didn't +contain metadata, but that has been added since then. Requiring fixes +a security concern where an app claims to require no permissions (by +having no metadata in commit) but then actually requires permissions +in the installed app. + +Conflict:NA +Reference:https://github.com/flatpak/flatpak/commit/93357d357119093804df05acc32ff335839c6451 + +--- + common/flatpak-dir.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c +index e6c8046..e6a83cf 100644 +--- a/common/flatpak-dir.c ++++ b/common/flatpak-dir.c +@@ -1763,7 +1763,6 @@ validate_commit_metadata (GVariant *commit_data, + const char *ref, + const char *required_metadata, + gsize required_metadata_size, +- gboolean require_xa_metadata, + GError **error) + { + g_autoptr(GVariant) commit_metadata = NULL; +@@ -1782,9 +1781,9 @@ validate_commit_metadata (GVariant *commit_data, + xa_metadata = g_variant_get_string (xa_metadata_v, &xa_metadata_size); + } + +- if ((xa_metadata == NULL && require_xa_metadata) || +- (xa_metadata != NULL && (xa_metadata_size != required_metadata_size || +- memcmp (xa_metadata, required_metadata, xa_metadata_size) != 0))) ++ if (xa_metadata == NULL || ++ xa_metadata_size != required_metadata_size || ++ memcmp (xa_metadata, required_metadata, xa_metadata_size) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, + _("Commit metadata for %s not matching expected metadata"), ref); +@@ -5814,7 +5813,6 @@ flatpak_dir_pull (FlatpakDir *self, + ref, + (const char *)g_bytes_get_data (require_metadata, NULL), + g_bytes_get_size (require_metadata), +- TRUE, + error)) + goto out; + } +@@ -8128,7 +8126,6 @@ flatpak_dir_deploy (FlatpakDir *self, + g_autoptr(GFile) metadata_file = NULL; + g_autofree char *metadata_contents = NULL; + gsize metadata_size = 0; +- gboolean is_oci; + + if (!flatpak_dir_ensure_repo (self, cancellable, error)) + return FALSE; +@@ -8353,12 +8350,9 @@ flatpak_dir_deploy (FlatpakDir *self, + /* Check the metadata in the commit to make sure it matches the actual + * deployed metadata, in case we relied on the one in the commit for + * a decision +- * Note: For historical reason we don't enforce commits to contain xa.metadata +- * since this was lacking in fedora builds. + */ +- is_oci = flatpak_dir_get_remote_oci (self, origin); + if (!validate_commit_metadata (commit_data, flatpak_decomposed_get_ref (ref), +- metadata_contents, metadata_size, !is_oci, error)) ++ metadata_contents, metadata_size, error)) + return FALSE; + + dotref = g_file_resolve_relative_path (checkoutdir, "files/.ref"); +-- +2.27.0 + diff --git a/backport-0005-CVE-2021-43860.patch b/backport-0005-CVE-2021-43860.patch new file mode 100644 index 0000000..9212b91 --- /dev/null +++ b/backport-0005-CVE-2021-43860.patch @@ -0,0 +1,239 @@ +From d9a8f9d8ccc0b7c1135d0ecde006a75d25f66aee Mon Sep 17 00:00:00 2001 +From: Alexander Larsson +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 + diff --git a/flatpak.spec b/flatpak.spec index d1a2086..580dcf6 100644 --- a/flatpak.spec +++ b/flatpak.spec @@ -1,6 +1,6 @@ Name: flatpak Version: 1.10.2 -Release: 4 +Release: 5 Summary: Application deployment framework for desktop apps License: LGPLv2+ URL: http://flatpak.org/ @@ -21,6 +21,11 @@ Patch6008: backport-run-Handle-unknown-syscalls-as-intended.patch Patch6009: backport-Fix-handling-of-syscalls-only-allowed-by-de.patch Patch6010: support-new-pyparsing.patch Patch6011: backport-CVE-2022-21682.patch +Patch6012: backport-0001-CVE-2021-43860.patch +Patch6013: backport-0002-CVE-2021-43860.patch +Patch6014: backport-0003-CVE-2021-43860.patch +Patch6015: backport-0004-CVE-2021-43860.patch +Patch6016: backport-0005-CVE-2021-43860.patch BuildRequires: pkgconfig(appstream-glib) pkgconfig(gio-unix-2.0) pkgconfig(gobject-introspection-1.0) >= 1.40.0 pkgconfig(json-glib-1.0) pkgconfig(libarchive) >= 2.8.0 BuildRequires: pkgconfig(libsoup-2.4) pkgconfig(libxml-2.0) >= 2.4 pkgconfig(ostree-1) >= 2020.8 pkgconfig(polkit-gobject-1) pkgconfig(libseccomp) pkgconfig(xau) @@ -126,6 +131,9 @@ flatpak remote-list --system &> /dev/null || : %{_mandir}/man5/flatpak-remote.5* %changelog +* Mon Feb 07 2022 dongyuzhen - 1.10.2-5 +- Fix CVE-2021-43860 + * Mon Jan 24 2022 wangkerong - 1.10.2-4 - Fix CVE-2022-21682 -- Gitee