Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian....@packages.debian.org
Usertags: pu
X-Debbugs-Cc: flat...@packages.debian.org
Control: affects -1 + src:flatpak

[ Reason ]
New upstream stable release fixing a security issue.

[ Impact ]
The same two CVEs that were fixed in 1.14.4-1 (#1033078), which the
security team have indicated are not going to get a DSA:

CVE-2023-28101: A malicious Flatpak app could prevent the flatpak(1) CLI
from displaying its permissions as intended, by having crafted permissions
or other metadata containing terminal escape sequences or other special
characters. (#1033098)

CVE-2023-28100: A malicious Flatpak app could execute code outside the
sandbox if run from a Linux virtual console. (#1033099)

Additionally, the new upstream stable release has some other bug fixes
backported from 1.12.x and 1.14.x for:
- temporary directories not being cleaned up if an upgrade is cancelled,
  in particular if it's blocked by parental controls (libmalcontent);
- the `flatpak history` command, which didn't previously work in bullseye;
- a build bug fix which isn't directly relevant to bullseye, but was
  necessary to get the upstream release out, and is harmless in bullseye

[ Tests ]
The automated test suite is run at build-time and by autopkgtest,
and still passes. It includes tests for the two CVE issues and the
`flatpak history` fixes. Coverage on buildds and lxc is not great,
because we're unable to actually run Flatpak apps in that environment,
but I ran the autopkgtest in autopkgtest-virt-qemu before upload (which
does get full coverage) and that also passes.

The new upstream stable release also adds unit test coverage for the
seccomp filter changes in previous security updates (CVE-2021-41133,
etc.), which were previously backported without automated tests.

A manual smoke-test on my partner's Debian 11 system was successful.

[ Risks ]
The security fixes are new, but are narrowly-targeted and seem rather safe.

The other changes have been in testing/unstable and in bullseye-backports
for a long time without regression reports.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
The attached debdiff has been filtered to remove Autotools noise. The
diffstat is unfiltered.

* app/flatpak-builtins-info.c, app/flatpak-builtins-remote-info.c,
  app/flatpak-cli-transaction.c, common/flatpak-context.c,
  common/flatpak-utils.c, common/flatpak-utils-private.h: CVE-2023-28101

* common/flatpak-run.c: CVE-2023-28100

* configure.ac, Makefile.am: unrelated bug fix for ability to compile with
  newer gpgme (unnecessary for bullseye, but necessary to get the
  upstream release out)

* app/flatpak-builtins-history.c, app/flatpak-main.c: unrelated bug fixes
  for `flatpak history` backported from the version in testing/unstable

* common/flatpak-dir.c: unrelated bug fix for a temporary directory not
  being cleaned up if an upgrade is cancelled

* tests: Test coverage for CVE-2023-28101, CVE-2023-28100, previous
  CVE fixes, and the history bugfix
debdiff *.dsc | filterdiff -p1 -xMakefile.in -x'*/Makefile.in' -xaclocal.m4 -xconfig.guess -xconfig.sub -xconfigure
-x'doc/reference/html/*.html' -xdoc/reference/html/style.css -xltmain.sh -x'm4/l*.m4' -x'po/*.po' -x'po/*.pot'

diffstat for flatpak-1.10.7 flatpak-1.10.8

 Makefile.am                                                                |    4 
 Makefile.in                                                                |   94 
 NEWS                                                                       |   36 
 aclocal.m4                                                                 |  193 
 app/flatpak-builtins-history.c                                             |   59 
 app/flatpak-builtins-info.c                                                |    8 
 app/flatpak-builtins-remote-info.c                                         |    5 
 app/flatpak-cli-transaction.c                                              |   12 
 app/flatpak-main.c                                                         |    5 
 common/flatpak-context.c                                                   |   36 
 common/flatpak-dir.c                                                       |   15 
 common/flatpak-ref-utils-private.h                                         |    1 
 common/flatpak-run.c                                                       |    4 
 common/flatpak-utils-private.h                                             |   14 
 common/flatpak-utils.c                                                     |  119 
 common/flatpak-version-macros.h                                            |    2 
 config.guess                                                               | 1502 +++--
 config.sub                                                                 | 2617 +++++-----
 configure                                                                  | 1152 +++-
 configure.ac                                                               |   16 
 debian/changelog                                                           |   26 
 debian/copyright                                                           |    2 
 doc/Makefile.in                                                            |    4 
 doc/reference/Makefile.in                                                  |    4 
 doc/reference/html/flatpak-Version-information.html                        |    2 
 doc/reference/html/gdbus-org.freedesktop.Flatpak.Authenticator.html        |  166 
 doc/reference/html/gdbus-org.freedesktop.Flatpak.AuthenticatorRequest.html |  107 
 doc/reference/html/gdbus-org.freedesktop.Flatpak.Development.html          |  160 
 doc/reference/html/gdbus-org.freedesktop.Flatpak.SessionHelper.html        |   56 
 doc/reference/html/gdbus-org.freedesktop.Flatpak.SystemHelper.html         |  513 +
 doc/reference/html/gdbus-org.freedesktop.impl.portal.PermissionStore.html  |  197 
 doc/reference/html/gdbus-org.freedesktop.portal.Documents.html             |  353 -
 doc/reference/html/gdbus-org.freedesktop.portal.Flatpak.UpdateMonitor.html |  143 
 doc/reference/html/gdbus-org.freedesktop.portal.Flatpak.html               |  359 -
 doc/reference/html/index.html                                              |    2 
 doc/reference/html/style.css                                               |   34 
 ltmain.sh                                                                  |  827 +--
 m4/libtool.m4                                                              |  229 
 m4/ltoptions.m4                                                            |    4 
 m4/ltsugar.m4                                                              |    2 
 m4/ltversion.m4                                                            |   13 
 m4/lt~obsolete.m4                                                          |    4 
 po/cs.po                                                                   |  294 -
 po/da.po                                                                   |  294 -
 po/de.po                                                                   |  294 -
 po/en_GB.po                                                                |  294 -
 po/es.po                                                                   |  294 -
 po/flatpak.pot                                                             |  296 -
 po/gl.po                                                                   |  294 -
 po/hr.po                                                                   |  298 -
 po/hu.po                                                                   |  294 -
 po/id.po                                                                   |  294 -
 po/oc.po                                                                   |  294 -
 po/pl.gmo                                                                  |binary
 po/pl.po                                                                   |  319 -
 po/pt_BR.po                                                                |  294 -
 po/ro.po                                                                   |  294 -
 po/ru.po                                                                   |  298 -
 po/sk.po                                                                   |  294 -
 po/sv.po                                                                   |  294 -
 po/tr.po                                                                   |  294 -
 po/uk.po                                                                   |  298 -
 po/zh_TW.po                                                                |  298 -
 tests/Makefile-test-matrix.am.inc                                          |    2 
 tests/Makefile.am.inc                                                      |   16 
 tests/make-test-app.sh                                                     |    8 
 tests/package_version.txt                                                  |    2 
 tests/test-context.c                                                       |   84 
 tests/test-history.sh                                                      |   62 
 tests/test-info.sh                                                         |   14 
 tests/test-seccomp.sh                                                      |  100 
 tests/testcommon.c                                                         |   74 
 tests/try-syscall.c                                                        |  182 
 73 files changed, 9267 insertions(+), 6301 deletions(-)

diff -Nru flatpak-1.10.7/app/flatpak-builtins-history.c flatpak-1.10.8/app/flatpak-builtins-history.c
--- flatpak-1.10.7/app/flatpak-builtins-history.c	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/app/flatpak-builtins-history.c	2022-02-09 16:34:19.000000000 +0000
@@ -160,16 +160,34 @@
     while ((reverse && sd_journal_previous (j) > 0) ||
            (!reverse && sd_journal_next (j) > 0))
       {
+        g_autofree char *ref_str = NULL;
+        g_autofree char *remote = NULL;
+
         /* determine whether to skip this entry */
 
+        ref_str = get_field (j, "REF", error);
+        if (*error)
+          return FALSE;
+
+        /* Appstream pulls are probably not interesting, and they are confusing
+         * since by default we include the Application column which shows up blank.
+         */
+        if (ref_str && ref_str[0] && g_str_has_prefix (ref_str, "appstream"))
+          continue;
+
+        remote = get_field (j, "REMOTE", error);
+        if (*error)
+          return FALSE;
+
+        /* Exclude pull to temp repo */
+        if (remote && remote[0] == '/')
+          continue;
+
         if (dirs)
           {
             gboolean include = FALSE;
             g_autofree char *installation = get_field (j, "INSTALLATION", NULL);
 
-            if (installation && installation[0] == '/')
-              include = TRUE; /* pull to a temp repo */
-
             for (i = 0; i < dirs->len && !include; i++)
               {
                 g_autofree char *name = flatpak_dir_get_name (dirs->pdata[i]);
@@ -217,24 +235,24 @@
                      strcmp (columns[k].name, "arch") == 0 ||
                      strcmp (columns[k].name, "branch") == 0)
               {
-                g_autoptr(FlatpakDecomposed) ref = NULL;
-                g_autofree char *ref_str = get_field (j, "REF", error);
-                if (*error)
-                  return FALSE;
+                g_autofree char *value = NULL;
 
-                if (ref_str)
-                  {
-                    ref = flatpak_decomposed_new_from_ref (ref_str, error);
-                    if (ref == NULL)
-                      return FALSE;
-                  }
+                if (ref_str && ref_str[0] &&
+                    !is_flatpak_ref (ref_str) &&
+                    g_strcmp0 (ref_str, OSTREE_REPO_METADATA_REF) != 0)
+                  g_warning ("Unknown ref in history: %s", ref_str);
 
                 if (strcmp (columns[k].name, "ref") == 0)
-                  flatpak_table_printer_add_column (printer, ref_str);
-                else
+                  value = g_strdup (ref_str);
+                else if (ref_str && ref_str[0] &&
+                         (g_str_has_prefix (ref_str, "app/") ||
+                          g_str_has_prefix (ref_str, "runtime/")))
                   {
-                    g_autofree char *value = NULL;
-                    if (ref)
+                    g_autoptr(FlatpakDecomposed) ref = NULL;
+                    ref = flatpak_decomposed_new_from_ref (ref_str, NULL);
+                    if (ref == NULL)
+                      g_warning ("Invalid ref in history: %s", ref_str);
+                    else
                       {
                         if (strcmp (columns[k].name, "application") == 0)
                           value = flatpak_decomposed_dup_id (ref);
@@ -243,9 +261,9 @@
                         else
                           value = flatpak_decomposed_dup_branch (ref);
                       }
-
-                    flatpak_table_printer_add_column (printer, value);
                   }
+
+                  flatpak_table_printer_add_column (printer, value);
               }
             else if (strcmp (columns[k].name, "installation") == 0)
               {
@@ -256,9 +274,6 @@
               }
             else if (strcmp (columns[k].name, "remote") == 0)
               {
-                g_autofree char *remote = get_field (j, "REMOTE", error);
-                if (*error)
-                  return FALSE;
                 flatpak_table_printer_add_column (printer, remote);
               }
             else if (strcmp (columns[k].name, "commit") == 0)
diff -Nru flatpak-1.10.7/app/flatpak-builtins-info.c flatpak-1.10.8/app/flatpak-builtins-info.c
--- flatpak-1.10.7/app/flatpak-builtins-info.c	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/app/flatpak-builtins-info.c	2023-03-15 17:29:33.000000000 +0000
@@ -400,7 +400,9 @@
           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 @@
               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 -Nru flatpak-1.10.7/app/flatpak-builtins-remote-info.c flatpak-1.10.8/app/flatpak-builtins-remote-info.c
--- flatpak-1.10.7/app/flatpak-builtins-remote-info.c	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/app/flatpak-builtins-remote-info.c	2023-03-15 17:29:33.000000000 +0000
@@ -441,7 +441,10 @@
 
           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 -Nru flatpak-1.10.7/app/flatpak-cli-transaction.c flatpak-1.10.8/app/flatpak-cli-transaction.c
--- flatpak-1.10.7/app/flatpak-cli-transaction.c	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/app/flatpak-cli-transaction.c	2023-03-15 17:29:33.000000000 +0000
@@ -894,12 +894,16 @@
                  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 @@
         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 -Nru flatpak-1.10.7/app/flatpak-main.c flatpak-1.10.8/app/flatpak-main.c
--- flatpak-1.10.7/app/flatpak-main.c	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/app/flatpak-main.c	2022-02-09 16:34:19.000000000 +0000
@@ -817,10 +817,11 @@
     check_environment ();
 
   /* Don't talk to dbus in enter, as it must be thread-free to setns, also
-     skip run/build for performance reasons (no need to connect to dbus). */
+     skip run/build/history for performance reasons (no need to connect to dbus). */
   if (g_strcmp0 (command->name, "enter") != 0 &&
       g_strcmp0 (command->name, "run") != 0 &&
-      g_strcmp0 (command->name, "build") != 0)
+      g_strcmp0 (command->name, "build") != 0 &&
+      g_strcmp0 (command->name, "history") != 0)
     polkit_agent = install_polkit_agent ();
 
   /* g_vfs_get_default can spawn threads */
diff -Nru flatpak-1.10.7/common/flatpak-context.c flatpak-1.10.8/common/flatpak-context.c
--- flatpak-1.10.7/common/flatpak-context.c	2022-01-18 15:50:17.000000000 +0000
+++ flatpak-1.10.8/common/flatpak-context.c	2023-03-16 09:55:42.000000000 +0000
@@ -487,11 +487,17 @@
                        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 @@
   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 @@
 {
   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 @@
         {
           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 @@
         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 -Nru flatpak-1.10.7/common/flatpak-dir.c flatpak-1.10.8/common/flatpak-dir.c
--- flatpak-1.10.7/common/flatpak-dir.c	2022-01-12 19:23:42.000000000 +0000
+++ flatpak-1.10.8/common/flatpak-dir.c	2023-03-15 11:18:22.000000000 +0000
@@ -8106,6 +8106,7 @@
   g_autofree char *ref_id = NULL;
   g_autoptr(GFile) root = NULL;
   g_autoptr(GFile) deploy_base = NULL;
+  glnx_autofd int deploy_base_dfd = -1;
   g_autoptr(GFile) checkoutdir = NULL;
   g_autoptr(GFile) bindir = NULL;
   g_autofree char *checkoutdirpath = NULL;
@@ -8122,8 +8123,6 @@
   OstreeRepoCheckoutAtOptions options = { 0, };
   const char *checksum;
   glnx_autofd int checkoutdir_dfd = -1;
-  g_autoptr(GFile) tmp_dir_template = NULL;
-  g_autofree char *tmp_dir_path = NULL;
   const char *xa_ref = NULL;
   g_autofree char *checkout_basename = NULL;
   gboolean created_extra_data = FALSE;
@@ -8132,6 +8131,7 @@
   g_autoptr(GFile) metadata_file = NULL;
   g_autofree char *metadata_contents = NULL;
   gsize metadata_size = 0;
+  g_auto(GLnxTmpDir) tmp_dir_handle = { 0, };
 
   if (!flatpak_dir_ensure_repo (self, cancellable, error))
     return FALSE;
@@ -8146,6 +8146,9 @@
 
   deploy_base = flatpak_dir_get_deploy_dir (self, ref);
 
+  if (!glnx_opendirat (AT_FDCWD, flatpak_file_get_path_cached (deploy_base), TRUE, &deploy_base_dfd, error))
+    return FALSE;
+
   if (checksum_or_latest == NULL)
     {
       g_debug ("No checksum specified, getting tip of %s from origin %s", flatpak_decomposed_get_ref (ref), origin);
@@ -8180,17 +8183,15 @@
                                _("%s commit %s already installed"), flatpak_decomposed_get_ref (ref), checksum);
 
   g_autofree char *template = g_strdup_printf (".%s-XXXXXX", checkout_basename);
-  tmp_dir_template = g_file_get_child (deploy_base, template);
-  tmp_dir_path = g_file_get_path (tmp_dir_template);
 
-  if (g_mkdtemp_full (tmp_dir_path, 0755) == NULL)
+  if (!glnx_mkdtempat (deploy_base_dfd, template, 0755, &tmp_dir_handle, NULL))
     {
       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                            _("Can't create deploy directory"));
       return FALSE;
     }
 
-  checkoutdir = g_file_new_for_path (tmp_dir_path);
+  checkoutdir = g_file_get_child (deploy_base, tmp_dir_handle.path);
 
   if (!ostree_repo_read_commit (self->repo, checksum, &root, NULL, cancellable, error))
     {
@@ -8487,6 +8488,8 @@
                     cancellable, NULL, NULL, error))
     return FALSE;
 
+  glnx_tmpdir_unset (&tmp_dir_handle);
+
   if (!flatpak_dir_set_active (self, ref, checkout_basename, cancellable, error))
     return FALSE;
 
diff -Nru flatpak-1.10.7/common/flatpak-ref-utils-private.h flatpak-1.10.8/common/flatpak-ref-utils-private.h
--- flatpak-1.10.7/common/flatpak-ref-utils-private.h	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/common/flatpak-ref-utils-private.h	2022-02-09 16:34:19.000000000 +0000
@@ -43,6 +43,7 @@
 gboolean flatpak_id_has_subref_suffix (const char *id,
                                        gssize      id_len);
 
+gboolean is_flatpak_ref (const char *ref);
 char * flatpak_get_arch_for_ref (const char *ref);
 const char *flatpak_get_compat_arch_reverse (const char *compat_arch);
 
diff -Nru flatpak-1.10.7/common/flatpak-run.c flatpak-1.10.8/common/flatpak-run.c
--- flatpak-1.10.7/common/flatpak-run.c	2021-10-11 14:04:46.000000000 +0100
+++ flatpak-1.10.8/common/flatpak-run.c	2023-03-16 09:55:42.000000000 +0000
@@ -2872,6 +2872,10 @@
 
     /* 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 -Nru flatpak-1.10.7/common/flatpak-utils.c flatpak-1.10.8/common/flatpak-utils.c
--- flatpak-1.10.7/common/flatpak-utils.c	2022-01-12 19:23:42.000000000 +0000
+++ flatpak-1.10.8/common/flatpak-utils.c	2023-03-16 09:55:42.000000000 +0000
@@ -3162,7 +3162,7 @@
 }
 
 
-static gboolean
+gboolean
 is_flatpak_ref (const char *ref)
 {
   return
@@ -8613,4 +8613,121 @@
   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);
+}
+
+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)
+{
+  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);
+}
 
+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 -Nru flatpak-1.10.7/common/flatpak-utils-private.h flatpak-1.10.8/common/flatpak-utils-private.h
--- flatpak-1.10.7/common/flatpak-utils-private.h	2021-07-20 11:03:24.000000000 +0100
+++ flatpak-1.10.8/common/flatpak-utils-private.h	2023-03-16 09:55:42.000000000 +0000
@@ -902,6 +902,20 @@
   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);
+
+gboolean flatpak_validate_path_characters (const char *path,
+                                           GError    **error);
+
 #define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
 
 #endif /* __FLATPAK_UTILS_H__ */
diff -Nru flatpak-1.10.7/common/flatpak-version-macros.h flatpak-1.10.8/common/flatpak-version-macros.h
--- flatpak-1.10.7/common/flatpak-version-macros.h	2022-01-18 17:35:08.000000000 +0000
+++ flatpak-1.10.8/common/flatpak-version-macros.h	2023-03-16 09:56:30.000000000 +0000
@@ -45,7 +45,7 @@
  *
  * The micro version.
  */
-#define FLATPAK_MICRO_VERSION (7)
+#define FLATPAK_MICRO_VERSION (8)
 
 /**
  * FLATPAK_CHECK_VERSION:
diff -Nru flatpak-1.10.7/configure.ac flatpak-1.10.8/configure.ac
--- flatpak-1.10.7/configure.ac	2022-01-18 17:34:14.000000000 +0000
+++ flatpak-1.10.8/configure.ac	2023-03-16 09:55:42.000000000 +0000
@@ -15,7 +15,7 @@
 
 m4_define([flatpak_major_version], [1])
 m4_define([flatpak_minor_version], [10])
-m4_define([flatpak_micro_version], [7])
+m4_define([flatpak_micro_version], [8])
 m4_define([flatpak_extra_version], [])
 m4_define([flatpak_interface_age], [0])
 m4_define([flatpak_binary_age],
@@ -260,10 +260,16 @@
 LIBS=$save_LIBS
 
 LIBGPGME_DEPENDENCY="1.1.8"
-PKG_CHECK_MODULES(DEP_GPGME, gpgme-pthread >= $LIBGPGME_DEPENDENCY, have_gpgme=yes, [
-    m4_ifdef([AM_PATH_GPGME_PTHREAD], [
-       AM_PATH_GPGME_PTHREAD($LIBGPGME_DEPENDENCY, have_gpgme=yes, have_gpgme=no)
-    ],[ have_gpgme=no ])
+PKG_CHECK_MODULES([DEP_GPGME], [gpgme >= 1.8.0], [have_gpgme=yes], [
+    PKG_CHECK_MODULES([DEP_GPGME_PTHREAD], [gpgme-pthread >= $LIBGPGME_DEPENDENCY], [
+        have_gpgme=yes
+    ], [
+        m4_ifdef([AM_PATH_GPGME_PTHREAD], [
+            AM_PATH_GPGME_PTHREAD([$LIBGPGME_DEPENDENCY], [have_gpgme=yes], [have_gpgme=no])
+        ], [
+            have_gpgme=no
+        ])
+    ])
 ])
 AS_IF([ test x$have_gpgme = xno ], [
    AC_MSG_ERROR([Need GPGME_PTHREAD version $LIBGPGME_DEPENDENCY or later])
diff -Nru flatpak-1.10.7/debian/changelog flatpak-1.10.8/debian/changelog
--- flatpak-1.10.7/debian/changelog	2022-01-18 18:24:45.000000000 +0000
+++ flatpak-1.10.8/debian/changelog	2023-03-18 15:29:44.000000000 +0000
@@ -1,3 +1,29 @@
+flatpak (1.10.8-0+deb11u1) bullseye; urgency=high
+
+  * New upstream stable release
+  * Security fixes:
+    - Escape special characters when displaying permissions and metadata,
+      preventing malicious apps from manipulating the appearance of the
+      permissions list using crafted metadata
+      (Closes: #1033098; CVE-2023-28101)
+    - If a Flatpak app is run on a Linux virtual console (tty1, etc.),
+      don't allow copy/paste via the TIOCLINUX ioctl
+      (Closes: #1033099; CVE-2023-28100).
+      Note that this is specific to virtual consoles: Flatpak is not
+      vulnerable to this if run from a graphical terminal emulator such
+      as xterm, gnome-terminal or Konsole.
+  * Other bug fixes:
+    - If an app update is blocked by parental controls policies, clean up
+      the temporary deploy directory
+    - Fix Autotools build with newer versions of gpgme
+    - Fix various regressions in `flatpak history` since 1.9.1
+    - Fix a typo in an error message
+    - Translation update: pl
+    - Add test coverage for seccomp filters
+  * d/copyright: Update
+
+ -- Simon McVittie <s...@debian.org>  Sat, 18 Mar 2023 15:29:44 +0000
+
 flatpak (1.10.7-0+deb11u1) bullseye-security; urgency=high
 
   * New upstream stable release
diff -Nru flatpak-1.10.7/debian/copyright flatpak-1.10.8/debian/copyright
--- flatpak-1.10.7/debian/copyright	2022-01-18 18:24:45.000000000 +0000
+++ flatpak-1.10.8/debian/copyright	2023-03-18 15:29:44.000000000 +0000
@@ -25,6 +25,8 @@
  © 2018-2019 Endless Mobile, Inc.
  © 2019 Matthias Clasen
  © 2019-2021 Matthew Leeds
+ © 2021 Simon McVittie
+ © 2021 Collabora Ltd.
 License: LGPL-2+ and LGPL-2.1+
 
 Files:
diff -Nru flatpak-1.10.7/Makefile.am flatpak-1.10.8/Makefile.am
--- flatpak-1.10.7/Makefile.am	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/Makefile.am	2023-03-15 11:18:57.000000000 +0000
@@ -84,8 +84,8 @@
 	$(NULL)
 
 # This canonicalizes the PKG_CHECK_MODULES or AM_PATH_GPGME results
-INTERNAL_GPGME_CFLAGS = $(DEP_GPGME_CFLAGS) $(GPGME_PTHREAD_CFLAGS)
-INTERNAL_GPGME_LIBS = $(DEP_GPGME_LIBS) $(GPGME_PTHREAD_LIBS)
+INTERNAL_GPGME_CFLAGS = $(DEP_GPGME_CFLAGS) $(DEP_GPGME_PTHREAD_CFLAGS) $(GPGME_PTHREAD_CFLAGS)
+INTERNAL_GPGME_LIBS = $(DEP_GPGME_LIBS) $(DEP_GPGME_PTHREAD_LIBS) $(GPGME_PTHREAD_LIBS)
 
 lib_LTLIBRARIES =
 noinst_LTLIBRARIES += libglnx.la
diff -Nru flatpak-1.10.7/NEWS flatpak-1.10.8/NEWS
--- flatpak-1.10.7/NEWS	2022-01-18 17:33:33.000000000 +0000
+++ flatpak-1.10.8/NEWS	2023-03-16 09:55:42.000000000 +0000
@@ -1,6 +1,40 @@
+Changes in 1.10.8
+~~~~~~~~~~~~~~~~~
+Released: 2023-03-16
+
+Security fixes:
+
+ * Escape special characters when displaying permissions and metadata,
+   preventing malicious apps from manipulating the appearance of the
+   permissions list using crafted metadata (CVE-2023-28101).
+
+ * If a Flatpak app is run on a Linux virtual console (tty1, tty2, etc.),
+   don't allow copy/paste via the TIOCLINUX ioctl (CVE-2023-28100).
+   Note that this is specific to virtual consoles: Flatpak is not
+   vulnerable to this if run from a graphical terminal emulator such as
+   xterm, gnome-terminal or Konsole.
+
+Other bug fixes:
+
+ * If an app update is blocked by parental controls policies, clean up the
+   temporary deploy directory (#5146)
+ * Fix Autotools build with versions of gpgme that no longer provide
+   gpgme-config(1) (#5173)
+ * Fix regressions in `flatpak history` since 1.9.1
+   - Don't display the appstream branch used internally
+   - Don't display temporary repositories used internally
+   - Ignore transaction log entries with empty REF field
+   - Warn instead of failing if other non-app, non-runtime refs are found
+   - Don't set up an unnecessary polkit agent for `flatpak history`
+   - Add test coverage
+ * Fix a typo in an error message
+ * Fix incorrect year in NEWS for 1.10.7 release
+ * Translation update: pl
+ * Add test coverage for Flatpak's seccomp filters
+
 Changes in 1.10.7
 ~~~~~~~~~~~~~~~~~
-Released: 2021-01-18
+Released: 2022-01-18
 
 This is a regression fix update, reverting non-backwards-compatible
 behaviour changes in the solution previously chosen for CVE-2022-21682.
Binary files /tmp/QcUbTCPHhV/flatpak-1.10.7/po/pl.gmo and /tmp/iaJObc2LHL/flatpak-1.10.8/po/pl.gmo differ
diff -Nru flatpak-1.10.7/tests/Makefile.am.inc flatpak-1.10.8/tests/Makefile.am.inc
--- flatpak-1.10.7/tests/Makefile.am.inc	2022-01-18 16:01:53.000000000 +0000
+++ flatpak-1.10.8/tests/Makefile.am.inc	2023-03-15 12:06:07.000000000 +0000
@@ -99,6 +99,10 @@
 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)\"
@@ -218,6 +222,7 @@
 	tests/test-run.sh{{user+system+system-norevokefs},{nodeltas+deltas}} \
 	tests/test-info.sh{user+system} \
 	tests/test-repo.sh{{user+system+system-norevokefs}+{{user+system},oldsummary}} \
+	tests/test-history.sh \
 	tests/test-sideload.sh{user+system} \
 	tests/test-default-remotes.sh \
 	tests/test-metadata-validation.sh \
@@ -232,6 +237,7 @@
 	tests/test-unused.sh \
 	tests/test-summaries.sh{user+system} \
 	tests/test-subset.sh{user+system} \
+	tests/test-seccomp.sh \
 	$(NULL)
 
 update-test-matrix:
@@ -262,7 +268,15 @@
 	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 -Nru flatpak-1.10.7/tests/Makefile-test-matrix.am.inc flatpak-1.10.8/tests/Makefile-test-matrix.am.inc
--- flatpak-1.10.7/tests/Makefile-test-matrix.am.inc	2022-01-12 19:23:42.000000000 +0000
+++ flatpak-1.10.8/tests/Makefile-test-matrix.am.inc	2023-03-15 12:05:59.000000000 +0000
@@ -35,6 +35,7 @@
 	tests/test-config.sh \
 	tests/test-build-update-repo.sh \
 	tests/test-http-utils.sh \
+	tests/test-history.sh \
 	tests/test-default-remotes.sh \
 	tests/test-metadata-validation.sh \
 	tests/test-extensions.sh \
@@ -42,6 +43,7 @@
 	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 -Nru flatpak-1.10.7/tests/make-test-app.sh flatpak-1.10.8/tests/make-test-app.sh
--- flatpak-1.10.7/tests/make-test-app.sh	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/tests/make-test-app.sh	2023-03-15 17:29:33.000000000 +0000
@@ -40,6 +40,14 @@
 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 -Nru flatpak-1.10.7/tests/package_version.txt flatpak-1.10.8/tests/package_version.txt
--- flatpak-1.10.7/tests/package_version.txt	2022-01-18 17:40:24.000000000 +0000
+++ flatpak-1.10.8/tests/package_version.txt	2023-03-16 09:57:55.000000000 +0000
@@ -1 +1 @@
-1.10.7
+1.10.8
diff -Nru flatpak-1.10.7/tests/testcommon.c flatpak-1.10.8/tests/testcommon.c
--- flatpak-1.10.7/tests/testcommon.c	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/tests/testcommon.c	2023-03-16 09:55:42.000000000 +0000
@@ -1557,6 +1557,78 @@
     }
 }
 
+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'"},
+  /* U+061C ARABIC LETTER MARK, non-printable */
+  {"\u061C", FLATPAK_ESCAPE_DEFAULT, "'\\u061C'"},
+  /* U+1343F EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE, non-printable and
+   * outside BMP */
+  {"\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);
+    }
+}
+
+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[])
 {
@@ -1585,6 +1657,8 @@
   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 ("/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);
diff -Nru flatpak-1.10.7/tests/test-context.c flatpak-1.10.8/tests/test-context.c
--- flatpak-1.10.7/tests/test-context.c	2022-01-18 16:01:56.000000000 +0000
+++ flatpak-1.10.8/tests/test-context.c	2023-03-16 09:55:42.000000000 +0000
@@ -34,13 +34,14 @@
 }
 
 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 @@
 
   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 @@
   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 @@
       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 @@
       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 @@
     }
 }
 
+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 -Nru flatpak-1.10.7/tests/test-history.sh flatpak-1.10.8/tests/test-history.sh
--- flatpak-1.10.7/tests/test-history.sh	1970-01-01 01:00:00.000000000 +0100
+++ flatpak-1.10.8/tests/test-history.sh	2022-02-09 16:34:19.000000000 +0000
@@ -0,0 +1,62 @@
+#!/bin/bash
+# Copyright (C) 2021 Matthew Leeds <mwle...@protonmail.com>
+# SPDX-License-Identifier: LGPL-2.0-or-later
+
+set -euo pipefail
+
+USE_SYSTEMDIR=yes
+
+. $(dirname $0)/libtest.sh
+
+skip_without_bwrap
+skip_revokefs_without_fuse
+
+echo "1..1"
+
+HISTORY_START_TIME=$(date +"%Y-%m-%d %H:%M:%S")
+sleep 1
+
+mkdir -p ${TEST_DATA_DIR}/system-history-installation
+mkdir -p ${FLATPAK_CONFIG_DIR}/installations.d
+cat << EOF > ${FLATPAK_CONFIG_DIR}/installations.d/history-installation.conf
+[Installation "history-installation"]
+Path=${TEST_DATA_DIR}/system-history-installation
+EOF
+
+# setup repo and install from it
+setup_repo_no_add
+port=$(cat httpd-port)
+${FLATPAK} --installation=history-installation remote-add \
+    --gpg-import=${FL_GPG_HOMEDIR}/pubring.gpg test-repo "http://127.0.0.1:${port}/test";
+${FLATPAK} --installation=history-installation install -y test-repo org.test.Hello master
+
+# appstream update shouldn't show up in history
+${FLATPAK} ${U} --appstream update test-repo
+
+# update, uninstall, and remote-delete should show up
+EXPORT_ARGS="" make_updated_app
+${FLATPAK} --installation=history-installation update -y org.test.Hello
+${FLATPAK} --installation=history-installation uninstall -y org.test.Platform org.test.Hello
+${FLATPAK} --installation=history-installation remote-delete test-repo
+
+# need --since and --columns here to make the test idempotent
+${FLATPAK} --installation=history-installation history --since="${HISTORY_START_TIME}" \
+    --columns=change,application,branch,installation,remote > history-log 2>&1
+
+diff history-log - << EOF
+add remote			system (history-installation)	test-repo
+deploy install	org.test.Hello.Locale	master	system (history-installation)	test-repo
+deploy install	org.test.Platform	master	system (history-installation)	test-repo
+deploy install	org.test.Hello	master	system (history-installation)	test-repo
+deploy update	org.test.Hello.Locale	master	system (history-installation)	test-repo
+deploy update	org.test.Hello	master	system (history-installation)	test-repo
+uninstall	org.test.Hello	master	system (history-installation)
+uninstall	org.test.Platform	master	system (history-installation)
+uninstall	org.test.Hello.Locale	master	system (history-installation)
+remove remote			system (history-installation)	test-repo
+EOF
+
+rm -f ${FLATPAK_CONFIG_DIR}/installations.d/history-inst.conf
+rm -rf ${TEST_DATA_DIR}/system-history-installation
+
+ok "history looks correct"
diff -Nru flatpak-1.10.7/tests/test-info.sh flatpak-1.10.8/tests/test-info.sh
--- flatpak-1.10.7/tests/test-info.sh	2021-06-16 09:15:42.000000000 +0100
+++ flatpak-1.10.8/tests/test-info.sh	2023-03-16 09:55:41.000000000 +0000
@@ -6,9 +6,9 @@
 
 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 @@
 
 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 -Nru flatpak-1.10.7/tests/test-seccomp.sh flatpak-1.10.8/tests/test-seccomp.sh
--- flatpak-1.10.7/tests/test-seccomp.sh	1970-01-01 01:00:00.000000000 +0100
+++ flatpak-1.10.8/tests/test-seccomp.sh	2023-03-16 09:55:42.000000000 +0000
@@ -0,0 +1,100 @@
+#!/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..18"
+
+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 "# 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="$?"
+  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
diff -Nru flatpak-1.10.7/tests/try-syscall.c flatpak-1.10.8/tests/try-syscall.c
--- flatpak-1.10.7/tests/try-syscall.c	1970-01-01 01:00:00.000000000 +0100
+++ flatpak-1.10.8/tests/try-syscall.c	2023-03-16 09:55:42.000000000 +0000
@@ -0,0 +1,182 @@
+/*
+ * 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, "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 */
+          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;
+}

Reply via email to