diff --git a/CVE-2021-21261-1.patch b/CVE-2021-21261-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..4e8b2795fbf2abcd5f195027aaa0760737d369b8 --- /dev/null +++ b/CVE-2021-21261-1.patch @@ -0,0 +1,156 @@ +From b04ab0f0c4fe4970737187a76389b20029e27488 Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Tue, 12 Jan 2021 12:21:31 +0000 +Subject: [PATCH] run: Convert all environment variables into bwrap + arguments + +This avoids some of them being filtered out by a setuid bwrap. It also +means that if they came from an untrusted source, they cannot be used +to inject arbitrary code into a non-setuid bwrap via mechanisms like +LD_PRELOAD. + +Because they get bundled into a memfd or temporary file, they do not +actually appear in argv, ensuring that they remain inaccessible to +processes running under a different uid (which is important if their +values are tokens or other secrets). + +Signed-off-by: Simon McVittie +Part-of: https://github.com/flatpak/flatpak/security/advisories/GHSA-4ppf-fxf6-vxg2 +--- + common/flatpak-bwrap-private.h | 3 +++ + common/flatpak-bwrap.c | 43 ++++++++++++++++++++++++++++++++++ + common/flatpak-run.c | 24 ++++++++++++------- + 3 files changed, 61 insertions(+), 9 deletions(-) + +--- flatpak.orig/common/flatpak-bwrap-private.h ++++ flatpak/common/flatpak-bwrap-private.h +@@ -43,6 +43,8 @@ void flatpak_bwrap_unset_env (F + const char *variable); + void flatpak_bwrap_add_arg (FlatpakBwrap *bwrap, + const char *arg); ++void flatpak_bwrap_take_arg (FlatpakBwrap *bwrap, ++ char *arg); + void flatpak_bwrap_add_noinherit_fd (FlatpakBwrap *bwrap, + int fd); + void flatpak_bwrap_add_fd (FlatpakBwrap *bwrap, +@@ -73,6 +75,7 @@ void flatpak_bwrap_add_bind_arg + const char *type, + const char *src, + const char *dest); ++void flatpak_bwrap_envp_to_args (FlatpakBwrap *bwrap); + gboolean flatpak_bwrap_bundle_args (FlatpakBwrap *bwrap, + int start, + int end, +--- flatpak.orig/common/flatpak-bwrap.c ++++ flatpak/common/flatpak-bwrap.c +@@ -108,6 +108,18 @@ flatpak_bwrap_add_arg (FlatpakBwrap *bwr + g_ptr_array_add (bwrap->argv, g_strdup (arg)); + } + ++/* ++ * flatpak_bwrap_take_arg: ++ * @arg: (transfer full): Take ownership of this argument ++ * ++ * Add @arg to @bwrap's argv, taking ownership of the pointer. ++ */ ++void ++flatpak_bwrap_take_arg (FlatpakBwrap *bwrap, char *arg) ++{ ++ g_ptr_array_add (bwrap->argv, arg); ++} ++ + void + flatpak_bwrap_finish (FlatpakBwrap *bwrap) + { +@@ -273,6 +285,37 @@ flatpak_bwrap_add_bind_arg (FlatpakBwrap + } + } + ++/* ++ * Convert bwrap->envp into a series of --setenv arguments for bwrap(1), ++ * assumed to be applied to an empty environment. Reset envp to be an ++ * empty environment. ++ */ ++void ++flatpak_bwrap_envp_to_args (FlatpakBwrap *bwrap) ++{ ++ gsize i; ++ ++ for (i = 0; bwrap->envp[i] != NULL; i++) ++ { ++ char *key_val = bwrap->envp[i]; ++ char *eq = strchr (key_val, '='); ++ ++ if (eq) ++ { ++ flatpak_bwrap_add_arg (bwrap, "--setenv"); ++ flatpak_bwrap_take_arg (bwrap, g_strndup (key_val, eq - key_val)); ++ flatpak_bwrap_add_arg (bwrap, eq + 1); ++ } ++ else ++ { ++ g_warn_if_reached (); ++ } ++ } ++ ++ g_strfreev (g_steal_pointer (&bwrap->envp)); ++ bwrap->envp = g_strdupv (flatpak_bwrap_empty_env); ++} ++ + gboolean + flatpak_bwrap_bundle_args (FlatpakBwrap *bwrap, + int start, +--- flatpak.orig/common/flatpak-run.c ++++ flatpak/common/flatpak-run.c +@@ -1120,15 +1120,6 @@ flatpak_run_add_environment_args (Flatpa + flatpak_run_add_system_dbus_args (bwrap, proxy_arg_bwrap, context, flags); + flatpak_run_add_a11y_dbus_args (bwrap, proxy_arg_bwrap, context, flags); + +- if (g_environ_getenv (bwrap->envp, "LD_LIBRARY_PATH") != NULL) +- { +- /* LD_LIBRARY_PATH is overridden for setuid helper, so pass it as cmdline arg */ +- flatpak_bwrap_add_args (bwrap, +- "--setenv", "LD_LIBRARY_PATH", g_environ_getenv (bwrap->envp, "LD_LIBRARY_PATH"), +- NULL); +- flatpak_bwrap_unset_env (bwrap, "LD_LIBRARY_PATH"); +- } +- + /* Must run this before spawning the dbus proxy, to ensure it + ends up in the app cgroup */ + if (!flatpak_run_in_transient_unit (app_id, &my_error)) +@@ -3139,6 +3130,8 @@ flatpak_run_app (const char *app_ref + command = default_command; + } + ++ flatpak_bwrap_envp_to_args (bwrap); ++ + if (!flatpak_bwrap_bundle_args (bwrap, 1, -1, FALSE, error)) + return FALSE; + +@@ -3161,6 +3154,12 @@ flatpak_run_app (const char *app_ref + char pid_str[64]; + g_autofree char *pid_path = NULL; + ++ /* flatpak_bwrap_envp_to_args() moved the environment variables to ++ * be set into --setenv instructions in argv, so the environment ++ * in which the bwrap command runs must be empty. */ ++ g_assert (bwrap->envp != NULL); ++ g_assert (bwrap->envp[0] == NULL); ++ + if (!g_spawn_async (NULL, + (char **) bwrap->argv->pdata, + bwrap->envp, +@@ -3185,6 +3184,13 @@ flatpak_run_app (const char *app_ref + + /* Ensure we unset O_CLOEXEC */ + flatpak_bwrap_child_setup_cb (bwrap->fds); ++ ++ /* flatpak_bwrap_envp_to_args() moved the environment variables to ++ * be set into --setenv instructions in argv, so the environment ++ * in which the bwrap command runs must be empty. */ ++ g_assert (bwrap->envp != NULL); ++ g_assert (bwrap->envp[0] == NULL); ++ + if (execvpe (flatpak_get_bwrap (), (char **) bwrap->argv->pdata, bwrap->envp) == -1) + { + g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), diff --git a/CVE-2021-21261-2.patch b/CVE-2021-21261-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..8250a8418fbf8cf3be084deff0519c6afdd47ba5 --- /dev/null +++ b/CVE-2021-21261-2.patch @@ -0,0 +1,228 @@ +From 1b82bf2f9df06ee60d222b4fb45fe3490d05ef94 Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Mon, 11 Jan 2021 14:51:36 +0000 +Subject: [PATCH] common: Move flatpak_buffer_to_sealed_memfd_or_tmpfile + to its own file + +We'll need this to use it in flatpak-portal without pulling the rest of +the common/ directory. + +Signed-off-by: Simon McVittie +--- + common/Makefile.am.inc | 2 + + common/flatpak-utils-memfd-private.h | 32 ++++++++++ + common/flatpak-utils-memfd.c | 90 ++++++++++++++++++++++++++++ + common/flatpak-utils-private.h | 1 + + common/flatpak-utils.c | 50 ---------------- + 5 files changed, 125 insertions(+), 50 deletions(-) + create mode 100644 common/flatpak-utils-memfd-private.h + create mode 100644 common/flatpak-utils-memfd.c + +--- flatpak.orig/common/Makefile.am.inc ++++ flatpak/common/Makefile.am.inc +@@ -96,6 +96,8 @@ libflatpak_common_la_SOURCES = \ + common/flatpak-utils.c \ + common/flatpak-utils-http.c \ + common/flatpak-utils-http-private.h \ ++ common/flatpak-utils-memfd.c \ ++ common/flatpak-utils-memfd-private.h \ + common/flatpak-utils-private.h \ + common/flatpak-chain-input-stream.c \ + common/flatpak-chain-input-stream-private.h \ +--- /dev/null ++++ flatpak/common/flatpak-utils-memfd-private.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright © 2014 Red Hat, Inc ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see . ++ * ++ * Authors: ++ * Alexander Larsson ++ */ ++ ++#ifndef __FLATPAK_UTILS_MEMFD_H__ ++#define __FLATPAK_UTILS_MEMFD_H__ ++ ++#include "libglnx/libglnx.h" ++ ++gboolean flatpak_buffer_to_sealed_memfd_or_tmpfile (GLnxTmpfile *tmpf, ++ const char *name, ++ const char *str, ++ size_t len, ++ GError **error); ++ ++#endif /* __FLATPAK_UTILS_MEMFD_H__ */ +--- /dev/null ++++ flatpak/common/flatpak-utils-memfd.c +@@ -0,0 +1,90 @@ ++/* ++ * Copyright © 2014 Red Hat, Inc ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see . ++ * ++ * Authors: ++ * Alexander Larsson ++ */ ++ ++#include "config.h" ++ ++#include "flatpak-utils-memfd-private.h" ++ ++#include "valgrind-private.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* If memfd_create() is available, generate a sealed memfd with contents of ++ * @str. Otherwise use an O_TMPFILE @tmpf in anonymous mode, write @str to ++ * @tmpf, and lseek() back to the start. See also similar uses in e.g. ++ * rpm-ostree for running dracut. ++ */ ++gboolean ++flatpak_buffer_to_sealed_memfd_or_tmpfile (GLnxTmpfile *tmpf, ++ const char *name, ++ const char *str, ++ size_t len, ++ GError **error) ++{ ++ if (len == -1) ++ len = strlen (str); ++ glnx_autofd int memfd = memfd_create (name, MFD_CLOEXEC | MFD_ALLOW_SEALING); ++ int fd; /* Unowned */ ++ if (memfd != -1) ++ { ++ fd = memfd; ++ } ++ else ++ { ++ /* We use an anonymous fd (i.e. O_EXCL) since we don't want ++ * the target container to potentially be able to re-link it. ++ */ ++ if (!G_IN_SET (errno, ENOSYS, EOPNOTSUPP)) ++ return glnx_throw_errno_prefix (error, "memfd_create"); ++ if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, tmpf, error)) ++ return FALSE; ++ fd = tmpf->fd; ++ } ++ if (ftruncate (fd, len) < 0) ++ return glnx_throw_errno_prefix (error, "ftruncate"); ++ if (glnx_loop_write (fd, str, len) < 0) ++ return glnx_throw_errno_prefix (error, "write"); ++ if (lseek (fd, 0, SEEK_SET) < 0) ++ return glnx_throw_errno_prefix (error, "lseek"); ++ if (memfd != -1) ++ { ++ /* Valgrind doesn't currently handle G_ADD_SEALS, so lets not seal when debugging... */ ++ if ((!RUNNING_ON_VALGRIND) && ++ fcntl (memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0) ++ return glnx_throw_errno_prefix (error, "fcntl(F_ADD_SEALS)"); ++ /* The other values can stay default */ ++ tmpf->fd = glnx_steal_fd (&memfd); ++ tmpf->initialized = TRUE; ++ } ++ return TRUE; ++} +--- flatpak.orig/common/flatpak-utils-private.h ++++ flatpak/common/flatpak-utils-private.h +@@ -32,6 +32,7 @@ + #include "flatpak-context-private.h" + #include "flatpak-error.h" + #include "flatpak-utils-http-private.h" ++#include "flatpak-utils-memfd-private.h" + #include + #include + +--- flatpak.orig/common/flatpak-utils.c ++++ flatpak/common/flatpak-utils.c +@@ -2280,56 +2280,6 @@ flatpak_file_rename (GFile *from, + return TRUE; + } + +-/* If memfd_create() is available, generate a sealed memfd with contents of +- * @str. Otherwise use an O_TMPFILE @tmpf in anonymous mode, write @str to +- * @tmpf, and lseek() back to the start. See also similar uses in e.g. +- * rpm-ostree for running dracut. +- */ +-gboolean +-flatpak_buffer_to_sealed_memfd_or_tmpfile (GLnxTmpfile *tmpf, +- const char *name, +- const char *str, +- size_t len, +- GError **error) +-{ +- if (len == -1) +- len = strlen (str); +- glnx_autofd int memfd = memfd_create (name, MFD_CLOEXEC | MFD_ALLOW_SEALING); +- int fd; /* Unowned */ +- if (memfd != -1) +- { +- fd = memfd; +- } +- else +- { +- /* We use an anonymous fd (i.e. O_EXCL) since we don't want +- * the target container to potentially be able to re-link it. +- */ +- if (!G_IN_SET (errno, ENOSYS, EOPNOTSUPP)) +- return glnx_throw_errno_prefix (error, "memfd_create"); +- if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, tmpf, error)) +- return FALSE; +- fd = tmpf->fd; +- } +- if (ftruncate (fd, len) < 0) +- return glnx_throw_errno_prefix (error, "ftruncate"); +- if (glnx_loop_write (fd, str, len) < 0) +- return glnx_throw_errno_prefix (error, "write"); +- if (lseek (fd, 0, SEEK_SET) < 0) +- return glnx_throw_errno_prefix (error, "lseek"); +- if (memfd != -1) +- { +- /* Valgrind doesn't currently handle G_ADD_SEALS, so lets not seal when debugging... */ +- if ((!RUNNING_ON_VALGRIND) && +- fcntl (memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0) +- return glnx_throw_errno_prefix (error, "fcntl(F_ADD_SEALS)"); +- /* The other values can stay default */ +- tmpf->fd = glnx_steal_fd (&memfd); +- tmpf->initialized = TRUE; +- } +- return TRUE; +-} +- + gboolean + flatpak_open_in_tmpdir_at (int tmpdir_fd, + int mode, diff --git a/CVE-2021-21261-3.patch b/CVE-2021-21261-3.patch new file mode 100644 index 0000000000000000000000000000000000000000..8a1d5d1472772dc43a4f57b3671fdac2d0d6714f --- /dev/null +++ b/CVE-2021-21261-3.patch @@ -0,0 +1,204 @@ +From 7a93013153a425d4cb8466cd9b665b98e713451d Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Sun, 10 Jan 2021 16:18:58 +0000 +Subject: [PATCH] context: Add --env-fd option + +This allows environment variables to be added to the context without +making their values visible to processes running under a different uid, +which might be significant if the variable's value is a token or some +other secret value. + +Signed-off-by: Simon McVittie +Part-of: https://github.com/flatpak/flatpak/security/advisories/GHSA-4ppf-fxf6-vxg2 +--- + common/flatpak-context.c | 60 ++++++++++++++++++++++++++++++++++++ + doc/flatpak-build-finish.xml | 18 +++++++++++ + doc/flatpak-build.xml | 18 +++++++++++ + doc/flatpak-override.xml | 18 +++++++++++ + doc/flatpak-run.xml | 18 +++++++++++ + 5 files changed, 132 insertions(+) + +--- flatpak.orig/common/flatpak-context.c ++++ flatpak/common/flatpak-context.c +@@ -1040,6 +1040,65 @@ option_env_cb (const gchar *option_name, + } + + static gboolean ++option_env_fd_cb (const gchar *option_name, ++ const gchar *value, ++ gpointer data, ++ GError **error) ++{ ++ FlatpakContext *context = data; ++ g_autoptr(GBytes) env_block = NULL; ++ gsize remaining; ++ const char *p; ++ guint64 fd; ++ gchar *endptr; ++ ++ fd = g_ascii_strtoull (value, &endptr, 10); ++ ++ if (endptr == NULL || *endptr != '\0' || fd > G_MAXINT) ++ return glnx_throw (error, "Not a valid file descriptor: %s", value); ++ ++ env_block = glnx_fd_readall_bytes ((int) fd, NULL, error); ++ ++ if (env_block == NULL) ++ return FALSE; ++ ++ p = g_bytes_get_data (env_block, &remaining); ++ ++ /* env_block might not be \0-terminated */ ++ while (remaining > 0) ++ { ++ size_t len = strnlen (p, remaining); ++ const char *equals; ++ ++ g_assert (len <= remaining); ++ ++ equals = memchr (p, '=', len); ++ ++ if (equals == NULL || equals == p) ++ return glnx_throw (error, ++ "Environment variable must be given in the form VARIABLE=VALUE, not %.*s", (int) len, p); ++ ++ flatpak_context_set_env_var (context, ++ g_strndup (p, equals - p), ++ g_strndup (equals + 1, len - (equals - p) - 1)); ++ p += len; ++ remaining -= len; ++ ++ if (remaining > 0) ++ { ++ g_assert (*p == '\0'); ++ p += 1; ++ remaining -= 1; ++ } ++ } ++ ++ if (fd >= 3) ++ close (fd); ++ ++ return TRUE; ++} ++ ++static gboolean + option_own_name_cb (const gchar *option_name, + const gchar *value, + gpointer data, +@@ -1206,6 +1265,7 @@ static GOptionEntry context_options[] = + { "filesystem", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_filesystem_cb, N_("Expose filesystem to app (:ro for read-only)"), N_("FILESYSTEM[:ro]") }, + { "nofilesystem", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_nofilesystem_cb, N_("Don't expose filesystem to app"), N_("FILESYSTEM") }, + { "env", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_env_cb, N_("Set environment variable"), N_("VAR=VALUE") }, ++ { "env-fd", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_env_fd_cb, N_("Read environment variables in env -0 format from FD"), N_("FD") }, + { "own-name", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_own_name_cb, N_("Allow app to own name on the session bus"), N_("DBUS_NAME") }, + { "talk-name", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_talk_name_cb, N_("Allow app to talk to name on the session bus"), N_("DBUS_NAME") }, + { "system-own-name", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK, &option_system_own_name_cb, N_("Allow app to own name on the system bus"), N_("DBUS_NAME") }, +--- flatpak.orig/doc/flatpak-build-finish.xml ++++ flatpak/doc/flatpak-build-finish.xml +@@ -277,6 +277,24 @@ key=v1;v2; + + + ++ ++ ++ ++ Read environment variables from the file descriptor ++ FD, and set them as if ++ via . This can be used to avoid ++ environment variables and their values becoming visible ++ to other users. ++ ++ Each environment variable is in the form ++ VAR=VALUE ++ followed by a zero byte. This is the same format used by ++ env -0 and ++ /proc/*/environ. ++ ++ ++ ++ + + + +--- flatpak.orig/doc/flatpak-build.xml ++++ flatpak/doc/flatpak-build.xml +@@ -284,6 +284,24 @@ key=v1;v2; + + + ++ ++ ++ ++ Read environment variables from the file descriptor ++ FD, and set them as if ++ via . This can be used to avoid ++ environment variables and their values becoming visible ++ to other users. ++ ++ Each environment variable is in the form ++ VAR=VALUE ++ followed by a zero byte. This is the same format used by ++ env -0 and ++ /proc/*/environ. ++ ++ ++ ++ + + + +--- flatpak.orig/doc/flatpak-override.xml ++++ flatpak/doc/flatpak-override.xml +@@ -258,6 +258,24 @@ key=v1;v2; + + + ++ ++ ++ ++ Read environment variables from the file descriptor ++ FD, and set them as if ++ via . This can be used to avoid ++ environment variables and their values becoming visible ++ to other users. ++ ++ Each environment variable is in the form ++ VAR=VALUE ++ followed by a zero byte. This is the same format used by ++ env -0 and ++ /proc/*/environ. ++ ++ ++ ++ + + + +--- flatpak.orig/doc/flatpak-run.xml ++++ flatpak/doc/flatpak-run.xml +@@ -361,6 +361,24 @@ key=v1;v2; + + + ++ ++ ++ ++ Read environment variables from the file descriptor ++ FD, and set them as if ++ via . This can be used to avoid ++ environment variables and their values becoming visible ++ to other users. ++ ++ Each environment variable is in the form ++ VAR=VALUE ++ followed by a zero byte. This is the same format used by ++ env -0 and ++ /proc/*/environ. ++ ++ ++ ++ + + + diff --git a/CVE-2021-21261-4.patch b/CVE-2021-21261-4.patch new file mode 100644 index 0000000000000000000000000000000000000000..2f644ae618809235da56539328c54c5ea532157d --- /dev/null +++ b/CVE-2021-21261-4.patch @@ -0,0 +1,138 @@ +From ce6a6e593310d42f7aecddb88d98e759f22ab6db Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Tue, 12 Jan 2021 12:25:59 +0000 +Subject: [PATCH] portal: Convert --env in extra-args into --env-fd + +This hides overridden variables from the command-line, which means +processes running under other uids can't see them in /proc/*/cmdline, +which might be important if they contain secrets. + +Signed-off-by: Simon McVittie +Part-of: https://github.com/flatpak/flatpak/security/advisories/GHSA-4ppf-fxf6-vxg2 +--- + portal/Makefile.am.inc | 4 ++- + portal/flatpak-portal.c | 65 ++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 67 insertions(+), 2 deletions(-) + +--- flatpak.orig/portal/Makefile.am.inc ++++ flatpak/portal/Makefile.am.inc +@@ -29,11 +29,13 @@ flatpak_portal_SOURCES = \ + portal/flatpak-portal-app-info.h \ + common/flatpak-portal-error.c \ + common/flatpak-portal-error.h \ ++ common/flatpak-utils-memfd.c \ ++ common/flatpak-utils-memfd-private.h \ + $(NULL) + + BUILT_SOURCES += $(nodist_flatpak_portal_SOURCES) + CLEANFILES += $(nodist_flatpak_portal_SOURCES) + +-flatpak_portal_LDADD = $(AM_LDADD) $(BASE_LIBS) ++flatpak_portal_LDADD = $(AM_LDADD) $(BASE_LIBS) libglnx.la + flatpak_portal_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) -DFLATPAK_COMPILATION + flatpak_portal_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/portal +--- flatpak.orig/portal/flatpak-portal.c ++++ flatpak/portal/flatpak-portal.c +@@ -32,6 +32,14 @@ + #include "flatpak-portal.h" + #include "flatpak-portal-app-info.h" + #include "flatpak-portal-error.h" ++#include "flatpak-utils-memfd-private.h" ++ ++/* Syntactic sugar added in newer GLib, which makes the error paths more ++ * clearly correct */ ++#ifndef G_DBUS_METHOD_INVOCATION_HANDLED ++# define G_DBUS_METHOD_INVOCATION_HANDLED TRUE ++# define G_DBUS_METHOD_INVOCATION_UNHANDLED FALSE ++#endif + + #define IDLE_TIMEOUT_SECS 10 * 60 + +@@ -166,9 +174,16 @@ typedef struct + int fd_map_len; + gboolean set_tty; + int tty; ++ int env_fd; + } ChildSetupData; + + static void ++drop_cloexec (int fd) ++{ ++ fcntl (fd, F_SETFD, 0); ++} ++ ++static void + child_setup_func (gpointer user_data) + { + ChildSetupData *data = (ChildSetupData *) user_data; +@@ -176,6 +191,9 @@ child_setup_func (gpointer user_data) + sigset_t set; + int i; + ++ if (data->env_fd != -1) ++ drop_cloexec (data->env_fd); ++ + /* Unblock all signals */ + sigemptyset (&set); + if (pthread_sigmask (SIG_SETMASK, &set, NULL) == -1) +@@ -321,6 +339,9 @@ handle_spawn (PortalFlatpak *obj + g_auto(GStrv) sandbox_expose = NULL; + g_auto(GStrv) sandbox_expose_ro = NULL; + gboolean sandboxed; ++ g_autoptr(GString) env_string = g_string_new (""); ++ ++ child_setup_data.env_fd = -1; + + app_info = g_object_get_data (G_OBJECT (invocation), "app-info"); + g_assert (app_info != NULL); +@@ -505,7 +526,49 @@ handle_spawn (PortalFlatpak *obj + else + { + for (i = 0; extra_args != NULL && extra_args[i] != NULL; i++) +- g_ptr_array_add (flatpak_argv, g_strdup (extra_args[i])); ++ { ++ if (g_str_has_prefix (extra_args[i], "--env=")) ++ { ++ const char *var_val = extra_args[i] + strlen ("--env="); ++ ++ if (var_val[0] == '\0' || var_val[0] == '=') ++ { ++ g_warning ("Environment variable in extra-args has empty name"); ++ continue; ++ } ++ ++ if (strchr (var_val, '=') == NULL) ++ { ++ g_warning ("Environment variable in extra-args has no value"); ++ continue; ++ } ++ ++ g_string_append (env_string, var_val); ++ g_string_append_c (env_string, '\0'); ++ } ++ else ++ { ++ g_ptr_array_add (flatpak_argv, g_strdup (extra_args[i])); ++ } ++ } ++ } ++ ++ if (env_string->len > 0) ++ { ++ g_auto(GLnxTmpfile) env_tmpf = { 0, }; ++ ++ if (!flatpak_buffer_to_sealed_memfd_or_tmpfile (&env_tmpf, "environ", ++ env_string->str, ++ env_string->len, &error)) ++ { ++ g_dbus_method_invocation_return_gerror (invocation, error); ++ return G_DBUS_METHOD_INVOCATION_HANDLED; ++ } ++ ++ child_setup_data.env_fd = glnx_steal_fd (&env_tmpf.fd); ++ g_ptr_array_add (flatpak_argv, ++ g_strdup_printf ("--env-fd=%d", ++ child_setup_data.env_fd)); + } + + /* Inherit launcher network access from launcher, unless diff --git a/CVE-2021-21261-5.patch b/CVE-2021-21261-5.patch new file mode 100644 index 0000000000000000000000000000000000000000..9f49a3b79b69d1581a81019be6e4b9d533350a61 --- /dev/null +++ b/CVE-2021-21261-5.patch @@ -0,0 +1,67 @@ +From f527eaeb132dcd5bb06115b987d6a6f8bfafac9b Mon Sep 17 00:00:00 2001 +From: Simon McVittie +Date: Sun, 10 Jan 2021 16:25:29 +0000 +Subject: [PATCH] portal: Do not use caller-supplied variables in + environment + +If the caller specifies a variable that can be used to inject arbitrary +code into processes, we must not allow it to enter the environment +block used to run `flatpak run`, which runs unsandboxed. + +This change requires the previous commit "context: Add --env-fd option", +which adds infrastructure used here. + +To be secure, this change also requires the previous commit +"run: Convert all environment variables into bwrap arguments", which +protects a non-setuid bwrap(1) from the same attack. + +Signed-off-by: Simon McVittie +Part-of: https://github.com/flatpak/flatpak/security/advisories/GHSA-4ppf-fxf6-vxg2 +--- + portal/flatpak-portal.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +--- flatpak.orig/portal/flatpak-portal.c ++++ flatpak/portal/flatpak-portal.c +@@ -506,6 +506,13 @@ handle_spawn (PortalFlatpak *obj + else + env = g_get_environ (); + ++ /* Let the environment variables given by the caller override the ones ++ * from extra_args. Don't add them to @env, because they are controlled ++ * by our caller, which might be trying to use them to inject code into ++ * flatpak(1); add them to the environment block instead. ++ * ++ * We don't use --env= here, so that if the values are something that ++ * should not be exposed to other uids, they can remain confidential. */ + n_envs = g_variant_n_children (arg_envs); + for (i = 0; i < n_envs; i++) + { +@@ -513,7 +520,26 @@ handle_spawn (PortalFlatpak *obj + const char *val = NULL; + g_variant_get_child (arg_envs, i, "{&s&s}", &var, &val); + +- env = g_environ_setenv (env, var, val, TRUE); ++ if (var[0] == '\0') ++ { ++ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Environment variable cannot have empty name"); ++ return G_DBUS_METHOD_INVOCATION_HANDLED; ++ } ++ ++ if (strchr (var, '=') != NULL) ++ { ++ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Environment variable name cannot contain '='"); ++ return G_DBUS_METHOD_INVOCATION_HANDLED; ++ } ++ ++ g_string_append (env_string, var); ++ g_string_append_c (env_string, '='); ++ g_string_append (env_string, val); ++ g_string_append_c (env_string, '\0'); + } + + g_ptr_array_add (flatpak_argv, g_strdup ("flatpak")); diff --git a/flatpak.spec b/flatpak.spec index 6eb380968ab91ae81c6e558eb4c1c59b634c6d99..36c3962e398242972aabe1c10451d776d0df0b21 100644 --- a/flatpak.spec +++ b/flatpak.spec @@ -1,10 +1,16 @@ Name: flatpak Version: 1.0.3 -Release: 2 +Release: 3 Summary: Application deployment framework for desktop apps License: LGPLv2+ URL: http://flatpak.org/ Source0: https://github.com/flatpak/flatpak/releases/download/%{version}/%{name}-%{version}.tar.xz +Patch0000: modify-automake-version.patch +Patch0001: CVE-2021-21261-1.patch +Patch0002: CVE-2021-21261-2.patch +Patch0003: CVE-2021-21261-3.patch +Patch0004: CVE-2021-21261-4.patch +Patch0005: CVE-2021-21261-5.patch BuildRequires: pkgconfig(appstream-glib) pkgconfig(gio-unix-2.0) pkgconfig(gobject-introspection-1.0) >= 1.40.0 pkgconfig(json-glib-1.0) pkgconfig(libarchive) >= 2.8.0 BuildRequires: pkgconfig(libsoup-2.4) pkgconfig(libxml-2.0) >= 2.4 pkgconfig(ostree-1) >= 2018.7 pkgconfig(polkit-gobject-1) pkgconfig(libseccomp) pkgconfig(xau) @@ -99,5 +105,9 @@ flatpak remote-list --system &> /dev/null || : %{_mandir}/man5/flatpak-remote.5* %changelog +* Sun Feb 07 2021 wangxiao - 1.0.3-3 +- Modify automake version +- Fix CVE-2021-21261 + * Thu Nov 21 2019 openEuler Buildteam - 1.0.3-2 - Package init diff --git a/modify-automake-version.patch b/modify-automake-version.patch new file mode 100644 index 0000000000000000000000000000000000000000..2020df11c20ee1760760c1119898627c4e100b02 --- /dev/null +++ b/modify-automake-version.patch @@ -0,0 +1,42 @@ +From b3dc7f6af7f2812d5b4a42592976c5b9d7febaad Mon Sep 17 00:00:00 2001 +From: wangxiao65 +Date: Sun, 7 Feb 2021 12:02:08 +0800 +Subject: [PATCH] modify automake version +When Makefile.am is modified, automake needs to be executed. +if the version of automake in the compile enviroment is inconsistent +with the version specified in configure, the compile will fail. + +--- + configure | 2 +- + configure.ac | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure b/configure +index 13abc0a..da4fa78 100755 +--- a/configure ++++ b/configure +@@ -12762,7 +12762,7 @@ CC=$lt_save_CC + ac_config_headers="$ac_config_headers config.h" + + +-am__api_version='1.15' ++am__api_version='1.16' + + # Find a good install program. We prefer a C program (faster), + # so one script is as good as another. But avoid the broken or +diff --git a/configure.ac b/configure.ac +index 202ffc8..4ca143e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -48,7 +48,7 @@ LT_INIT([disable-static]) + AC_CONFIG_SRCDIR([common/flatpak-dir.c]) + AC_CONFIG_HEADERS([config.h]) + AC_CONFIG_MACRO_DIR([m4]) +-AM_INIT_AUTOMAKE([1.13.4 no-define no-dist-gzip dist-xz tar-ustar foreign subdir-objects]) ++AM_INIT_AUTOMAKE([1.16.2 no-define no-dist-gzip dist-xz tar-ustar foreign subdir-objects]) + AC_PROG_SED + AC_PROG_YACC + +-- +2.23.0 +