Skip to content
Snippets Groups Projects
Commit dbe5cce8 authored by Simon McVittie's avatar Simon McVittie
Browse files

pv-wrap: Factor out checks for running under Flatpak


wrap.c is too big, and main() in particular is too big, so anything we
can reasonably factor out here is quite welcome.

Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
parent 65afa20d
No related branches found
No related tags found
1 merge request!292Improve Flatpak sub-sandboxing support
......@@ -205,6 +205,8 @@ executable(
'runtime.c',
'runtime.h',
'wrap.c',
'wrap-flatpak.c',
'wrap-flatpak.h',
'wrap-setup.c',
'wrap-setup.h',
] + enums,
......
/*
* Copyright © 2020-2021 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "wrap-flatpak.h"
#include "libglnx/libglnx.h"
#include "utils.h"
static gboolean
check_launch_on_host (const char *launch_executable,
GError **error)
{
g_autofree gchar *child_stdout = NULL;
g_autofree gchar *child_stderr = NULL;
int wait_status;
const char *test_argv[] =
{
NULL,
"--bus-name=org.freedesktop.Flatpak",
"--",
"true",
NULL
};
test_argv[0] = launch_executable;
if (!g_spawn_sync (NULL, /* cwd */
(gchar **) test_argv,
NULL, /* environ */
G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
NULL, NULL, /* child setup */
&child_stdout,
&child_stderr,
&wait_status,
error))
{
return FALSE;
}
if (wait_status != 0)
{
pv_log_failure ("Cannot run commands on host system: wait status %d",
wait_status);
if (child_stdout != NULL && child_stdout[0] != '\0')
pv_log_failure ("Output:\n%s", child_stdout);
if (child_stderr != NULL && child_stderr[0] != '\0')
pv_log_failure ("Diagnostic output:\n%s", child_stderr);
return glnx_throw (error, "Unable to run a command on the host system");
}
return TRUE;
}
/*
* pv_wrap_check_flatpak:
* @tools_dir: Path to .../pressure-vessel/bin/
* @subsandbox_out: (out) (not optional) (nullable): Used to return
* an adverb command that will launch its arguments in a sub-sandbox,
* or %NULL if not using sub-sandboxing
* @run_on_host_out: (out) (not optional) (nullable): Used to return
* an adverb command that will launch its arguments on the host system,
* or %NULL if not using sandbox escape
*
* Check that we are running under Flatpak and can launch the game somehow.
* On success, exactly one of the `(out)` parameters will be set to non-%NULL.
*
* Returns: %TRUE on success
*/
gboolean
pv_wrap_check_flatpak (const char *tools_dir,
FlatpakBwrap **subsandbox_out,
FlatpakBwrap **run_on_host_out,
GError **error)
{
g_autoptr(FlatpakBwrap) subsandbox = NULL;
g_autoptr(FlatpakBwrap) run_on_host = NULL;
g_autofree gchar *launch_executable = NULL;
g_return_val_if_fail (tools_dir != NULL, FALSE);
g_return_val_if_fail (subsandbox_out != NULL, FALSE);
g_return_val_if_fail (*subsandbox_out == NULL, FALSE);
g_return_val_if_fail (run_on_host_out != NULL, FALSE);
g_return_val_if_fail (*run_on_host_out == NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
launch_executable = g_build_filename (tools_dir,
"pressure-vessel-launch",
NULL);
/* Deliberately not documented: only people who are in a position
* to run their own modified versions of Flatpak and pressure-vessel
* should be using this, and those people can find this in the
* source code */
if (g_getenv ("PRESSURE_VESSEL_FLATPAK_PR4018") != NULL)
{
g_warning ("Assuming your version of Flatpak contains unmerged "
"changes (#4018, #4125, #4126, #4093)");
/* Use a sub-sandbox */
subsandbox = flatpak_bwrap_new (flatpak_bwrap_empty_env);
flatpak_bwrap_add_arg (subsandbox, launch_executable);
/* Tell pressure-vessel-launch to send its whole environment
* to the subsandbox, except for the parts that we edit later.
* This effectively matches bwrap's behaviour. */
flatpak_bwrap_add_arg (subsandbox, "--pass-env-matching=*");
flatpak_bwrap_add_arg (subsandbox,
"--bus-name=org.freedesktop.portal.Flatpak");
}
/* Also deliberately not documented */
else if (g_getenv ("PRESSURE_VESSEL_FLATPAK_SANDBOX_ESCAPE") != NULL)
{
g_warning ("Assuming permissions have been set to allow Steam "
"to escape from the Flatpak sandbox");
/* If we have permission to escape from the sandbox, we'll do that,
* and launch bwrap that way */
run_on_host = flatpak_bwrap_new (flatpak_bwrap_empty_env);
flatpak_bwrap_add_arg (run_on_host,
launch_executable);
flatpak_bwrap_add_arg (run_on_host,
"--bus-name=org.freedesktop.Flatpak");
/* If we can't launch a command on the host, just fail. */
if (!check_launch_on_host (launch_executable, error))
return FALSE;
}
else
{
return glnx_throw (error,
"pressure-vessel (SteamLinuxRuntime) cannot be run "
"in a Flatpak environment. For Proton 5.13+, "
"unofficial community builds that do not use "
"pressure-vessel are available.");
}
/* Exactly one of them is non-NULL on success */
g_assert ((subsandbox != NULL) + (run_on_host != NULL) == 1);
*subsandbox_out = g_steal_pointer (&subsandbox);
*run_on_host_out = g_steal_pointer (&run_on_host);
return TRUE;
}
/*
* Copyright © 2020-2021 Collabora Ltd.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include "libglnx/libglnx.h"
#include "flatpak-bwrap-private.h"
gboolean pv_wrap_check_flatpak (const char *tools_dir,
FlatpakBwrap **flatpak_subsandbox,
FlatpakBwrap **flatpak_run_on_host,
GError **error);
......@@ -43,6 +43,7 @@
#include "flatpak-utils-private.h"
#include "runtime.h"
#include "utils.h"
#include "wrap-flatpak.h"
#include "wrap-interactive.h"
#include "wrap-setup.h"
......@@ -208,54 +209,6 @@ check_bwrap (const char *tools_dir,
return NULL;
}
static gboolean
check_launch_on_host (const char *launch_executable,
GError **error)
{
g_autofree gchar *child_stdout = NULL;
g_autofree gchar *child_stderr = NULL;
int wait_status;
const char *test_argv[] =
{
NULL,
"--bus-name=org.freedesktop.Flatpak",
"--",
"true",
NULL
};
test_argv[0] = launch_executable;
if (!g_spawn_sync (NULL, /* cwd */
(gchar **) test_argv,
NULL, /* environ */
G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
NULL, NULL, /* child setup */
&child_stdout,
&child_stderr,
&wait_status,
error))
{
return FALSE;
}
if (wait_status != 0)
{
pv_log_failure ("Cannot run commands on host system: wait status %d",
wait_status);
if (child_stdout != NULL && child_stdout[0] != '\0')
pv_log_failure ("Output:\n%s", child_stdout);
if (child_stderr != NULL && child_stderr[0] != '\0')
pv_log_failure ("Diagnostic output:\n%s", child_stderr);
return glnx_throw (error, "Unable to run a command on the host system");
}
return TRUE;
}
/* Nvidia Vulkan ray-tracing requires to load the `nvidia_uvm.ko` kernel
* module, and this is usually done in `libcuda.so.1` by running the setuid
* binary `nvidia-modprobe`. But when we are inside a container we don't bind
......@@ -1368,7 +1321,6 @@ main (int argc,
g_autoptr(FlatpakBwrap) argv_in_container = NULL;
g_autoptr(FlatpakBwrap) final_argv = NULL;
g_autoptr(FlatpakExports) exports = NULL;
g_autofree gchar *launch_executable = NULL;
g_autofree gchar *bwrap_executable = NULL;
g_autofree gchar *cwd_p = NULL;
g_autofree gchar *cwd_l = NULL;
......@@ -1797,60 +1749,14 @@ main (int argc,
/* If we are in a Flatpak environment we can't use bwrap directly */
if (is_flatpak_env)
{
if (!pv_wrap_check_flatpak (tools_dir,
&flatpak_subsandbox,
&flatpak_run_on_host,
error))
goto out;
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");
/* Deliberately not documented: only people who are in a position
* to run their own modified versions of Flatpak and pressure-vessel
* should be using this, and those people can find this in the
* source code */
if (g_getenv ("PRESSURE_VESSEL_FLATPAK_PR4018") != NULL)
{
g_warning ("Assuming your version of Flatpak contains unmerged "
"changes (#4018, #4125, #4126, #4093)");
/* Use a sub-sandbox */
flatpak_subsandbox = flatpak_bwrap_new (flatpak_bwrap_empty_env);
flatpak_bwrap_add_arg (flatpak_subsandbox,
launch_executable);
/* Tell pressure-vessel-launch to send its whole environment
* to the subsandbox, except for the parts that we edit later.
* This effectively matches bwrap's behaviour. */
flatpak_bwrap_add_arg (flatpak_subsandbox, "--pass-env-matching=*");
flatpak_bwrap_add_arg (flatpak_subsandbox,
"--bus-name=org.freedesktop.portal.Flatpak");
}
/* Also deliberately not documented */
else if (g_getenv ("PRESSURE_VESSEL_FLATPAK_SANDBOX_ESCAPE") != NULL)
{
g_warning ("Assuming permissions have been set to allow Steam "
"to escape from the Flatpak sandbox");
/* If we have permission to escape from the sandbox, we'll do that,
* and launch bwrap that way */
flatpak_run_on_host = flatpak_bwrap_new (flatpak_bwrap_empty_env);
flatpak_bwrap_add_arg (flatpak_run_on_host,
launch_executable);
flatpak_bwrap_add_arg (flatpak_run_on_host,
"--bus-name=org.freedesktop.Flatpak");
/* If we can't launch a command on the host, just fail. */
if (!check_launch_on_host (launch_executable, error))
goto out;
}
else
{
glnx_throw (error,
"pressure-vessel (SteamLinuxRuntime) cannot be run "
"in a Flatpak environment. For Proton 5.13+, "
"unofficial community builds that do not use "
"pressure-vessel are available.");
goto out;
}
}
else
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment