summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2021-01-10 16:11:28 +0000
committerAlexander Larsson <alexander.larsson@gmail.com>2021-01-14 09:33:24 +0100
commit6d1773d2a54dde9b099043f07a2094a4f1c2f486 (patch)
tree1e66141b2ca8aa84f47e70a2bc9f9966859c7a3b
parentfe95ef6fad6f87bafdf31c3069386de3bf646e78 (diff)
downloadflatpak-6d1773d2a54dde9b099043f07a2094a4f1c2f486.tar.gz
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 <smcv@collabora.com> Part-of: https://github.com/flatpak/flatpak/security/advisories/GHSA-4ppf-fxf6-vxg2
-rw-r--r--common/flatpak-bwrap-private.h3
-rw-r--r--common/flatpak-bwrap.c43
-rw-r--r--common/flatpak-run.c32
3 files changed, 60 insertions, 18 deletions
diff --git a/common/flatpak-bwrap-private.h b/common/flatpak-bwrap-private.h
index 92d6e9de..6c31b789 100644
--- a/common/flatpak-bwrap-private.h
+++ b/common/flatpak-bwrap-private.h
@@ -43,6 +43,8 @@ void flatpak_bwrap_unset_env (FlatpakBwrap *bwrap,
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 (FlatpakBwrap *bwrap,
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,
diff --git a/common/flatpak-bwrap.c b/common/flatpak-bwrap.c
index c45154cc..6a02e868 100644
--- a/common/flatpak-bwrap.c
+++ b/common/flatpak-bwrap.c
@@ -109,6 +109,18 @@ flatpak_bwrap_add_arg (FlatpakBwrap *bwrap, const char *arg)
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)
{
@@ -274,6 +286,37 @@ flatpak_bwrap_add_bind_arg (FlatpakBwrap *bwrap,
}
}
+/*
+ * 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,
diff --git a/common/flatpak-run.c b/common/flatpak-run.c
index e8e49a7f..c69f2c38 100644
--- a/common/flatpak-run.c
+++ b/common/flatpak-run.c
@@ -1463,24 +1463,6 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap,
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");
- }
-
- if (g_environ_getenv (bwrap->envp, "TMPDIR") != NULL)
- {
- /* TMPDIR is overridden for setuid helper, so pass it as cmdline arg */
- flatpak_bwrap_add_args (bwrap,
- "--setenv", "TMPDIR", g_environ_getenv (bwrap->envp, "TMPDIR"),
- NULL);
- flatpak_bwrap_unset_env (bwrap, "TMPDIR");
- }
-
/* 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))
@@ -4068,6 +4050,8 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
command = default_command;
}
+ flatpak_bwrap_envp_to_args (bwrap);
+
if (!flatpak_bwrap_bundle_args (bwrap, 1, -1, FALSE, error))
return FALSE;
@@ -4098,6 +4082,12 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
/* We use LEAVE_DESCRIPTORS_OPEN to work around dead-lock, see flatpak_close_fds_workaround */
spawn_flags |= G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
+ /* 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,
@@ -4125,6 +4115,12 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
* we do want to allow inheriting fds into flatpak run. */
flatpak_bwrap_child_setup (bwrap->fds, FALSE);
+ /* 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),