[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1033078: unblock: flatpak/1.14.4-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: flatpak@packages.debian.org, security@debian.org
Control: affects -1 + src:flatpak

Please unblock package flatpak

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

[ Impact ]
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.

CVE-2023-28100: A malicious Flatpak app could execute code outside the
sandbox if run from a Linux virtual console. (Mitigation: I'm fairly
sure nobody actually does this, because Flatpak is intended to be used
in a Wayland or X11 environment; running it from an xterm or equivalent
is not vulnerable.)

[ Tests ]
The automated test suite is run at build-time and by autopkgtest, and
still passes. It includes tests for the two CVE issues. 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 qemu before upload and that
also passes.

[ Risks ]
Low risk, targeted fixes only. The only non-security change is a
translation update.

[ 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 testing

[ Other info ]
As with bullseye, I'm involved in upstream release management, and I'd
like to make use of upstream stable releases for stable/security updates
in preference to forking the upstream codebase for Debian.

unblock flatpak/1.14.4-1
debdiff *.dsc | filterdiff -p1 -x'po/*.po' -x 'po/*.pot' -xconfigure

diffstat for flatpak-1.14.3 flatpak-1.14.4

 NEWS                                                |   20 +
 app/flatpak-builtins-info.c                         |    8 
 app/flatpak-builtins-remote-info.c                  |    5 
 app/flatpak-cli-transaction.c                       |   17 -
 common/flatpak-context.c                            |   36 ++
 common/flatpak-run.c                                |    4 
 common/flatpak-utils-private.h                      |   14 +
 common/flatpak-utils.c                              |  121 +++++++++
 common/flatpak-version-macros.h                     |    2 
 configure                                           |   26 +-
 configure.ac                                        |    2 
 debian/changelog                                    |   15 +
 doc/reference/html/flatpak-Version-information.html |    2 
 doc/reference/html/index.html                       |    2 
 po/cs.po                                            |  204 ++++++++--------
 po/da.po                                            |  204 ++++++++--------
 po/de.po                                            |  204 ++++++++--------
 po/en_GB.po                                         |  204 ++++++++--------
 po/es.po                                            |  204 ++++++++--------
 po/flatpak.pot                                      |  206 ++++++++--------
 po/fr.po                                            |  204 ++++++++--------
 po/gl.po                                            |  204 ++++++++--------
 po/hi.po                                            |  204 ++++++++--------
 po/hr.po                                            |  204 ++++++++--------
 po/hu.po                                            |  204 ++++++++--------
 po/id.po                                            |  204 ++++++++--------
 po/oc.po                                            |  204 ++++++++--------
 po/pl.gmo                                           |binary
 po/pl.po                                            |  250 ++++++++++----------
 po/pt.po                                            |  204 ++++++++--------
 po/pt_BR.po                                         |  204 ++++++++--------
 po/ro.po                                            |  204 ++++++++--------
 po/ru.po                                            |  204 ++++++++--------
 po/sk.po                                            |  204 ++++++++--------
 po/sv.po                                            |  204 ++++++++--------
 po/tr.po                                            |  204 ++++++++--------
 po/uk.po                                            |  204 ++++++++--------
 po/zh_CN.po                                         |  204 ++++++++--------
 po/zh_TW.po                                         |  204 ++++++++--------
 tests/make-test-app.sh                              |    8 
 tests/package_version.txt                           |    2 
 tests/test-context.c                                |   84 ++++++
 tests/test-info.sh                                  |   14 -
 tests/test-seccomp.sh                               |    8 
 tests/testcommon.c                                  |   74 +++++
 tests/try-syscall.c                                 |    9 
 46 files changed, 2903 insertions(+), 2514 deletions(-)

diff -Nru flatpak-1.14.3/app/flatpak-builtins-info.c flatpak-1.14.4/app/flatpak-builtins-info.c
--- flatpak-1.14.3/app/flatpak-builtins-info.c	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/app/flatpak-builtins-info.c	2023-03-15 17:37:23.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.14.3/app/flatpak-builtins-remote-info.c flatpak-1.14.4/app/flatpak-builtins-remote-info.c
--- flatpak-1.14.3/app/flatpak-builtins-remote-info.c	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/app/flatpak-builtins-remote-info.c	2023-03-15 17:37:23.000000000 +0000
@@ -431,7 +431,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.14.3/app/flatpak-cli-transaction.c flatpak-1.14.4/app/flatpak-cli-transaction.c
--- flatpak-1.14.3/app/flatpak-cli-transaction.c	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/app/flatpak-cli-transaction.c	2023-03-16 09:55:13.000000000 +0000
@@ -755,6 +755,9 @@
     }
   else if (reason)
     {
+      g_autofree char *escaped_reason = flatpak_escape_string (reason,
+                                                               FLATPAK_ESCAPE_ALLOW_NEWLINES |
+                                                               FLATPAK_ESCAPE_DO_NOT_QUOTE);
       if (is_pinned)
         {
           /* Only runtimes can be pinned */
@@ -770,7 +773,7 @@
             g_print (_("\nInfo: app %s%s%s branch %s%s%s is end-of-life, with reason:\n"),
                      on, ref_name, off, on, ref_branch, off);
         }
-      g_print ("   %s\n", reason);
+      g_print ("   %s\n", escaped_reason);
     }
 }
 
@@ -1121,12 +1124,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;
 
@@ -1135,10 +1142,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.14.3/common/flatpak-context.c flatpak-1.14.4/common/flatpak-context.c
--- flatpak-1.14.3/common/flatpak-context.c	2023-02-18 14:08:15.000000000 +0000
+++ flatpak-1.14.4/common/flatpak-context.c	2023-03-16 09:55:13.000000000 +0000
@@ -488,11 +488,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
@@ -854,6 +860,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;
@@ -1510,8 +1519,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;
@@ -1703,11 +1711,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);
@@ -1724,7 +1745,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.14.3/common/flatpak-run.c flatpak-1.14.4/common/flatpak-run.c
--- flatpak-1.14.3/common/flatpak-run.c	2023-02-18 14:08:27.000000000 +0000
+++ flatpak-1.14.4/common/flatpak-run.c	2023-03-16 09:55:13.000000000 +0000
@@ -3210,6 +3210,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.14.3/common/flatpak-utils.c flatpak-1.14.4/common/flatpak-utils.c
--- flatpak-1.14.3/common/flatpak-utils.c	2023-01-30 11:43:35.000000000 +0000
+++ flatpak-1.14.4/common/flatpak-utils.c	2023-03-16 09:55:13.000000000 +0000
@@ -625,7 +625,7 @@
   g_autofree char *modules_data = NULL;
   g_autoptr(GError) error = NULL;
   char *start, *end;
-  
+
   if (!g_file_get_contents ("/proc/modules", &modules_data, NULL, &error))
     {
       g_debug ("Failed to read /proc/modules: %s", error->message);
@@ -9221,6 +9221,125 @@
   return g_strcmp0 (uri1_norm, uri2_norm) == 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;
+}
+
 gboolean
 running_under_sudo (void)
 {
diff -Nru flatpak-1.14.3/common/flatpak-utils-private.h flatpak-1.14.4/common/flatpak-utils-private.h
--- flatpak-1.14.3/common/flatpak-utils-private.h	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/common/flatpak-utils-private.h	2023-03-16 09:55:13.000000000 +0000
@@ -928,6 +928,20 @@
 gboolean flatpak_uri_equal (const char *uri1,
                             const char *uri2);
 
+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);
+
 gboolean running_under_sudo (void);
 
 #define FLATPAK_MESSAGE_ID "c7b39b1e006b464599465e105b361485"
diff -Nru flatpak-1.14.3/common/flatpak-version-macros.h flatpak-1.14.4/common/flatpak-version-macros.h
--- flatpak-1.14.3/common/flatpak-version-macros.h	2023-02-27 12:23:30.000000000 +0000
+++ flatpak-1.14.4/common/flatpak-version-macros.h	2023-03-16 09:56:12.000000000 +0000
@@ -45,7 +45,7 @@
  *
  * The micro version.
  */
-#define FLATPAK_MICRO_VERSION (3)
+#define FLATPAK_MICRO_VERSION (4)
 
 /**
  * FLATPAK_CHECK_VERSION:
diff -Nru flatpak-1.14.3/configure.ac flatpak-1.14.4/configure.ac
--- flatpak-1.14.3/configure.ac	2023-02-27 12:22:48.000000000 +0000
+++ flatpak-1.14.4/configure.ac	2023-03-16 09:55:13.000000000 +0000
@@ -15,7 +15,7 @@
 
 m4_define([flatpak_major_version], [1])
 m4_define([flatpak_minor_version], [14])
-m4_define([flatpak_micro_version], [3])
+m4_define([flatpak_micro_version], [4])
 m4_define([flatpak_extra_version], [])
 m4_define([flatpak_interface_age], [0])
 m4_define([flatpak_binary_age],
diff -Nru flatpak-1.14.3/debian/changelog flatpak-1.14.4/debian/changelog
--- flatpak-1.14.3/debian/changelog	2023-02-27 12:52:48.000000000 +0000
+++ flatpak-1.14.4/debian/changelog	2023-03-16 10:39:01.000000000 +0000
@@ -1,3 +1,18 @@
+flatpak (1.14.4-1) unstable; urgency=high
+
+  * New upstream security fix release
+    - 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, 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.
+    - Translation update: pl
+
+ -- Simon McVittie <smcv@debian.org>  Thu, 16 Mar 2023 10:39:01 +0000
+
 flatpak (1.14.3-1) unstable; urgency=medium
 
   * New upstream stable release
diff -Nru flatpak-1.14.3/doc/reference/html/flatpak-Version-information.html flatpak-1.14.4/doc/reference/html/flatpak-Version-information.html
--- flatpak-1.14.3/doc/reference/html/flatpak-Version-information.html	2023-02-27 12:31:37.000000000 +0000
+++ flatpak-1.14.4/doc/reference/html/flatpak-Version-information.html	2023-03-16 09:58:23.000000000 +0000
@@ -129,7 +129,7 @@
 <hr>
 <div class="refsect2">
 <a name="FLATPAK-MICRO-VERSION:CAPS"></a><h3>FLATPAK_MICRO_VERSION</h3>
-<pre class="programlisting">#define FLATPAK_MICRO_VERSION (3)
+<pre class="programlisting">#define FLATPAK_MICRO_VERSION (4)
 </pre>
 <p>The micro version.</p>
 </div>
diff -Nru flatpak-1.14.3/doc/reference/html/index.html flatpak-1.14.4/doc/reference/html/index.html
--- flatpak-1.14.3/doc/reference/html/index.html	2023-02-27 12:31:37.000000000 +0000
+++ flatpak-1.14.4/doc/reference/html/index.html	2023-03-16 09:58:23.000000000 +0000
@@ -15,7 +15,7 @@
 <div>
 <div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">Flatpak Library Reference Manual</p></th></tr></table></div>
 <div><p class="releaseinfo">
-      For flatpak 1.14.3
+      For flatpak 1.14.4
 
     </p></div>
 </div>
diff -Nru flatpak-1.14.3/NEWS flatpak-1.14.4/NEWS
--- flatpak-1.14.3/NEWS	2023-02-27 12:22:59.000000000 +0000
+++ flatpak-1.14.4/NEWS	2023-03-16 09:55:13.000000000 +0000
@@ -1,3 +1,23 @@
+Changes in 1.14.4
+~~~~~~~~~~~~~~~~~
+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:
+
+* Translation update: pl
+
 Changes in 1.14.3
 ~~~~~~~~~~~~~~~~~
 Released: 2023-02-27
Binary files /tmp/mI8ANadtfJ/flatpak-1.14.3/po/pl.gmo and /tmp/1FYUGB45AB/flatpak-1.14.4/po/pl.gmo differ
diff -Nru flatpak-1.14.3/tests/make-test-app.sh flatpak-1.14.4/tests/make-test-app.sh
--- flatpak-1.14.3/tests/make-test-app.sh	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/tests/make-test-app.sh	2023-03-15 17:37:23.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.14.3/tests/package_version.txt flatpak-1.14.4/tests/package_version.txt
--- flatpak-1.14.3/tests/package_version.txt	2023-02-27 12:24:09.000000000 +0000
+++ flatpak-1.14.4/tests/package_version.txt	2023-03-16 09:57:43.000000000 +0000
@@ -1 +1 @@
-1.14.3
+1.14.4
diff -Nru flatpak-1.14.3/tests/testcommon.c flatpak-1.14.4/tests/testcommon.c
--- flatpak-1.14.3/tests/testcommon.c	2022-11-17 18:07:49.000000000 +0000
+++ flatpak-1.14.4/tests/testcommon.c	2023-03-16 09:55:13.000000000 +0000
@@ -1837,6 +1837,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[])
 {
@@ -1870,6 +1942,8 @@
   g_test_add_func ("/common/quote-argv", test_quote_argv);
   g_test_add_func ("/common/str-is-integer", test_str_is_integer);
   g_test_add_func ("/common/parse-x11-display", test_parse_x11_display);
+  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.14.3/tests/test-context.c flatpak-1.14.4/tests/test-context.c
--- flatpak-1.14.3/tests/test-context.c	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/tests/test-context.c	2023-03-16 09:55:13.000000000 +0000
@@ -129,13 +129,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);
@@ -145,7 +146,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));
@@ -158,8 +159,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
@@ -179,19 +179,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));
@@ -273,20 +280,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));
@@ -427,6 +442,65 @@
     }
 }
 
+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[])
 {
@@ -435,6 +509,8 @@
   g_test_add_func ("/context/env", test_context_env);
   g_test_add_func ("/context/env-fd", test_context_env_fd);
   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.14.3/tests/test-info.sh flatpak-1.14.4/tests/test-info.sh
--- flatpak-1.14.3/tests/test-info.sh	2022-11-17 18:07:49.000000000 +0000
+++ flatpak-1.14.4/tests/test-info.sh	2023-03-16 09:55:13.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.14.3/tests/test-seccomp.sh flatpak-1.14.4/tests/test-seccomp.sh
--- flatpak-1.14.3/tests/test-seccomp.sh	2022-11-17 18:07:49.000000000 +0000
+++ flatpak-1.14.4/tests/test-seccomp.sh	2023-03-16 09:55:13.000000000 +0000
@@ -8,7 +8,7 @@
 
 skip_without_bwrap
 
-echo "1..16"
+echo "1..18"
 
 setup_repo
 install_repo
@@ -80,6 +80,12 @@
     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 -Nru flatpak-1.14.3/tests/try-syscall.c flatpak-1.14.4/tests/try-syscall.c
--- flatpak-1.14.3/tests/try-syscall.c	2022-11-17 18:26:13.000000000 +0000
+++ flatpak-1.14.4/tests/try-syscall.c	2023-03-16 09:55:13.000000000 +0000
@@ -151,6 +151,15 @@
             }
         }
 #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 */

Reply to: