Skip to content
Snippets Groups Projects

Flatpak-related fixes

Merged Simon McVittie requested to merge wip/flatpak into master
1 file
+ 43
48
Compare changes
  • Side-by-side
  • Inline
+ 97
100
@@ -206,35 +206,26 @@ check_bwrap (const char *tools_dir,
return NULL;
}
static gchar *
check_flatpak_spawn (void)
static gboolean
check_launch_on_host (const char *launch_executable,
GError **error)
{
g_autoptr(GError) local_error = NULL;
GError **error = &local_error;
g_autofree gchar *spawn_exec = NULL;
g_autofree gchar *child_stdout = NULL;
g_autofree gchar *child_stderr = NULL;
int wait_status;
const char *spawn_test_argv[] =
const char *test_argv[] =
{
NULL,
"--host",
"--directory=/",
"--bus-name=org.freedesktop.Flatpak",
"--",
"true",
NULL
};
/* All known Flatpak runtimes have flatpak-spawn in the PATH */
spawn_exec = g_find_program_in_path ("flatpak-spawn");
if (spawn_exec == NULL
|| !g_file_test (spawn_exec, G_FILE_TEST_IS_EXECUTABLE))
return NULL;
spawn_test_argv[0] = spawn_exec;
test_argv[0] = launch_executable;
if (!g_spawn_sync (NULL, /* cwd */
(gchar **) spawn_test_argv,
(gchar **) test_argv,
NULL, /* environ */
G_SPAWN_DEFAULT,
NULL, NULL, /* child setup */
@@ -243,25 +234,24 @@ check_flatpak_spawn (void)
&wait_status,
error))
{
g_warning ("Cannot run flatpak-spawn: %s", local_error->message);
g_clear_error (&local_error);
return FALSE;
}
else if (wait_status != 0)
if (wait_status != 0)
{
g_warning ("Cannot run flatpak-spawn: wait status %d", wait_status);
g_warning ("Cannot run commands on host system: wait status %d",
wait_status);
if (child_stdout != NULL && child_stdout[0] != '\0')
g_warning ("Output:\n%s", child_stdout);
if (child_stderr != NULL && child_stderr[0] != '\0')
g_warning ("Diagnostic output:\n%s", child_stderr);
}
else
{
return g_steal_pointer (&spawn_exec);
return glnx_throw (error, "Unable to run a command on the host system");
}
return NULL;
return TRUE;
}
/*
@@ -723,7 +713,6 @@ static char *opt_steam_app_id = NULL;
static gboolean opt_gc_runtimes = TRUE;
static gboolean opt_generate_locales = TRUE;
static char *opt_home = NULL;
static gboolean opt_host_fallback = FALSE;
static char *opt_graphics_provider = NULL;
static char *graphics_provider_mount_point = NULL;
static gboolean opt_launcher = FALSE;
@@ -1021,9 +1010,6 @@ static GOptionEntry options[] =
G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_home,
"Use HOME as home directory. Implies --unshare-home. "
"[Default: $PRESSURE_VESSEL_HOME if set]", "HOME" },
{ "host-fallback", '\0',
G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_host_fallback,
"Run COMMAND on the host system if we cannot run it in a container.", NULL },
{ "host-ld-preload", '\0',
G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, &opt_host_ld_preload_cb,
"Add MODULE from the host system to LD_PRELOAD when executing COMMAND.",
@@ -1231,7 +1217,7 @@ main (int argc,
g_autoptr(FlatpakBwrap) adverb_args = NULL;
g_autofree gchar *adverb_in_container = NULL;
g_autoptr(FlatpakBwrap) wrapped_command = NULL;
g_autofree gchar *spawn_executable = NULL;
g_autofree gchar *launch_executable = NULL;
g_autofree gchar *bwrap_executable = NULL;
g_autoptr(GString) adjusted_ld_preload = g_string_new ("");
g_autofree gchar *cwd_p = NULL;
@@ -1255,6 +1241,7 @@ main (int argc,
g_str_equal,
g_free, NULL);
g_autofree char *lock_env_fd = NULL;
g_autoptr(GArray) pass_fds_through_adverb = g_array_new (FALSE, FALSE, sizeof (int));
my_pid = getpid ();
@@ -1625,76 +1612,33 @@ main (int argc,
/* If we are in a Flatpak environment we can't use bwrap directly */
if (is_flatpak_env)
{
g_debug ("Checking for flatpak-spawn...");
spawn_executable = check_flatpak_spawn ();
launch_executable = g_build_filename (tools_dir,
"pressure-vessel-launch",
NULL);
/* Assume "bwrap" to exist in the host system and to be in its PATH */
bwrap_executable = g_strdup ("bwrap");
/* If we can't launch a command on the host, just fail. */
if (!check_launch_on_host (launch_executable, error))
goto out;
}
else
{
g_debug ("Checking for bwrap...");
/* if this fails, it will warn */
bwrap_executable = check_bwrap (tools_dir, opt_only_prepare);
}
if (opt_test)
{
if ((is_flatpak_env && spawn_executable == NULL)
|| bwrap_executable == NULL)
{
ret = 1;
goto out;
}
else
{
if (spawn_executable != NULL)
g_debug ("OK (%s) (%s)", spawn_executable, bwrap_executable);
else
g_debug ("OK (%s)", bwrap_executable);
ret = 0;
goto out;
}
if (bwrap_executable == NULL)
goto out;
g_debug ("OK (%s)", bwrap_executable);
}
if ((is_flatpak_env && spawn_executable == NULL)
|| bwrap_executable == NULL)
if (opt_test)
{
/* TODO in a Flatpak environment, host is not what we expect it to be */
if (opt_host_fallback)
{
g_message ("Falling back to executing wrapped command directly");
if (opt_env_if_host != NULL)
{
for (i = 0; opt_env_if_host[i] != NULL; i++)
{
char *equals = strchr (opt_env_if_host[i], '=');
g_assert (equals != NULL);
*equals = '\0';
flatpak_bwrap_set_env (wrapped_command, opt_env_if_host[i],
equals + 1, TRUE);
}
}
flatpak_bwrap_finish (wrapped_command);
/* flatpak_bwrap_finish did this */
g_assert (g_ptr_array_index (wrapped_command->argv,
wrapped_command->argv->len - 1) == NULL);
execvpe (g_ptr_array_index (wrapped_command->argv, 0),
(char * const *) wrapped_command->argv->pdata,
wrapped_command->envp);
glnx_throw_errno_prefix (error, "execvpe %s",
(gchar *) g_ptr_array_index (wrapped_command->argv, 0));
goto out;
}
else
{
goto out;
}
ret = 0;
goto out;
}
if (!is_flatpak_env)
@@ -2090,8 +2034,9 @@ main (int argc,
g_hash_table_add (extra_locked_vars_to_inherit, g_strdup ("XDG_RUNTIME_DIR"));
/* The bwrap envp will be completely ignored when calling
* `flatpak-spawn --host`. For this reason we convert them to
* `--setenv`. */
* pv-launch. For this reason we convert them to `--setenv`.
* (TODO: Now that we're using pv-launch instead of flatpak-spawn,
* we could use --pass-env) */
for (i = 0; bwrap->envp != NULL && bwrap->envp[i] != NULL; i++)
{
g_auto(GStrv) split = g_strsplit (bwrap->envp[i], "=", 2);
@@ -2194,6 +2139,49 @@ main (int argc,
lock_env_fd = g_strdup_printf ("%d", lock_env_tmpf.fd);
flatpak_bwrap_add_fd (bwrap, glnx_steal_fd (&lock_env_tmpf.fd));
if (is_flatpak_env)
{
int userns_fd, userns2_fd, pidns_fd;
/* Tell the bwrap instance on the host to join the same user and pid
* namespaces as Steam in Flatpak. Otherwise, pid-based IPC between
* the Steam client and the game will fail.
*
* This is not expected to work if bwrap on the host is setuid,
* so it will not work for users of Debian, Arch linux-hardened, etc.,
* but it's better than nothing. */
userns_fd = open ("/run/.userns", O_RDONLY | O_CLOEXEC);
if (userns_fd >= 0)
{
g_array_append_val (pass_fds_through_adverb, userns_fd);
flatpak_bwrap_add_args_data_fd (bwrap, "--userns",
glnx_steal_fd (&userns_fd),
NULL);
userns2_fd = open_namespace_fd_if_needed ("/proc/self/ns/user",
"/run/.userns");
if (userns2_fd >= 0)
{
g_array_append_val (pass_fds_through_adverb, userns2_fd);
flatpak_bwrap_add_args_data_fd (bwrap, "--userns2",
glnx_steal_fd (&userns2_fd),
NULL);
}
}
pidns_fd = open ("/proc/self/ns/pid", O_RDONLY | O_CLOEXEC);
if (pidns_fd >= 0)
{
g_array_append_val (pass_fds_through_adverb, pidns_fd);
flatpak_bwrap_add_args_data_fd (bwrap, "--pidns",
glnx_steal_fd (&pidns_fd),
NULL);
}
}
if (opt_verbose)
{
g_message ("%s options before bundling:", bwrap_executable);
@@ -2254,6 +2242,13 @@ main (int argc,
}
}
for (i = 0; i < pass_fds_through_adverb->len; i++)
{
int fd = g_array_index (pass_fds_through_adverb, int, i);
flatpak_bwrap_add_arg_printf (bwrap, "--pass-fd=%d", fd);
}
flatpak_bwrap_add_arg_printf (bwrap, "--pass-fd=%s", lock_env_fd);
switch (opt_shell)
@@ -2325,24 +2320,26 @@ main (int argc,
if (is_flatpak_env)
{
/* Just use the envp from @bwrap */
g_autoptr(FlatpakBwrap) flatpak_spawn = flatpak_bwrap_new (flatpak_bwrap_empty_env);
flatpak_bwrap_add_arg (flatpak_spawn, spawn_executable);
flatpak_bwrap_add_arg (flatpak_spawn, "--host");
g_autoptr(FlatpakBwrap) launch_on_host = flatpak_bwrap_new (flatpak_bwrap_empty_env);
flatpak_bwrap_add_arg (launch_on_host, launch_executable);
flatpak_bwrap_add_arg (launch_on_host, "--bus-name=org.freedesktop.Flatpak");
for (i = 0; i < bwrap->fds->len; i++)
{
g_autofree char *fd_str = g_strdup_printf ("--forward-fd=%d",
g_array_index (bwrap->fds, int, i));
flatpak_bwrap_add_arg (flatpak_spawn, fd_str);
flatpak_bwrap_add_arg (launch_on_host, fd_str);
}
/* Change the current working directory where flatpak-spawn will run.
/* Change the current working directory where pv-launch will run bwrap.
* Bwrap will then set its directory by itself. For this reason here
* we just need a directory that it's known to exist. */
flatpak_bwrap_add_arg (flatpak_spawn, "--directory=/");
flatpak_bwrap_add_arg (launch_on_host, "--directory=/");
flatpak_bwrap_add_arg (launch_on_host, "--");
flatpak_bwrap_append_bwrap (flatpak_spawn, bwrap);
flatpak_bwrap_append_bwrap (launch_on_host, bwrap);
g_clear_pointer (&bwrap, flatpak_bwrap_free);
bwrap = g_steal_pointer (&flatpak_spawn);
bwrap = g_steal_pointer (&launch_on_host);
}
if (opt_verbose)
Loading