Skip to content

Commit

Permalink
run: Convert all environment variables into bwrap arguments
Browse files Browse the repository at this point in the history
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: GHSA-4ppf-fxf6-vxg2
  • Loading branch information
smcv authored and alexlarsson committed Jan 14, 2021
1 parent fe95ef6 commit 6d1773d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 18 deletions.
3 changes: 3 additions & 0 deletions common/flatpak-bwrap-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
43 changes: 43 additions & 0 deletions common/flatpak-bwrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down
32 changes: 14 additions & 18 deletions common/flatpak-run.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit 6d1773d

Please sign in to comment.