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
This commit is contained in:
Simon McVittie
2021-01-10 16:11:28 +00:00
committed by Alexander Larsson
parent fe95ef6fad
commit 6d1773d2a5
3 changed files with 60 additions and 18 deletions

View File

@@ -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,

View File

@@ -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,

View File

@@ -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),