Fix CVE-2023-28100 and CVE-2023-28101 and Fix several memory leaks
(cherry picked from commit 6fe17b7f232e7c9530c41cff1c634d3cbad5ef28)
This commit is contained in:
parent
748a464156
commit
c06772b78d
394
CVE-2023-28100-pre1.patch
Normal file
394
CVE-2023-28100-pre1.patch
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
From 4206d681c5c52691dec0074e3f8c32dab1953a94 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon McVittie <smcv@collabora.com>
|
||||||
|
Date: Fri, 21 May 2021 17:41:31 +0100
|
||||||
|
Subject: [PATCH] test-context: Exercise some corner cases for merging
|
||||||
|
filesystems
|
||||||
|
|
||||||
|
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||||
|
Co-authored-by: Alexander Larsson <alexl@redhat.com>
|
||||||
|
(cherry picked from commit fab0f8ed7c52fc58e6c550d123ede9621c760ca7)
|
||||||
|
[smcv: Also backport the scaffolding to create this test-case]
|
||||||
|
---
|
||||||
|
tests/Makefile.am.inc | 11 +-
|
||||||
|
tests/test-context.c | 343 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 353 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 tests/test-context.c
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc
|
||||||
|
index 53d6403e4c..0fb650cb38 100644
|
||||||
|
--- a/tests/Makefile.am.inc
|
||||||
|
+++ b/tests/Makefile.am.inc
|
||||||
|
@@ -66,6 +66,10 @@ testcommon_LDADD = \
|
||||||
|
$(NULL)
|
||||||
|
testcommon_SOURCES = tests/testcommon.c
|
||||||
|
|
||||||
|
+test_context_CFLAGS = $(testcommon_CFLAGS)
|
||||||
|
+test_context_LDADD = $(testcommon_LDADD)
|
||||||
|
+test_context_SOURCES = tests/test-context.c
|
||||||
|
+
|
||||||
|
test_exports_CFLAGS = $(testcommon_CFLAGS)
|
||||||
|
test_exports_LDADD = $(testcommon_LDADD)
|
||||||
|
test_exports_SOURCES = tests/test-exports.c
|
||||||
|
@@ -252,7 +256,12 @@ test_scripts = ${TEST_MATRIX}
|
||||||
|
dist_test_scripts = ${TEST_MATRIX_DIST}
|
||||||
|
dist_installed_test_extra_scripts += ${TEST_MATRIX_EXTRA_DIST}
|
||||||
|
|
||||||
|
-test_programs = testlibrary testcommon test-exports
|
||||||
|
+test_programs = \
|
||||||
|
+ test-context \
|
||||||
|
+ test-exports \
|
||||||
|
+ testcommon \
|
||||||
|
+ testlibrary \
|
||||||
|
+ $(NULL)
|
||||||
|
test_extra_programs = tests/httpcache tests/test-update-portal tests/test-portal-impl tests/test-authenticator tests/list-unused
|
||||||
|
|
||||||
|
@VALGRIND_CHECK_RULES@
|
||||||
|
diff --git a/tests/test-context.c b/tests/test-context.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..c128a83fae
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/test-context.c
|
||||||
|
@@ -0,0 +1,343 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright © 2021 Collabora Ltd.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or
|
||||||
|
+ * modify it under the terms of the GNU Lesser General Public
|
||||||
|
+ * License as published by the Free Software Foundation; either
|
||||||
|
+ * version 2.1 of the License, or (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This library is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
+ * Lesser General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU Lesser General Public
|
||||||
|
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "config.h"
|
||||||
|
+
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+
|
||||||
|
+#include <glib.h>
|
||||||
|
+#include "flatpak.h"
|
||||||
|
+#include "flatpak-context-private.h"
|
||||||
|
+#include "flatpak-run-private.h"
|
||||||
|
+#include "flatpak-utils-private.h"
|
||||||
|
+
|
||||||
|
+/* g_str_has_prefix as a GEqualFunc */
|
||||||
|
+static gboolean
|
||||||
|
+str_has_prefix (gconstpointer candidate,
|
||||||
|
+ gconstpointer pattern)
|
||||||
|
+{
|
||||||
|
+ return g_str_has_prefix (candidate, pattern);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void context_parse_args (FlatpakContext *context,
|
||||||
|
+ ...) G_GNUC_NULL_TERMINATED;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+context_parse_args (FlatpakContext *context,
|
||||||
|
+ ...)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(GError) local_error = NULL;
|
||||||
|
+ g_autoptr(GOptionContext) oc = NULL;
|
||||||
|
+ g_autoptr(GOptionGroup) group = NULL;
|
||||||
|
+ g_autoptr(GPtrArray) args = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
+ g_auto(GStrv) argv = NULL;
|
||||||
|
+ const char *arg;
|
||||||
|
+ va_list ap;
|
||||||
|
+
|
||||||
|
+ g_ptr_array_add (args, g_strdup ("argv[0]"));
|
||||||
|
+
|
||||||
|
+ va_start (ap, context);
|
||||||
|
+
|
||||||
|
+ while ((arg = va_arg (ap, const char *)) != NULL)
|
||||||
|
+ g_ptr_array_add (args, g_strdup (arg));
|
||||||
|
+
|
||||||
|
+ va_end (ap);
|
||||||
|
+
|
||||||
|
+ g_ptr_array_add (args, NULL);
|
||||||
|
+ argv = (GStrv) g_ptr_array_free (g_steal_pointer (&args), FALSE);
|
||||||
|
+
|
||||||
|
+ oc = g_option_context_new ("");
|
||||||
|
+ group = flatpak_context_get_options (context);
|
||||||
|
+ g_option_context_add_group (oc, group);
|
||||||
|
+ g_option_context_parse_strv (oc, &argv, &local_error);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_context_merge_fs (void)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * We want to arrive at the same result regardless of whether we:
|
||||||
|
+ * - start from lowest precedence, and successively merge higher
|
||||||
|
+ * precedences into it, discarding them when done;
|
||||||
|
+ * - successively merge highest precedence into second-highest, and
|
||||||
|
+ * then discard highest
|
||||||
|
+ */
|
||||||
|
+ enum { LOWEST_FIRST, HIGHEST_FIRST, INVALID } merge_order;
|
||||||
|
+
|
||||||
|
+ for (merge_order = LOWEST_FIRST; merge_order < INVALID; merge_order++)
|
||||||
|
+ {
|
||||||
|
+ g_autoptr(FlatpakContext) lowest = flatpak_context_new ();
|
||||||
|
+ g_autoptr(FlatpakContext) middle = flatpak_context_new ();
|
||||||
|
+ g_autoptr(FlatpakContext) highest = flatpak_context_new ();
|
||||||
|
+ gpointer value;
|
||||||
|
+
|
||||||
|
+ context_parse_args (lowest,
|
||||||
|
+ "--filesystem=/one",
|
||||||
|
+ NULL);
|
||||||
|
+ context_parse_args (middle,
|
||||||
|
+ "--nofilesystem=host:reset",
|
||||||
|
+ "--filesystem=/two",
|
||||||
|
+ NULL);
|
||||||
|
+ context_parse_args (highest,
|
||||||
|
+ "--nofilesystem=host",
|
||||||
|
+ "--filesystem=/three",
|
||||||
|
+ NULL);
|
||||||
|
+
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (middle->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (middle->filesystems, "/three", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (highest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (highest->filesystems, "host-reset", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (highest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (highest->filesystems, "/two", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (highest->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+
|
||||||
|
+ if (merge_order == LOWEST_FIRST)
|
||||||
|
+ {
|
||||||
|
+ flatpak_context_merge (lowest, middle);
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ flatpak_context_merge (lowest, highest);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ flatpak_context_merge (middle, highest);
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (middle->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (middle->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+
|
||||||
|
+ flatpak_context_merge (lowest, middle);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (merge_order = LOWEST_FIRST; merge_order < INVALID; merge_order++)
|
||||||
|
+ {
|
||||||
|
+ g_autoptr(FlatpakContext) lowest = flatpak_context_new ();
|
||||||
|
+ g_autoptr(FlatpakContext) mid_low = flatpak_context_new ();
|
||||||
|
+ g_autoptr(FlatpakContext) mid_high = flatpak_context_new ();
|
||||||
|
+ g_autoptr(FlatpakContext) highest = flatpak_context_new ();
|
||||||
|
+ g_autoptr(GError) local_error = NULL;
|
||||||
|
+ g_autoptr(GKeyFile) metakey = g_key_file_new ();
|
||||||
|
+ g_autoptr(GPtrArray) args = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
+ g_autofree char *filesystems = NULL;
|
||||||
|
+ gpointer value;
|
||||||
|
+
|
||||||
|
+ context_parse_args (lowest,
|
||||||
|
+ "--filesystem=/one",
|
||||||
|
+ NULL);
|
||||||
|
+ context_parse_args (mid_low,
|
||||||
|
+ "--nofilesystem=host:reset",
|
||||||
|
+ "--filesystem=/two",
|
||||||
|
+ NULL);
|
||||||
|
+ context_parse_args (mid_high,
|
||||||
|
+ "--filesystem=host",
|
||||||
|
+ "--filesystem=/three",
|
||||||
|
+ NULL);
|
||||||
|
+ context_parse_args (highest,
|
||||||
|
+ "--nofilesystem=host",
|
||||||
|
+ "--filesystem=/four",
|
||||||
|
+ NULL);
|
||||||
|
+
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/four", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_low->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_low->filesystems, "/three", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_low->filesystems, "/four", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_high->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "host-reset", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "/two", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_high->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "/four", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (highest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "host-reset", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (highest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (highest->filesystems, "/two", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (highest->filesystems, "/three", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (highest->filesystems, "/four", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+
|
||||||
|
+ if (merge_order == LOWEST_FIRST)
|
||||||
|
+ {
|
||||||
|
+ flatpak_context_merge (lowest, mid_low);
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/four", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ flatpak_context_merge (lowest, mid_high);
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/four", NULL, NULL));
|
||||||
|
+
|
||||||
|
+ flatpak_context_merge (lowest, highest);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ flatpak_context_merge (mid_high, highest);
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_high->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "host-reset", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_high->filesystems, "/two", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_high->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_high->filesystems, "/four", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+
|
||||||
|
+ flatpak_context_merge (mid_low, mid_high);
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (mid_low->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (mid_low->filesystems, "/four", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+
|
||||||
|
+ flatpak_context_merge (lowest, mid_low);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_NONE);
|
||||||
|
+ g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "/one", NULL, NULL));
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/two", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/three", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+ g_assert_true (g_hash_table_lookup_extended (lowest->filesystems, "/four", NULL, &value));
|
||||||
|
+ g_assert_cmpint (GPOINTER_TO_INT (value), ==, FLATPAK_FILESYSTEM_MODE_READ_WRITE);
|
||||||
|
+
|
||||||
|
+ flatpak_context_save_metadata (lowest, FALSE, metakey);
|
||||||
|
+ filesystems = g_key_file_get_value (metakey,
|
||||||
|
+ FLATPAK_METADATA_GROUP_CONTEXT,
|
||||||
|
+ FLATPAK_METADATA_KEY_FILESYSTEMS,
|
||||||
|
+ &local_error);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
+ g_test_message ("%s=%s", FLATPAK_METADATA_KEY_FILESYSTEMS, filesystems);
|
||||||
|
+ /* !host:reset is serialized first */
|
||||||
|
+ g_assert_true (g_str_has_prefix (filesystems, "!host:reset;"));
|
||||||
|
+ /* The rest are serialized in arbitrary order */
|
||||||
|
+ g_assert_nonnull (strstr (filesystems, ";!host;"));
|
||||||
|
+ g_assert_null (strstr (filesystems, "/one"));
|
||||||
|
+ g_assert_nonnull (strstr (filesystems, ";/two;"));
|
||||||
|
+ g_assert_nonnull (strstr (filesystems, ";/three;"));
|
||||||
|
+ g_assert_nonnull (strstr (filesystems, ";/four;"));
|
||||||
|
+
|
||||||
|
+ flatpak_context_to_args (lowest, args);
|
||||||
|
+ /* !host:reset is serialized first */
|
||||||
|
+ g_assert_cmpuint (args->len, >, 0);
|
||||||
|
+ g_assert_cmpstr (g_ptr_array_index (args, 0), ==,
|
||||||
|
+ "--nofilesystem=host:reset");
|
||||||
|
+ /* The rest are serialized in arbitrary order */
|
||||||
|
+ g_assert_true (g_ptr_array_find_with_equal_func (args, "--nofilesystem=host", g_str_equal, NULL));
|
||||||
|
+ g_assert_false (g_ptr_array_find_with_equal_func (args, "--filesystem=/one", str_has_prefix, NULL));
|
||||||
|
+ g_assert_false (g_ptr_array_find_with_equal_func (args, "--nofilesystem=/one", str_has_prefix, NULL));
|
||||||
|
+ g_assert_true (g_ptr_array_find_with_equal_func (args, "--filesystem=/two", g_str_equal, NULL));
|
||||||
|
+ g_assert_true (g_ptr_array_find_with_equal_func (args, "--filesystem=/three", g_str_equal, NULL));
|
||||||
|
+ g_assert_true (g_ptr_array_find_with_equal_func (args, "--filesystem=/four", g_str_equal, NULL));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main (int argc, char *argv[])
|
||||||
|
+{
|
||||||
|
+ g_test_init (&argc, &argv, NULL);
|
||||||
|
+
|
||||||
|
+ g_test_add_func ("/context/merge-fs", test_context_merge_fs);
|
||||||
|
+
|
||||||
|
+ return g_test_run ();
|
||||||
|
+}
|
||||||
231
CVE-2023-28100-pre2.patch
Normal file
231
CVE-2023-28100-pre2.patch
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
From b83fb81d1a66fe4ea31fd9c36ca425705eaaca99 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon McVittie <smcv@collabora.com>
|
||||||
|
Date: Thu, 21 Oct 2021 17:39:08 +0100
|
||||||
|
Subject: [PATCH] tests: Add try-syscall helper
|
||||||
|
|
||||||
|
This exercises various syscalls. It's heavily based on the one from
|
||||||
|
<https://github.com/containers/bubblewrap/pull/459>, but with the
|
||||||
|
addition of a mode to output the numeric values of various expected
|
||||||
|
errno codes, which are not otherwise available to shell scripts.
|
||||||
|
|
||||||
|
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||||
|
(cherry picked from commit 4ce251882c488953ca6e3734f00c5dbe2e1e3e7a)
|
||||||
|
(cherry picked from commit f82e2a45777e6f370b9d3be787a84cddc3ed0575)
|
||||||
|
---
|
||||||
|
.gitignore | 1 +
|
||||||
|
tests/Makefile.am.inc | 14 +++-
|
||||||
|
tests/try-syscall.c | 173 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 187 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 tests/try-syscall.c
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc
|
||||||
|
index 3632591a04..2548080254 100644
|
||||||
|
--- a/tests/Makefile.am.inc
|
||||||
|
+++ b/tests/Makefile.am.inc
|
||||||
|
@@ -99,6 +99,10 @@ tests_test_authenticator_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) \
|
||||||
|
tests_test_authenticator_LDADD = $(AM_LDADD) $(BASE_LIBS) libflatpak-common.la libflatpak-common-base.la libglnx.la
|
||||||
|
tests_test_authenticator_SOURCES = tests/test-authenticator.c
|
||||||
|
|
||||||
|
+tests_try_syscall_CFLAGS = $(AM_CFLAGS)
|
||||||
|
+tests_try_syscall_LDADD = $(AM_LDADD)
|
||||||
|
+tests_try_syscall_SOURCES = tests/try-syscall.c
|
||||||
|
+
|
||||||
|
tests_list_unused_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS) $(APPSTREAM_GLIB_CFLAGS) \
|
||||||
|
-DFLATPAK_COMPILATION \
|
||||||
|
-DLOCALEDIR=\"$(localedir)\"
|
||||||
|
@@ -263,7 +267,15 @@ test_programs = \
|
||||||
|
testcommon \
|
||||||
|
testlibrary \
|
||||||
|
$(NULL)
|
||||||
|
-test_extra_programs = tests/httpcache tests/test-update-portal tests/test-portal-impl tests/test-authenticator tests/list-unused
|
||||||
|
+
|
||||||
|
+test_extra_programs = \
|
||||||
|
+ tests/httpcache \
|
||||||
|
+ tests/list-unused \
|
||||||
|
+ tests/test-authenticator \
|
||||||
|
+ tests/test-portal-impl \
|
||||||
|
+ tests/test-update-portal \
|
||||||
|
+ tests/try-syscall \
|
||||||
|
+ $(NULL)
|
||||||
|
|
||||||
|
@VALGRIND_CHECK_RULES@
|
||||||
|
VALGRIND_SUPPRESSIONS_FILES=tests/flatpak.supp tests/glib.supp
|
||||||
|
diff --git a/tests/try-syscall.c b/tests/try-syscall.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..84a0ca6673
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/try-syscall.c
|
||||||
|
@@ -0,0 +1,173 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright 2021 Simon McVittie
|
||||||
|
+ * SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
+ *
|
||||||
|
+ * Try one or more system calls that might have been blocked by a
|
||||||
|
+ * seccomp filter. Return the last value of errno seen.
|
||||||
|
+ *
|
||||||
|
+ * In general, we pass a bad fd or pointer to each syscall that will
|
||||||
|
+ * accept one, so that it will fail with EBADF or EFAULT without side-effects.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <sys/ioctl.h>
|
||||||
|
+#include <sys/prctl.h>
|
||||||
|
+#include <sys/socket.h>
|
||||||
|
+#include <sys/syscall.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+
|
||||||
|
+#if defined(_MIPS_SIM)
|
||||||
|
+# if _MIPS_SIM == _MIPS_SIM_ABI32
|
||||||
|
+# define MISSING_SYSCALL_BASE 4000
|
||||||
|
+# elif _MIPS_SIM == _MIPS_SIM_ABI64
|
||||||
|
+# define MISSING_SYSCALL_BASE 5000
|
||||||
|
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
|
||||||
|
+# define MISSING_SYSCALL_BASE 6000
|
||||||
|
+# else
|
||||||
|
+# error "Unknown MIPS ABI"
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if defined(__ia64__)
|
||||||
|
+# define MISSING_SYSCALL_BASE 1024
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if defined(__alpha__)
|
||||||
|
+# define MISSING_SYSCALL_BASE 110
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if defined(__x86_64__) && defined(__ILP32__)
|
||||||
|
+# define MISSING_SYSCALL_BASE 0x40000000
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * MISSING_SYSCALL_BASE:
|
||||||
|
+ *
|
||||||
|
+ * Number to add to the syscall numbers of recently-added syscalls
|
||||||
|
+ * to get the appropriate syscall for the current ABI.
|
||||||
|
+ */
|
||||||
|
+#ifndef MISSING_SYSCALL_BASE
|
||||||
|
+# define MISSING_SYSCALL_BASE 0
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifndef __NR_clone3
|
||||||
|
+# define __NR_clone3 (MISSING_SYSCALL_BASE + 435)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * The size of clone3's parameter (as of 2021)
|
||||||
|
+ */
|
||||||
|
+#define SIZEOF_STRUCT_CLONE_ARGS ((size_t) 88)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * An invalid pointer that will cause syscalls to fail with EFAULT
|
||||||
|
+ */
|
||||||
|
+#define WRONG_POINTER ((char *) 1)
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main (int argc, char **argv)
|
||||||
|
+{
|
||||||
|
+ int errsv = 0;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 1; i < argc; i++)
|
||||||
|
+ {
|
||||||
|
+ const char *arg = argv[i];
|
||||||
|
+
|
||||||
|
+ if (strcmp (arg, "print-errno-values") == 0)
|
||||||
|
+ {
|
||||||
|
+ printf ("EBADF=%d\n", EBADF);
|
||||||
|
+ printf ("EFAULT=%d\n", EFAULT);
|
||||||
|
+ printf ("ENOENT=%d\n", ENOENT);
|
||||||
|
+ printf ("ENOSYS=%d\n", ENOSYS);
|
||||||
|
+ printf ("EPERM=%d\n", EPERM);
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp (arg, "chmod") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EFAULT */
|
||||||
|
+ if (chmod (WRONG_POINTER, 0700) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp (arg, "chroot") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EFAULT */
|
||||||
|
+ if (chroot (WRONG_POINTER) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp (arg, "clone3") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EFAULT */
|
||||||
|
+ if (syscall (__NR_clone3, WRONG_POINTER, SIZEOF_STRUCT_CLONE_ARGS) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp (arg, "ioctl TIOCNOTTY") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EBADF */
|
||||||
|
+ if (ioctl (-1, TIOCNOTTY) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp (arg, "ioctl TIOCSTI") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EBADF */
|
||||||
|
+ if (ioctl (-1, TIOCSTI, WRONG_POINTER) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#ifdef __LP64__
|
||||||
|
+ else if (strcmp (arg, "ioctl TIOCSTI CVE-2019-10063") == 0)
|
||||||
|
+ {
|
||||||
|
+ unsigned long not_TIOCSTI = (0x123UL << 32) | (unsigned long) TIOCSTI;
|
||||||
|
+
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EBADF */
|
||||||
|
+ if (syscall (__NR_ioctl, -1, not_TIOCSTI, WRONG_POINTER) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ else if (strcmp (arg, "listen") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EBADF */
|
||||||
|
+ if (listen (-1, 42) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (strcmp (arg, "prctl") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EFAULT */
|
||||||
|
+ if (prctl (PR_GET_CHILD_SUBREAPER, WRONG_POINTER, 0, 0, 0) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ fprintf (stderr, "Unsupported syscall \"%s\"\n", arg);
|
||||||
|
+ errsv = ENOENT;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return errsv;
|
||||||
|
+}
|
||||||
142
CVE-2023-28100-pre3.patch
Normal file
142
CVE-2023-28100-pre3.patch
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
From e7880e25b9d400feeaacb82f115fae676ce6c65d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon McVittie <smcv@collabora.com>
|
||||||
|
Date: Thu, 21 Oct 2021 17:41:08 +0100
|
||||||
|
Subject: [PATCH] tests: Add basic test coverage for our seccomp filters
|
||||||
|
|
||||||
|
In particular, this checks that CVE-2017-5226, CVE-2019-10063 and
|
||||||
|
CVE-2021-41133 are still prevented.
|
||||||
|
|
||||||
|
Signed-off-by: Simon McVittie <smcv@collabora.com>
|
||||||
|
(cherry picked from commit 7c5aec474caef7aa004286cc9359611ad21d227b)
|
||||||
|
(cherry picked from commit ff0f5a15b26dac28c8efd88c8d47e51751df8043)
|
||||||
|
---
|
||||||
|
tests/Makefile-test-matrix.am.inc | 1 +
|
||||||
|
tests/Makefile.am.inc | 1 +
|
||||||
|
tests/test-seccomp.sh | 94 +++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 96 insertions(+)
|
||||||
|
create mode 100755 tests/test-seccomp.sh
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile-test-matrix.am.inc b/tests/Makefile-test-matrix.am.inc
|
||||||
|
index f56c169e60..e1ec09ffb0 100644
|
||||||
|
--- a/tests/Makefile-test-matrix.am.inc
|
||||||
|
+++ b/tests/Makefile-test-matrix.am.inc
|
||||||
|
@@ -43,6 +43,7 @@ TEST_MATRIX_DIST= \
|
||||||
|
tests/test-override.sh \
|
||||||
|
tests/test-auth.sh \
|
||||||
|
tests/test-unused.sh \
|
||||||
|
+ tests/test-seccomp.sh \
|
||||||
|
$(NULL)
|
||||||
|
TEST_MATRIX_EXTRA_DIST= \
|
||||||
|
tests/test-run.sh \
|
||||||
|
diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc
|
||||||
|
index 2548080254..fd13c0cd3d 100644
|
||||||
|
--- a/tests/Makefile.am.inc
|
||||||
|
+++ b/tests/Makefile.am.inc
|
||||||
|
@@ -237,6 +237,7 @@ TEST_MATRIX_SOURCE = \
|
||||||
|
tests/test-unused.sh \
|
||||||
|
tests/test-summaries.sh{user+system} \
|
||||||
|
tests/test-subset.sh{user+system} \
|
||||||
|
+ tests/test-seccomp.sh \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
update-test-matrix:
|
||||||
|
diff --git a/tests/test-seccomp.sh b/tests/test-seccomp.sh
|
||||||
|
new file mode 100755
|
||||||
|
index 0000000000..72b0dad231
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/test-seccomp.sh
|
||||||
|
@@ -0,0 +1,94 @@
|
||||||
|
+#!/bin/bash
|
||||||
|
+# Copyright 2021 Collabora Ltd.
|
||||||
|
+# SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
+
|
||||||
|
+set -euo pipefail
|
||||||
|
+
|
||||||
|
+. $(dirname $0)/libtest.sh
|
||||||
|
+
|
||||||
|
+skip_without_bwrap
|
||||||
|
+
|
||||||
|
+echo "1..16"
|
||||||
|
+
|
||||||
|
+setup_repo
|
||||||
|
+install_repo
|
||||||
|
+
|
||||||
|
+cp -a "$G_TEST_BUILDDIR/try-syscall" "$test_tmpdir/try-syscall"
|
||||||
|
+
|
||||||
|
+# How this works:
|
||||||
|
+# try-syscall tries to make various syscalls, some benign, some not.
|
||||||
|
+#
|
||||||
|
+# The parameters are chosen to make them fail with EBADF or EFAULT if
|
||||||
|
+# not blocked. If they are blocked, we get ENOSYS or EPERM. If the syscall
|
||||||
|
+# is impossible for a particular architecture, we get ENOENT.
|
||||||
|
+#
|
||||||
|
+# The exit status is an errno value, which we can compare with the expected
|
||||||
|
+# errno value.
|
||||||
|
+
|
||||||
|
+eval "$("$test_tmpdir/try-syscall" print-errno-values)"
|
||||||
|
+
|
||||||
|
+try_syscall () {
|
||||||
|
+ ${FLATPAK} run \
|
||||||
|
+ --filesystem="$test_tmpdir" \
|
||||||
|
+ --command="$test_tmpdir/try-syscall" \
|
||||||
|
+ $extra_argv \
|
||||||
|
+ org.test.Hello "$@"
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+for extra_argv in "" "--allow=multiarch"; do
|
||||||
|
+ echo "# testing with extra argv: '$extra_argv'"
|
||||||
|
+
|
||||||
|
+ echo "# chmod (benign)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall chmod || e="$?"
|
||||||
|
+ assert_streq "$e" "$EFAULT"
|
||||||
|
+ ok "chmod not blocked"
|
||||||
|
+
|
||||||
|
+ echo "# chroot (harmful)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall chroot || e="$?"
|
||||||
|
+ assert_streq "$e" "$EPERM"
|
||||||
|
+ ok "chroot blocked with EPERM"
|
||||||
|
+
|
||||||
|
+ echo "# clone3 (harmful)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall clone3 || e="$?"
|
||||||
|
+ # This is either ENOSYS because the kernel genuinely doesn't implement it,
|
||||||
|
+ # or because we successfully blocked it. We can't tell which.
|
||||||
|
+ assert_streq "$e" "$ENOSYS"
|
||||||
|
+ ok "clone3 blocked with ENOSYS (CVE-2021-41133)"
|
||||||
|
+
|
||||||
|
+ echo "# ioctl TIOCNOTTY (benign)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall "ioctl TIOCNOTTY" || e="$?"
|
||||||
|
+ assert_streq "$e" "$EBADF"
|
||||||
|
+ ok "ioctl TIOCNOTTY not blocked"
|
||||||
|
+
|
||||||
|
+ echo "# ioctl TIOCSTI (CVE-2017-5226)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall "ioctl TIOCSTI" || e="$?"
|
||||||
|
+ assert_streq "$e" "$EPERM"
|
||||||
|
+ ok "ioctl TIOCSTI blocked (CVE-2017-5226)"
|
||||||
|
+
|
||||||
|
+ echo "# ioctl TIOCSTI (trying to repeat CVE-2019-10063)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall "ioctl TIOCSTI CVE-2019-10063" || e="$?"
|
||||||
|
+ if test "$e" = "$ENOENT"; then
|
||||||
|
+ echo "ok # SKIP Cannot replicate CVE-2019-10063 on 32-bit architecture"
|
||||||
|
+ else
|
||||||
|
+ assert_streq "$e" "$EPERM"
|
||||||
|
+ ok "ioctl TIOCSTI with high bits blocked (CVE-2019-10063)"
|
||||||
|
+ fi
|
||||||
|
+
|
||||||
|
+ echo "# listen (benign)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall "listen" || e="$?"
|
||||||
|
+ assert_streq "$e" "$EBADF"
|
||||||
|
+ ok "listen not blocked"
|
||||||
|
+
|
||||||
|
+ echo "# prctl (benign)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall "prctl" || e="$?"
|
||||||
|
+ assert_streq "$e" "$EFAULT"
|
||||||
|
+ ok "prctl not blocked"
|
||||||
|
+done
|
||||||
85
CVE-2023-28100.patch
Normal file
85
CVE-2023-28100.patch
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
From a9bf18040cc075a70657c6090a59d7f6fe78f893 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Simon McVittie <smcv@debian.org>
|
||||||
|
Date: Wed, 15 Mar 2023 09:58:56 +0000
|
||||||
|
Subject: [PATCH] run: Prevent TIOCLINUX ioctl, the same as TIOCSTI
|
||||||
|
|
||||||
|
The TIOCLINUX ioctl is only available on Linux virtual consoles such as
|
||||||
|
/dev/tty1. It has several Linux-specific functions, one of which is a
|
||||||
|
copy/paste operation which can be used for attacks similar to TIOCSTI.
|
||||||
|
|
||||||
|
This vulnerability does not affect typical graphical terminal emulators
|
||||||
|
such as xterm, gnome-terminal and Konsole, and Flatpak is primarily
|
||||||
|
designed to be run from a Wayland or X11 graphical environment, so this
|
||||||
|
is relatively unlikely to be a practical problem.
|
||||||
|
|
||||||
|
CVE-2023-28100, GHSA-7qpw-3vjv-xrqp
|
||||||
|
|
||||||
|
Resolves: https://github.com/flatpak/flatpak/security/advisories/GHSA-7qpw-3vjv-xrqp
|
||||||
|
Signed-off-by: Simon McVittie <smcv@debian.org>
|
||||||
|
---
|
||||||
|
common/flatpak-run.c | 4 ++++
|
||||||
|
tests/test-seccomp.sh | 8 +++++++-
|
||||||
|
tests/try-syscall.c | 9 +++++++++
|
||||||
|
3 files changed, 20 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
|
||||||
|
index 1c43ca7205..c4dcaca9e6 100644
|
||||||
|
--- a/common/flatpak-run.c
|
||||||
|
+++ b/common/flatpak-run.c
|
||||||
|
@@ -2872,6 +2872,10 @@ setup_seccomp (FlatpakBwrap *bwrap,
|
||||||
|
|
||||||
|
/* Don't allow faking input to the controlling tty (CVE-2017-5226) */
|
||||||
|
{SCMP_SYS (ioctl), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCSTI)},
|
||||||
|
+ /* In the unlikely event that the controlling tty is a Linux virtual
|
||||||
|
+ * console (/dev/tty2 or similar), copy/paste operations have an effect
|
||||||
|
+ * similar to TIOCSTI (CVE-2023-28100) */
|
||||||
|
+ {SCMP_SYS (ioctl), EPERM, &SCMP_A1 (SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int) TIOCLINUX)},
|
||||||
|
|
||||||
|
/* seccomp can't look into clone3()'s struct clone_args to check whether
|
||||||
|
* the flags are OK, so we have no choice but to block clone3().
|
||||||
|
diff --git a/tests/test-seccomp.sh b/tests/test-seccomp.sh
|
||||||
|
index 72b0dad231..be6fb085d0 100755
|
||||||
|
--- a/tests/test-seccomp.sh
|
||||||
|
+++ b/tests/test-seccomp.sh
|
||||||
|
@@ -8,7 +8,7 @@ set -euo pipefail
|
||||||
|
|
||||||
|
skip_without_bwrap
|
||||||
|
|
||||||
|
-echo "1..16"
|
||||||
|
+echo "1..18"
|
||||||
|
|
||||||
|
setup_repo
|
||||||
|
install_repo
|
||||||
|
@@ -80,6 +80,12 @@ for extra_argv in "" "--allow=multiarch"; do
|
||||||
|
ok "ioctl TIOCSTI with high bits blocked (CVE-2019-10063)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
+ echo "# ioctl TIOCLINUX (CVE-2023-28100)"
|
||||||
|
+ e=0
|
||||||
|
+ try_syscall "ioctl TIOCLINUX" || e="$?"
|
||||||
|
+ assert_streq "$e" "$EPERM"
|
||||||
|
+ ok "ioctl TIOCLINUX blocked"
|
||||||
|
+
|
||||||
|
echo "# listen (benign)"
|
||||||
|
e=0
|
||||||
|
try_syscall "listen" || e="$?"
|
||||||
|
diff --git a/tests/try-syscall.c b/tests/try-syscall.c
|
||||||
|
index 84a0ca6673..9dab899ba3 100644
|
||||||
|
--- a/tests/try-syscall.c
|
||||||
|
+++ b/tests/try-syscall.c
|
||||||
|
@@ -144,6 +144,15 @@ main (int argc, char **argv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
+ else if (strcmp (arg, "ioctl TIOCLINUX") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* If not blocked by seccomp, this will fail with EBADF */
|
||||||
|
+ if (ioctl (-1, TIOCLINUX, WRONG_POINTER) != 0)
|
||||||
|
+ {
|
||||||
|
+ errsv = errno;
|
||||||
|
+ perror (arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
else if (strcmp (arg, "listen") == 0)
|
||||||
|
{
|
||||||
|
/* If not blocked by seccomp, this will fail with EBADF */
|
||||||
320
CVE-2023-28101-1.patch
Normal file
320
CVE-2023-28101-1.patch
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
From acd627a2fabe9856947399044dbf7aa79247c75b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ryan Gonzalez <ryan.gonzalez@collabora.com>
|
||||||
|
Date: Sat, 4 Mar 2023 16:23:37 -0600
|
||||||
|
Subject: [PATCH] Ensure special characters in permissions and metadata are
|
||||||
|
escaped
|
||||||
|
|
||||||
|
This prevents someone from placing special characters in order to
|
||||||
|
manipulate the appearance of the permissions list.
|
||||||
|
|
||||||
|
CVE-2023-28101, GHSA-h43h-fwqx-mpp8
|
||||||
|
|
||||||
|
Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
|
||||||
|
---
|
||||||
|
app/flatpak-builtins-info.c | 8 +++-
|
||||||
|
app/flatpak-builtins-remote-info.c | 5 +-
|
||||||
|
app/flatpak-cli-transaction.c | 12 +++--
|
||||||
|
common/flatpak-utils-private.h | 11 +++++
|
||||||
|
common/flatpak-utils.c | 77 ++++++++++++++++++++++++++++++
|
||||||
|
tests/make-test-app.sh | 8 ++++
|
||||||
|
tests/test-info.sh | 14 ++++--
|
||||||
|
tests/testcommon.c | 39 +++++++++++++++
|
||||||
|
8 files changed, 164 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/app/flatpak-builtins-info.c b/app/flatpak-builtins-info.c
|
||||||
|
index c13d2d89eb..35d49c446a 100644
|
||||||
|
--- a/app/flatpak-builtins-info.c
|
||||||
|
+++ b/app/flatpak-builtins-info.c
|
||||||
|
@@ -400,7 +400,9 @@ flatpak_builtin_info (int argc, char **argv, GCancellable *cancellable, GError *
|
||||||
|
if (!g_file_load_contents (file, cancellable, &data, &data_size, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
- g_print ("%s", data);
|
||||||
|
+ flatpak_print_escaped_string (data,
|
||||||
|
+ FLATPAK_ESCAPE_ALLOW_NEWLINES
|
||||||
|
+ | FLATPAK_ESCAPE_DO_NOT_QUOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_show_permissions || opt_file_access)
|
||||||
|
@@ -421,7 +423,9 @@ flatpak_builtin_info (int argc, char **argv, GCancellable *cancellable, GError *
|
||||||
|
if (contents == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
- g_print ("%s", contents);
|
||||||
|
+ flatpak_print_escaped_string (contents,
|
||||||
|
+ FLATPAK_ESCAPE_ALLOW_NEWLINES
|
||||||
|
+ | FLATPAK_ESCAPE_DO_NOT_QUOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_file_access)
|
||||||
|
diff --git a/app/flatpak-builtins-remote-info.c b/app/flatpak-builtins-remote-info.c
|
||||||
|
index 20705a97ca..0ab05b7ca4 100644
|
||||||
|
--- a/app/flatpak-builtins-remote-info.c
|
||||||
|
+++ b/app/flatpak-builtins-remote-info.c
|
||||||
|
@@ -441,7 +441,10 @@ flatpak_builtin_remote_info (int argc, char **argv, GCancellable *cancellable, G
|
||||||
|
|
||||||
|
if (opt_show_metadata)
|
||||||
|
{
|
||||||
|
- g_print ("%s", xa_metadata ? xa_metadata : "");
|
||||||
|
+ if (xa_metadata != NULL)
|
||||||
|
+ flatpak_print_escaped_string (xa_metadata,
|
||||||
|
+ FLATPAK_ESCAPE_ALLOW_NEWLINES
|
||||||
|
+ | FLATPAK_ESCAPE_DO_NOT_QUOTE);
|
||||||
|
if (xa_metadata == NULL || !g_str_has_suffix (xa_metadata, "\n"))
|
||||||
|
g_print ("\n");
|
||||||
|
}
|
||||||
|
diff --git a/app/flatpak-cli-transaction.c b/app/flatpak-cli-transaction.c
|
||||||
|
index a258f905c4..b915bedd04 100644
|
||||||
|
--- a/app/flatpak-cli-transaction.c
|
||||||
|
+++ b/app/flatpak-cli-transaction.c
|
||||||
|
@@ -894,12 +894,16 @@ print_perm_line (int idx,
|
||||||
|
int cols)
|
||||||
|
{
|
||||||
|
g_autoptr(GString) res = g_string_new (NULL);
|
||||||
|
+ g_autofree char *escaped_first_perm = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- g_string_append_printf (res, " [%d] %s", idx, (char *) items->pdata[0]);
|
||||||
|
+ escaped_first_perm = flatpak_escape_string (items->pdata[0], FLATPAK_ESCAPE_DEFAULT);
|
||||||
|
+ g_string_append_printf (res, " [%d] %s", idx, escaped_first_perm);
|
||||||
|
|
||||||
|
for (i = 1; i < items->len; i++)
|
||||||
|
{
|
||||||
|
+ g_autofree char *escaped = flatpak_escape_string (items->pdata[i],
|
||||||
|
+ FLATPAK_ESCAPE_DEFAULT);
|
||||||
|
char *p;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
@@ -908,10 +912,10 @@ print_perm_line (int idx,
|
||||||
|
p = res->str;
|
||||||
|
|
||||||
|
len = (res->str + strlen (res->str)) - p;
|
||||||
|
- if (len + strlen ((char *) items->pdata[i]) + 2 >= cols)
|
||||||
|
- g_string_append_printf (res, ",\n %s", (char *) items->pdata[i]);
|
||||||
|
+ if (len + strlen (escaped) + 2 >= cols)
|
||||||
|
+ g_string_append_printf (res, ",\n %s", escaped);
|
||||||
|
else
|
||||||
|
- g_string_append_printf (res, ", %s", (char *) items->pdata[i]);
|
||||||
|
+ g_string_append_printf (res, ", %s", escaped);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_print ("%s\n", res->str);
|
||||||
|
diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h
|
||||||
|
index 1a92154706..c1282641f9 100644
|
||||||
|
--- a/common/flatpak-utils-private.h
|
||||||
|
+++ b/common/flatpak-utils-private.h
|
||||||
|
@@ -902,6 +902,17 @@ null_safe_g_ptr_array_unref (gpointer data)
|
||||||
|
g_clear_pointer (&data, g_ptr_array_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
+typedef enum {
|
||||||
|
+ FLATPAK_ESCAPE_DEFAULT = 0,
|
||||||
|
+ FLATPAK_ESCAPE_ALLOW_NEWLINES = 1 << 0,
|
||||||
|
+ FLATPAK_ESCAPE_DO_NOT_QUOTE = 1 << 1,
|
||||||
|
+} FlatpakEscapeFlags;
|
||||||
|
+
|
||||||
|
+char * flatpak_escape_string (const char *s,
|
||||||
|
+ FlatpakEscapeFlags flags);
|
||||||
|
+void flatpak_print_escaped_string (const char *s,
|
||||||
|
+ FlatpakEscapeFlags flags);
|
||||||
|
+
|
||||||
|
#define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
|
||||||
|
|
||||||
|
#endif /* __FLATPAK_UTILS_H__ */
|
||||||
|
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||||
|
index 3a5adb82ee..0b91ae3f91 100644
|
||||||
|
--- a/common/flatpak-utils.c
|
||||||
|
+++ b/common/flatpak-utils.c
|
||||||
|
@@ -8613,4 +8613,81 @@ flatpak_dconf_path_is_similar (const char *path1,
|
||||||
|
return (path1[i1] == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
+static gboolean
|
||||||
|
+is_char_safe (gunichar c)
|
||||||
|
+{
|
||||||
|
+ return g_unichar_isgraph (c) || c == ' ';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static gboolean
|
||||||
|
+should_hex_escape (gunichar c,
|
||||||
|
+ FlatpakEscapeFlags flags)
|
||||||
|
+{
|
||||||
|
+ if ((flags & FLATPAK_ESCAPE_ALLOW_NEWLINES) && c == '\n')
|
||||||
|
+ return FALSE;
|
||||||
|
|
||||||
|
+ return !is_char_safe (c);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+append_hex_escaped_character (GString *result,
|
||||||
|
+ gunichar c)
|
||||||
|
+{
|
||||||
|
+ if (c <= 0xFF)
|
||||||
|
+ g_string_append_printf (result, "\\x%02X", c);
|
||||||
|
+ else if (c <= 0xFFFF)
|
||||||
|
+ g_string_append_printf (result, "\\u%04X", c);
|
||||||
|
+ else
|
||||||
|
+ g_string_append_printf (result, "\\U%08X", c);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+flatpak_escape_string (const char *s,
|
||||||
|
+ FlatpakEscapeFlags flags)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(GString) res = g_string_new ("");
|
||||||
|
+ gboolean did_escape = FALSE;
|
||||||
|
+
|
||||||
|
+ while (*s)
|
||||||
|
+ {
|
||||||
|
+ gunichar c = g_utf8_get_char_validated (s, -1);
|
||||||
|
+ if (c == (gunichar)-2 || c == (gunichar)-1)
|
||||||
|
+ {
|
||||||
|
+ /* Need to convert to unsigned first, to avoid negative chars becoming
|
||||||
|
+ huge gunichars. */
|
||||||
|
+ append_hex_escaped_character (res, (unsigned char)*s++);
|
||||||
|
+ did_escape = TRUE;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ else if (should_hex_escape (c, flags))
|
||||||
|
+ {
|
||||||
|
+ append_hex_escaped_character (res, c);
|
||||||
|
+ did_escape = TRUE;
|
||||||
|
+ }
|
||||||
|
+ else if (c == '\\' || (!(flags & FLATPAK_ESCAPE_DO_NOT_QUOTE) && c == '\''))
|
||||||
|
+ {
|
||||||
|
+ g_string_append_printf (res, "\\%c", (char) c);
|
||||||
|
+ did_escape = TRUE;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ g_string_append_unichar (res, c);
|
||||||
|
+
|
||||||
|
+ s = g_utf8_find_next_char (s, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (did_escape && !(flags & FLATPAK_ESCAPE_DO_NOT_QUOTE))
|
||||||
|
+ {
|
||||||
|
+ g_string_prepend_c (res, '\'');
|
||||||
|
+ g_string_append_c (res, '\'');
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return g_string_free (g_steal_pointer (&res), FALSE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+flatpak_print_escaped_string (const char *s,
|
||||||
|
+ FlatpakEscapeFlags flags)
|
||||||
|
+{
|
||||||
|
+ g_autofree char *escaped = flatpak_escape_string (s, flags);
|
||||||
|
+ g_print ("%s", escaped);
|
||||||
|
+}
|
||||||
|
diff --git a/tests/make-test-app.sh b/tests/make-test-app.sh
|
||||||
|
index 731160535c..125e97f6b5 100755
|
||||||
|
--- a/tests/make-test-app.sh
|
||||||
|
+++ b/tests/make-test-app.sh
|
||||||
|
@@ -40,6 +40,14 @@ required-flatpak=$REQUIRED_VERSION
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
+if [ x${INCLUDE_SPECIAL_CHARACTER-} != x ]; then
|
||||||
|
+TAB=$'\t'
|
||||||
|
+cat >> ${DIR}/metadata <<EOF
|
||||||
|
+[Environment]
|
||||||
|
+A=x${TAB}y
|
||||||
|
+EOF
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
cat >> ${DIR}/metadata <<EOF
|
||||||
|
[Extension $APP_ID.Locale]
|
||||||
|
directory=share/runtime/locale
|
||||||
|
diff --git a/tests/test-info.sh b/tests/test-info.sh
|
||||||
|
index 4a247bdb48..2158c11b10 100644
|
||||||
|
--- a/tests/test-info.sh
|
||||||
|
+++ b/tests/test-info.sh
|
||||||
|
@@ -6,9 +6,9 @@ set -euo pipefail
|
||||||
|
|
||||||
|
skip_revokefs_without_fuse
|
||||||
|
|
||||||
|
-echo "1..7"
|
||||||
|
+echo "1..8"
|
||||||
|
|
||||||
|
-setup_repo
|
||||||
|
+INCLUDE_SPECIAL_CHARACTER=1 setup_repo
|
||||||
|
install_repo
|
||||||
|
|
||||||
|
COMMIT=`${FLATPAK} ${U} info --show-commit org.test.Hello`
|
||||||
|
@@ -19,9 +19,17 @@ assert_file_has_content info "^app/org\.test\.Hello/$(flatpak --default-arch)/ma
|
||||||
|
|
||||||
|
ok "info -rcos"
|
||||||
|
|
||||||
|
+${FLATPAK} info --show-metadata org.test.Hello > info
|
||||||
|
+
|
||||||
|
+# CVE-2023-28101
|
||||||
|
+assert_file_has_content info "name=org\.test\.Hello"
|
||||||
|
+assert_file_has_content info "^A=x\\\\x09y"
|
||||||
|
+
|
||||||
|
+ok "info --show-metadata"
|
||||||
|
+
|
||||||
|
${FLATPAK} info --show-permissions org.test.Hello > info
|
||||||
|
|
||||||
|
-assert_file_empty info
|
||||||
|
+assert_file_has_content info "^A=x\\\\x09y"
|
||||||
|
|
||||||
|
ok "info --show-permissions"
|
||||||
|
|
||||||
|
diff --git a/tests/testcommon.c b/tests/testcommon.c
|
||||||
|
index 1d217c072a..daae5e4aac 100644
|
||||||
|
--- a/tests/testcommon.c
|
||||||
|
+++ b/tests/testcommon.c
|
||||||
|
@@ -1557,6 +1557,44 @@ test_dconf_paths (void)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+typedef struct {
|
||||||
|
+ const char *in;
|
||||||
|
+ FlatpakEscapeFlags flags;
|
||||||
|
+ const char *out;
|
||||||
|
+} EscapeData;
|
||||||
|
+
|
||||||
|
+static EscapeData escapes[] = {
|
||||||
|
+ {"abc def", FLATPAK_ESCAPE_DEFAULT, "abc def"},
|
||||||
|
+ {"やあ", FLATPAK_ESCAPE_DEFAULT, "やあ"},
|
||||||
|
+ {"\033[;1m", FLATPAK_ESCAPE_DEFAULT, "'\\x1B[;1m'"},
|
||||||
|
+ // non-printable U+061C
|
||||||
|
+ {"\u061C", FLATPAK_ESCAPE_DEFAULT, "'\\u061C'"},
|
||||||
|
+ // non-printable U+1343F
|
||||||
|
+ {"\xF0\x93\x90\xBF", FLATPAK_ESCAPE_DEFAULT, "'\\U0001343F'"},
|
||||||
|
+ // invalid utf-8
|
||||||
|
+ {"\xD8\1", FLATPAK_ESCAPE_DEFAULT, "'\\xD8\\x01'"},
|
||||||
|
+ {"\b \n abc ' \\", FLATPAK_ESCAPE_DEFAULT, "'\\x08 \\x0A abc \\' \\\\'"},
|
||||||
|
+ {"\b \n abc ' \\", FLATPAK_ESCAPE_DO_NOT_QUOTE, "\\x08 \\x0A abc ' \\\\"},
|
||||||
|
+ {"abc\tdef\n\033[;1m ghi\b", FLATPAK_ESCAPE_ALLOW_NEWLINES | FLATPAK_ESCAPE_DO_NOT_QUOTE,
|
||||||
|
+ "abc\\x09def\n\\x1B[;1m ghi\\x08"},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* CVE-2023-28101 */
|
||||||
|
+static void
|
||||||
|
+test_string_escape (void)
|
||||||
|
+{
|
||||||
|
+ gsize idx;
|
||||||
|
+
|
||||||
|
+ for (idx = 0; idx < G_N_ELEMENTS (escapes); idx++)
|
||||||
|
+ {
|
||||||
|
+ EscapeData *data = &escapes[idx];
|
||||||
|
+ g_autofree char *ret = NULL;
|
||||||
|
+
|
||||||
|
+ ret = flatpak_escape_string (data->in, data->flags);
|
||||||
|
+ g_assert_cmpstr (ret, ==, data->out);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
@@ -1585,6 +1623,7 @@ main (int argc, char *argv[])
|
||||||
|
g_test_add_func ("/common/dconf-app-id", test_dconf_app_id);
|
||||||
|
g_test_add_func ("/common/dconf-paths", test_dconf_paths);
|
||||||
|
g_test_add_func ("/common/decompose-ref", test_decompose);
|
||||||
|
+ g_test_add_func ("/common/string-escape", test_string_escape);
|
||||||
|
|
||||||
|
g_test_add_func ("/app/looks-like-branch", test_looks_like_branch);
|
||||||
|
g_test_add_func ("/app/columns", test_columns);
|
||||||
408
CVE-2023-28101-2.patch
Normal file
408
CVE-2023-28101-2.patch
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
From e88eedce76f79a5573df4fc38b344bbeaf7af024 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ryan Gonzalez <ryan.gonzalez@collabora.com>
|
||||||
|
Date: Sat, 4 Mar 2023 21:07:03 -0600
|
||||||
|
Subject: [PATCH] Reject paths given to --filesystem/--persist with special
|
||||||
|
characters
|
||||||
|
|
||||||
|
There isn't much in the way of legit reasons for this, but it's a
|
||||||
|
potential security footgun when displaying the text.
|
||||||
|
|
||||||
|
CVE-2023-28101, GHSA-h43h-fwqx-mpp8
|
||||||
|
|
||||||
|
Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
|
||||||
|
Co-authored-by: Simon McVittie <smcv@collabora.com>
|
||||||
|
---
|
||||||
|
common/flatpak-context.c | 36 ++++++++++++---
|
||||||
|
common/flatpak-utils-private.h | 3 ++
|
||||||
|
common/flatpak-utils.c | 40 ++++++++++++++++
|
||||||
|
tests/test-context.c | 84 ++++++++++++++++++++++++++++++++--
|
||||||
|
tests/testcommon.c | 41 +++++++++++++++--
|
||||||
|
5 files changed, 190 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/common/flatpak-context.c b/common/flatpak-context.c
|
||||||
|
index 9c506499a4..512a577f81 100644
|
||||||
|
--- a/common/flatpak-context.c
|
||||||
|
+++ b/common/flatpak-context.c
|
||||||
|
@@ -487,11 +487,17 @@ flatpak_context_apply_generic_policy (FlatpakContext *context,
|
||||||
|
g_ptr_array_free (new, FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
+
|
||||||
|
+static gboolean
|
||||||
|
flatpak_context_set_persistent (FlatpakContext *context,
|
||||||
|
- const char *path)
|
||||||
|
+ const char *path,
|
||||||
|
+ GError **error)
|
||||||
|
{
|
||||||
|
+ if (!flatpak_validate_path_characters (path, error))
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
g_hash_table_insert (context->persistent, g_strdup (path), GINT_TO_POINTER (1));
|
||||||
|
+ return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
@@ -853,6 +859,9 @@ flatpak_context_parse_filesystem (const char *filesystem_and_mode,
|
||||||
|
g_autofree char *filesystem = NULL;
|
||||||
|
char *slash;
|
||||||
|
|
||||||
|
+ if (!flatpak_validate_path_characters (filesystem_and_mode, error))
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
filesystem = parse_filesystem_flags (filesystem_and_mode, negated, mode_out, error);
|
||||||
|
if (filesystem == NULL)
|
||||||
|
return FALSE;
|
||||||
|
@@ -1484,8 +1493,7 @@ option_persist_cb (const gchar *option_name,
|
||||||
|
{
|
||||||
|
FlatpakContext *context = data;
|
||||||
|
|
||||||
|
- flatpak_context_set_persistent (context, value);
|
||||||
|
- return TRUE;
|
||||||
|
+ return flatpak_context_set_persistent (context, value, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean option_no_desktop_deprecated;
|
||||||
|
@@ -1677,11 +1685,24 @@ flatpak_context_load_metadata (FlatpakContext *context,
|
||||||
|
{
|
||||||
|
const char *fs = parse_negated (filesystems[i], &remove);
|
||||||
|
g_autofree char *filesystem = NULL;
|
||||||
|
+ g_autoptr(GError) local_error = NULL;
|
||||||
|
FlatpakFilesystemMode mode;
|
||||||
|
|
||||||
|
if (!flatpak_context_parse_filesystem (fs, remove,
|
||||||
|
- &filesystem, &mode, NULL))
|
||||||
|
- g_debug ("Unknown filesystem type %s", filesystems[i]);
|
||||||
|
+ &filesystem, &mode, &local_error))
|
||||||
|
+ {
|
||||||
|
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA))
|
||||||
|
+ {
|
||||||
|
+ /* Invalid characters, so just hard-fail. */
|
||||||
|
+ g_propagate_error (error, g_steal_pointer (&local_error));
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ g_debug ("Unknown filesystem type %s", filesystems[i]);
|
||||||
|
+ g_clear_error (&local_error);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert (mode == FLATPAK_FILESYSTEM_MODE_NONE || !remove);
|
||||||
|
@@ -1698,7 +1719,8 @@ flatpak_context_load_metadata (FlatpakContext *context,
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; persistent[i] != NULL; i++)
|
||||||
|
- flatpak_context_set_persistent (context, persistent[i]);
|
||||||
|
+ if (!flatpak_context_set_persistent (context, persistent[i], error))
|
||||||
|
+ return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_key_file_has_group (metakey, FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY))
|
||||||
|
diff --git a/common/flatpak-utils-private.h b/common/flatpak-utils-private.h
|
||||||
|
index c1282641f9..195023c20f 100644
|
||||||
|
--- a/common/flatpak-utils-private.h
|
||||||
|
+++ b/common/flatpak-utils-private.h
|
||||||
|
@@ -913,6 +913,9 @@ char * flatpak_escape_string (const char *s,
|
||||||
|
void flatpak_print_escaped_string (const char *s,
|
||||||
|
FlatpakEscapeFlags flags);
|
||||||
|
|
||||||
|
+gboolean flatpak_validate_path_characters (const char *path,
|
||||||
|
+ GError **error);
|
||||||
|
+
|
||||||
|
#define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
|
||||||
|
|
||||||
|
#endif /* __FLATPAK_UTILS_H__ */
|
||||||
|
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||||
|
index 0b91ae3f91..b562522e58 100644
|
||||||
|
--- a/common/flatpak-utils.c
|
||||||
|
+++ b/common/flatpak-utils.c
|
||||||
|
@@ -8641,6 +8641,14 @@ append_hex_escaped_character (GString *result,
|
||||||
|
g_string_append_printf (result, "\\U%08X", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static char *
|
||||||
|
+escape_character (gunichar c)
|
||||||
|
+{
|
||||||
|
+ g_autoptr(GString) res = g_string_new ("");
|
||||||
|
+ append_hex_escaped_character (res, c);
|
||||||
|
+ return g_string_free (g_steal_pointer (&res), FALSE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
char *
|
||||||
|
flatpak_escape_string (const char *s,
|
||||||
|
FlatpakEscapeFlags flags)
|
||||||
|
@@ -8691,3 +8699,35 @@ flatpak_print_escaped_string (const char *s,
|
||||||
|
g_autofree char *escaped = flatpak_escape_string (s, flags);
|
||||||
|
g_print ("%s", escaped);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+gboolean
|
||||||
|
+flatpak_validate_path_characters (const char *path,
|
||||||
|
+ GError **error)
|
||||||
|
+{
|
||||||
|
+ while (*path)
|
||||||
|
+ {
|
||||||
|
+ gunichar c = g_utf8_get_char_validated (path, -1);
|
||||||
|
+ if (c == (gunichar)-1 || c == (gunichar)-2)
|
||||||
|
+ {
|
||||||
|
+ /* Need to convert to unsigned first, to avoid negative chars becoming
|
||||||
|
+ huge gunichars. */
|
||||||
|
+ g_autofree char *escaped_char = escape_character ((unsigned char)*path);
|
||||||
|
+ g_autofree char *escaped = flatpak_escape_string (path, FLATPAK_ESCAPE_DEFAULT);
|
||||||
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||||
|
+ "Non-UTF8 byte %s in path %s", escaped_char, escaped);
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+ else if (!is_char_safe (c))
|
||||||
|
+ {
|
||||||
|
+ g_autofree char *escaped_char = escape_character (c);
|
||||||
|
+ g_autofree char *escaped = flatpak_escape_string (path, FLATPAK_ESCAPE_DEFAULT);
|
||||||
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||||
|
+ "Non-graphical character %s in path %s", escaped_char, escaped);
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ path = g_utf8_find_next_char (path, NULL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return TRUE;
|
||||||
|
+}
|
||||||
|
diff --git a/tests/test-context.c b/tests/test-context.c
|
||||||
|
index c128a83fae..6c15feb013 100644
|
||||||
|
--- a/tests/test-context.c
|
||||||
|
+++ b/tests/test-context.c
|
||||||
|
@@ -34,13 +34,14 @@ str_has_prefix (gconstpointer candidate,
|
||||||
|
}
|
||||||
|
|
||||||
|
static void context_parse_args (FlatpakContext *context,
|
||||||
|
+ GError **error,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
static void
|
||||||
|
context_parse_args (FlatpakContext *context,
|
||||||
|
+ GError **error,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
- g_autoptr(GError) local_error = NULL;
|
||||||
|
g_autoptr(GOptionContext) oc = NULL;
|
||||||
|
g_autoptr(GOptionGroup) group = NULL;
|
||||||
|
g_autoptr(GPtrArray) args = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
@@ -50,7 +51,7 @@ context_parse_args (FlatpakContext *context,
|
||||||
|
|
||||||
|
g_ptr_array_add (args, g_strdup ("argv[0]"));
|
||||||
|
|
||||||
|
- va_start (ap, context);
|
||||||
|
+ va_start (ap, error);
|
||||||
|
|
||||||
|
while ((arg = va_arg (ap, const char *)) != NULL)
|
||||||
|
g_ptr_array_add (args, g_strdup (arg));
|
||||||
|
@@ -63,8 +64,7 @@ context_parse_args (FlatpakContext *context,
|
||||||
|
oc = g_option_context_new ("");
|
||||||
|
group = flatpak_context_get_options (context);
|
||||||
|
g_option_context_add_group (oc, group);
|
||||||
|
- g_option_context_parse_strv (oc, &argv, &local_error);
|
||||||
|
- g_assert_no_error (local_error);
|
||||||
|
+ g_option_context_parse_strv (oc, &argv, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -84,19 +84,26 @@ test_context_merge_fs (void)
|
||||||
|
g_autoptr(FlatpakContext) lowest = flatpak_context_new ();
|
||||||
|
g_autoptr(FlatpakContext) middle = flatpak_context_new ();
|
||||||
|
g_autoptr(FlatpakContext) highest = flatpak_context_new ();
|
||||||
|
+ g_autoptr(GError) local_error = NULL;
|
||||||
|
gpointer value;
|
||||||
|
|
||||||
|
context_parse_args (lowest,
|
||||||
|
+ &local_error,
|
||||||
|
"--filesystem=/one",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
context_parse_args (middle,
|
||||||
|
+ &local_error,
|
||||||
|
"--nofilesystem=host:reset",
|
||||||
|
"--filesystem=/two",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
context_parse_args (highest,
|
||||||
|
+ &local_error,
|
||||||
|
"--nofilesystem=host",
|
||||||
|
"--filesystem=/three",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, NULL));
|
||||||
|
g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, NULL));
|
||||||
|
@@ -178,20 +185,28 @@ test_context_merge_fs (void)
|
||||||
|
gpointer value;
|
||||||
|
|
||||||
|
context_parse_args (lowest,
|
||||||
|
+ &local_error,
|
||||||
|
"--filesystem=/one",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
context_parse_args (mid_low,
|
||||||
|
+ &local_error,
|
||||||
|
"--nofilesystem=host:reset",
|
||||||
|
"--filesystem=/two",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
context_parse_args (mid_high,
|
||||||
|
+ &local_error,
|
||||||
|
"--filesystem=host",
|
||||||
|
"--filesystem=/three",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
context_parse_args (highest,
|
||||||
|
+ &local_error,
|
||||||
|
"--nofilesystem=host",
|
||||||
|
"--filesystem=/four",
|
||||||
|
NULL);
|
||||||
|
+ g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host", NULL, NULL));
|
||||||
|
g_assert_false (g_hash_table_lookup_extended (lowest->filesystems, "host-reset", NULL, NULL));
|
||||||
|
@@ -332,12 +347,73 @@ test_context_merge_fs (void)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+const char *invalid_path_args[] = {
|
||||||
|
+ "--filesystem=/\033[J:ro",
|
||||||
|
+ "--filesystem=/\033[J",
|
||||||
|
+ "--persist=\033[J",
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* CVE-2023-28101 */
|
||||||
|
+static void
|
||||||
|
+test_validate_path_args (void)
|
||||||
|
+{
|
||||||
|
+ gsize idx;
|
||||||
|
+
|
||||||
|
+ for (idx = 0; idx < G_N_ELEMENTS (invalid_path_args); idx++)
|
||||||
|
+ {
|
||||||
|
+ g_autoptr(FlatpakContext) context = flatpak_context_new ();
|
||||||
|
+ g_autoptr(GError) local_error = NULL;
|
||||||
|
+ const char *path = invalid_path_args[idx];
|
||||||
|
+
|
||||||
|
+ context_parse_args (context, &local_error, path, NULL);
|
||||||
|
+ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
|
||||||
|
+ g_assert (strstr (local_error->message, "Non-graphical character"));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ const char *key;
|
||||||
|
+ const char *value;
|
||||||
|
+} PathValidityData;
|
||||||
|
+
|
||||||
|
+PathValidityData invalid_path_meta[] = {
|
||||||
|
+ {FLATPAK_METADATA_KEY_FILESYSTEMS, "\033[J"},
|
||||||
|
+ {FLATPAK_METADATA_KEY_PERSISTENT, "\033[J"},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* CVE-2023-28101 */
|
||||||
|
+static void
|
||||||
|
+test_validate_path_meta (void)
|
||||||
|
+{
|
||||||
|
+ gsize idx;
|
||||||
|
+
|
||||||
|
+ for (idx = 0; idx < G_N_ELEMENTS (invalid_path_meta); idx++)
|
||||||
|
+ {
|
||||||
|
+ g_autoptr(FlatpakContext) context = flatpak_context_new ();
|
||||||
|
+ g_autoptr(GKeyFile) metakey = g_key_file_new ();
|
||||||
|
+ g_autoptr(GError) local_error = NULL;
|
||||||
|
+ PathValidityData *data = &invalid_path_meta[idx];
|
||||||
|
+ gboolean ret = FALSE;
|
||||||
|
+
|
||||||
|
+ g_key_file_set_string_list (metakey, FLATPAK_METADATA_GROUP_CONTEXT,
|
||||||
|
+ data->key, &data->value, 1);
|
||||||
|
+
|
||||||
|
+ ret = flatpak_context_load_metadata (context, metakey, &local_error);
|
||||||
|
+ g_assert_false (ret);
|
||||||
|
+ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
|
||||||
|
+ g_assert (strstr (local_error->message, "Non-graphical character"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_func ("/context/merge-fs", test_context_merge_fs);
|
||||||
|
+ g_test_add_func ("/context/validate-path-args", test_validate_path_args);
|
||||||
|
+ g_test_add_func ("/context/validate-path-meta", test_validate_path_meta);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
||||||
|
diff --git a/tests/testcommon.c b/tests/testcommon.c
|
||||||
|
index daae5e4aac..0840632575 100644
|
||||||
|
--- a/tests/testcommon.c
|
||||||
|
+++ b/tests/testcommon.c
|
||||||
|
@@ -1567,11 +1567,12 @@ static EscapeData escapes[] = {
|
||||||
|
{"abc def", FLATPAK_ESCAPE_DEFAULT, "abc def"},
|
||||||
|
{"やあ", FLATPAK_ESCAPE_DEFAULT, "やあ"},
|
||||||
|
{"\033[;1m", FLATPAK_ESCAPE_DEFAULT, "'\\x1B[;1m'"},
|
||||||
|
- // non-printable U+061C
|
||||||
|
+ /* U+061C ARABIC LETTER MARK, non-printable */
|
||||||
|
{"\u061C", FLATPAK_ESCAPE_DEFAULT, "'\\u061C'"},
|
||||||
|
- // non-printable U+1343F
|
||||||
|
+ /* U+1343F EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE, non-printable and
|
||||||
|
+ * outside BMP */
|
||||||
|
{"\xF0\x93\x90\xBF", FLATPAK_ESCAPE_DEFAULT, "'\\U0001343F'"},
|
||||||
|
- // invalid utf-8
|
||||||
|
+ /* invalid utf-8 */
|
||||||
|
{"\xD8\1", FLATPAK_ESCAPE_DEFAULT, "'\\xD8\\x01'"},
|
||||||
|
{"\b \n abc ' \\", FLATPAK_ESCAPE_DEFAULT, "'\\x08 \\x0A abc \\' \\\\'"},
|
||||||
|
{"\b \n abc ' \\", FLATPAK_ESCAPE_DO_NOT_QUOTE, "\\x08 \\x0A abc ' \\\\"},
|
||||||
|
@@ -1595,6 +1596,39 @@ test_string_escape (void)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+typedef struct {
|
||||||
|
+ const char *path;
|
||||||
|
+ gboolean ret;
|
||||||
|
+} PathValidityData;
|
||||||
|
+
|
||||||
|
+static PathValidityData paths[] = {
|
||||||
|
+ {"/a/b/../c.def", TRUE},
|
||||||
|
+ {"やあ", TRUE},
|
||||||
|
+ /* U+061C ARABIC LETTER MARK, non-printable */
|
||||||
|
+ {"\u061C", FALSE},
|
||||||
|
+ /* U+1343F EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE, non-printable and
|
||||||
|
+ * outside BMP */
|
||||||
|
+ {"\xF0\x93\x90\xBF", FALSE},
|
||||||
|
+ /* invalid utf-8 */
|
||||||
|
+ {"\xD8\1", FALSE},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* CVE-2023-28101 */
|
||||||
|
+static void
|
||||||
|
+test_validate_path_characters (void)
|
||||||
|
+{
|
||||||
|
+ gsize idx;
|
||||||
|
+
|
||||||
|
+ for (idx = 0; idx < G_N_ELEMENTS (paths); idx++)
|
||||||
|
+ {
|
||||||
|
+ PathValidityData *data = &paths[idx];
|
||||||
|
+ gboolean ret = FALSE;
|
||||||
|
+
|
||||||
|
+ ret = flatpak_validate_path_characters (data->path, NULL);
|
||||||
|
+ g_assert_cmpint (ret, ==, data->ret);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
@@ -1624,6 +1658,7 @@ main (int argc, char *argv[])
|
||||||
|
g_test_add_func ("/common/dconf-paths", test_dconf_paths);
|
||||||
|
g_test_add_func ("/common/decompose-ref", test_decompose);
|
||||||
|
g_test_add_func ("/common/string-escape", test_string_escape);
|
||||||
|
+ g_test_add_func ("/common/validate-path-characters", test_validate_path_characters);
|
||||||
|
|
||||||
|
g_test_add_func ("/app/looks-like-branch", test_looks_like_branch);
|
||||||
|
g_test_add_func ("/app/columns", test_columns);
|
||||||
85
backport-Fix-several-memory-leaks.patch
Normal file
85
backport-Fix-several-memory-leaks.patch
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
From b912053c6cc556f131465c1fd877d7bd0b433539 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Phaedrus Leeds <mwleeds@protonmail.com>
|
||||||
|
Date: Sun, 2 May 2021 21:53:02 -0500
|
||||||
|
Subject: [PATCH] Fix several memory leaks
|
||||||
|
|
||||||
|
(cherry picked from commit 404d7c6941baf63d1b3ccbe9ee9d34f3ff12f35f)
|
||||||
|
---
|
||||||
|
app/flatpak-builtins-document-export.c | 6 +++---
|
||||||
|
common/flatpak-dir.c | 7 ++++---
|
||||||
|
common/flatpak-utils.c | 1 +
|
||||||
|
portal/flatpak-portal.c | 2 +-
|
||||||
|
4 files changed, 9 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/app/flatpak-builtins-document-export.c b/app/flatpak-builtins-document-export.c
|
||||||
|
index 15f1ad1275..e701a826bb 100644
|
||||||
|
--- a/app/flatpak-builtins-document-export.c
|
||||||
|
+++ b/app/flatpak-builtins-document-export.c
|
||||||
|
@@ -90,8 +90,8 @@ flatpak_builtin_document_export (int argc, char **argv,
|
||||||
|
g_autofree char *dirname = NULL;
|
||||||
|
g_autofree char *doc_path = NULL;
|
||||||
|
XdpDbusDocuments *documents;
|
||||||
|
- int fd, fd_id;
|
||||||
|
- int i;
|
||||||
|
+ glnx_autofd int fd = -1;
|
||||||
|
+ int i, fd_id;
|
||||||
|
GUnixFDList *fd_list = NULL;
|
||||||
|
const char *doc_id;
|
||||||
|
struct stat stbuf;
|
||||||
|
@@ -173,7 +173,7 @@ flatpak_builtin_document_export (int argc, char **argv,
|
||||||
|
|
||||||
|
fd_list = g_unix_fd_list_new ();
|
||||||
|
fd_id = g_unix_fd_list_append (fd_list, fd, error);
|
||||||
|
- close (fd);
|
||||||
|
+ glnx_close_fd (&fd);
|
||||||
|
|
||||||
|
if (opt_noexist)
|
||||||
|
{
|
||||||
|
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
|
||||||
|
index 94a86f4afb..0724677b91 100644
|
||||||
|
--- a/common/flatpak-dir.c
|
||||||
|
+++ b/common/flatpak-dir.c
|
||||||
|
@@ -13690,14 +13690,15 @@ parse_ref_file (GKeyFile *keyfile,
|
||||||
|
collection_id = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||||
|
FLATPAK_REF_DEPLOY_COLLECTION_ID_KEY, NULL);
|
||||||
|
|
||||||
|
- if (collection_id == NULL || *collection_id == '\0')
|
||||||
|
+ if (collection_id != NULL && *collection_id == '\0')
|
||||||
|
+ g_clear_pointer (&collection_id, g_free);
|
||||||
|
+ if (collection_id == NULL)
|
||||||
|
{
|
||||||
|
collection_id = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
|
||||||
|
FLATPAK_REF_COLLECTION_ID_KEY, NULL);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
if (collection_id != NULL && *collection_id == '\0')
|
||||||
|
- collection_id = NULL;
|
||||||
|
+ g_clear_pointer (&collection_id, g_free);
|
||||||
|
|
||||||
|
if (collection_id != NULL && gpg_data == NULL)
|
||||||
|
return flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Collection ID requires GPG key to be provided"));
|
||||||
|
diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c
|
||||||
|
index 56cbb06db3..84bc6a398d 100644
|
||||||
|
--- a/common/flatpak-utils.c
|
||||||
|
+++ b/common/flatpak-utils.c
|
||||||
|
@@ -2235,6 +2235,7 @@ flatpak_parse_repofile (const char *remote_name,
|
||||||
|
decoded = g_base64_decode (gpg_key, &decoded_len);
|
||||||
|
if (decoded_len < 10) /* Check some minimal size so we don't get crap */
|
||||||
|
{
|
||||||
|
+ g_free (decoded);
|
||||||
|
flatpak_fail_error (error, FLATPAK_ERROR_INVALID_DATA, _("Invalid gpg key"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
diff --git a/portal/flatpak-portal.c b/portal/flatpak-portal.c
|
||||||
|
index 7887c57a3b..0539ff2d22 100644
|
||||||
|
--- a/portal/flatpak-portal.c
|
||||||
|
+++ b/portal/flatpak-portal.c
|
||||||
|
@@ -767,7 +767,7 @@ handle_spawn (PortalFlatpak *object,
|
||||||
|
const gint *fds = NULL;
|
||||||
|
gint fds_len = 0;
|
||||||
|
g_autofree FdMapEntry *fd_map = NULL;
|
||||||
|
- gchar **env;
|
||||||
|
+ g_auto(GStrv) env = NULL;
|
||||||
|
gint32 max_fd;
|
||||||
|
GKeyFile *app_info;
|
||||||
|
g_autoptr(GPtrArray) flatpak_argv = g_ptr_array_new_with_free_func (g_free);
|
||||||
21
flatpak.spec
21
flatpak.spec
@ -1,6 +1,6 @@
|
|||||||
Name: flatpak
|
Name: flatpak
|
||||||
Version: 1.10.2
|
Version: 1.10.2
|
||||||
Release: 5
|
Release: 7
|
||||||
Summary: Application deployment framework for desktop apps
|
Summary: Application deployment framework for desktop apps
|
||||||
License: LGPLv2+
|
License: LGPLv2+
|
||||||
URL: http://flatpak.org/
|
URL: http://flatpak.org/
|
||||||
@ -26,6 +26,19 @@ Patch6013: backport-0002-CVE-2021-43860.patch
|
|||||||
Patch6014: backport-0003-CVE-2021-43860.patch
|
Patch6014: backport-0003-CVE-2021-43860.patch
|
||||||
Patch6015: backport-0004-CVE-2021-43860.patch
|
Patch6015: backport-0004-CVE-2021-43860.patch
|
||||||
Patch6016: backport-0005-CVE-2021-43860.patch
|
Patch6016: backport-0005-CVE-2021-43860.patch
|
||||||
|
Patch6017: backport-Fix-several-memory-leaks.patch
|
||||||
|
# https://github.com/flatpak/flatpak/commit/4206d681c5c52691dec0074e3f8c32dab1953a94
|
||||||
|
Patch6018: CVE-2023-28100-pre1.patch
|
||||||
|
# https://github.com/flatpak/flatpak/commit/b83fb81d1a66fe4ea31fd9c36ca425705eaaca99
|
||||||
|
Patch6019: CVE-2023-28100-pre2.patch
|
||||||
|
# https://github.com/flatpak/flatpak/commit/e7880e25b9d400feeaacb82f115fae676ce6c65d
|
||||||
|
Patch6020: CVE-2023-28100-pre3.patch
|
||||||
|
# https://github.com/flatpak/flatpak/commit/a9bf18040cc075a70657c6090a59d7f6fe78f893
|
||||||
|
Patch6021: CVE-2023-28100.patch
|
||||||
|
# https://github.com/flatpak/flatpak/commit/acd627a2fabe9856947399044dbf7aa79247c75b
|
||||||
|
Patch6022: CVE-2023-28101-1.patch
|
||||||
|
# https://github.com/flatpak/flatpak/commit/e88eedce76f79a5573df4fc38b344bbeaf7af024
|
||||||
|
Patch6023: CVE-2023-28101-2.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(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)
|
BuildRequires: pkgconfig(libsoup-2.4) pkgconfig(libxml-2.0) >= 2.4 pkgconfig(ostree-1) >= 2020.8 pkgconfig(polkit-gobject-1) pkgconfig(libseccomp) pkgconfig(xau)
|
||||||
@ -131,6 +144,12 @@ flatpak remote-list --system &> /dev/null || :
|
|||||||
%{_mandir}/man5/flatpak-remote.5*
|
%{_mandir}/man5/flatpak-remote.5*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 28 2024 yaoxin <yao_xin001@hoperun.com> - 1.10.2-7
|
||||||
|
- Fix CVE-2023-28100 and CVE-2023-28101
|
||||||
|
|
||||||
|
* Tue Dec 26 2023 maokecheng <maokecheng@xfusion.com> - 1.10.2-6
|
||||||
|
- DESC:Fix several memory leaks
|
||||||
|
|
||||||
* Sat Jan 29 2022 dongyuzhen <dongyuzhen@h-partners.com> - 1.10.2-5
|
* Sat Jan 29 2022 dongyuzhen <dongyuzhen@h-partners.com> - 1.10.2-5
|
||||||
- Fix CVE-2021-43860
|
- Fix CVE-2021-43860
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user