Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • steamrt/steam-runtime-tools
1 result
Show changes
Commits on Source (62)
Showing
with 1672 additions and 290 deletions
......@@ -29,6 +29,8 @@
* meet every requirement.
*/
#include <steam-runtime-tools/glib-backports-internal.h>
#include <steam-runtime-tools/steam-runtime-tools.h>
#include <errno.h>
......@@ -42,7 +44,12 @@
#include <glib.h>
#include <glib-object.h>
#include <steam-runtime-tools/bwrap-internal.h>
#include <steam-runtime-tools/container-internal.h>
#include <steam-runtime-tools/cpu-feature-internal.h>
#include <steam-runtime-tools/log-internal.h>
#include <steam-runtime-tools/resolve-in-sysroot-internal.h>
#include <steam-runtime-tools/steam-internal.h>
#include <steam-runtime-tools/utils-internal.h>
#define X86_FEATURES_REQUIRED (SRT_X86_FEATURE_X86_64 \
......@@ -53,10 +60,12 @@ enum
{
OPTION_HELP = 1,
OPTION_VERSION,
OPTION_VERBOSE = 'v',
};
struct option long_options[] =
{
{ "verbose", no_argument, NULL, OPTION_VERBOSE },
{ "version", no_argument, NULL, OPTION_VERSION },
{ "help", no_argument, NULL, OPTION_HELP },
{ NULL, 0, NULL, 0 }
......@@ -88,25 +97,127 @@ check_x86_features (SrtX86FeatureFlags features)
return ((features & X86_FEATURES_REQUIRED) == X86_FEATURES_REQUIRED);
}
static const char need_unprivileged_userns_clone[] =
"Steam now requires user namespaces to be enabled.\n"
"\n"
"The sysctl /proc/sys/kernel/unprivileged_userns_clone should be set to 1.\n"
"\n"
"This requirement is the same as for Flatpak, which has more detailed\n"
"information available:\n"
"https://github.com/flatpak/flatpak/wiki/User-namespace-requirements\n"
;
static const char need_max_user_namespaces[] =
"Steam now requires user namespaces to be enabled.\n"
"\n"
"The sysctl /proc/sys/user/max_user_namespaces should be set to at least 100.\n"
"\n"
"This requirement is the same as for Flatpak, which has more detailed\n"
"information available:\n"
"https://github.com/flatpak/flatpak/wiki/User-namespace-requirements\n"
;
static const char cannot_run_bwrap[] =
"Steam now requires user namespaces to be enabled.\n"
"\n"
"This requirement is the same as for Flatpak, which has more detailed\n"
"information available:\n"
"https://github.com/flatpak/flatpak/wiki/User-namespace-requirements\n"
;
static const char installed_in_usr[] =
"Steam is intended to install into your home directory, typically\n"
"~/.local/share/Steam. It cannot be installed below /usr.\n"
;
static const char flatpak_needs_unprivileged_bwrap[] =
"The unofficial Steam Flatpak app now requires user namespaces to be\n"
"enabled.\n"
"\n"
"Check that the bubblewrap executable used by Flatpak, usually\n"
"/usr/bin/bwrap or /usr/libexec/flatpak-bwrap, is not setuid root.\n"
"\n"
"If the file /proc/sys/kernel/unprivileged_userns_clone exists, check that\n"
"it contains value 1.\n"
"\n"
"If the file /proc/sys/user/max_user_namespaces exists, check that its\n"
"value is at least 100.\n"
"\n"
"For more details, please see:\n"
"https://github.com/flatpak/flatpak/wiki/User-namespace-requirements\n"
;
static const char flatpak_too_old[] =
"The unofficial Steam Flatpak app requires Flatpak 1.12.0 or later.\n"
"Using the latest stable release of Flatpak is recommended.\n"
;
static const char flatpak_needs_display[] =
"The unofficial Steam Flatpak app requires a correctly-configured desktop\n"
"session, which must provide the DISPLAY environment variable to the\n"
"D-Bus session bus activation environment.\n"
"\n"
"On systems that use systemd --user, the DISPLAY environment variable must\n"
"also be present in the systemd --user activation environment.\n"
"\n"
"This is usually achieved by running:\n"
"\n"
" dbus-update-activation-environment DISPLAY\n"
"\n"
"during desktop environment startup.\n"
"\n"
"For more details, please see:\n"
"https://github.com/ValveSoftware/steam-for-linux/issues/10554\n"
;
/* This one is the generic "something went wrong" message for Flatpak,
* so we can't be particularly specific here. */
static const char flatpak_needs_subsandbox[] =
"The unofficial Steam Flatpak app requires a working D-Bus session bus\n"
"and flatpak-portal service.\n"
"\n"
"Running this command might provide more diagnostic information:\n"
"\n"
" flatpak run --command=bash com.valvesoftware.Steam -c 'flatpak-spawn -vv true'\n"
;
int
main (int argc,
char **argv)
{
FILE *original_stdout = NULL;
GError *error = NULL;
g_autoptr(FILE) original_stdout = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(SrtContainerInfo) container_info = NULL;
g_autoptr(SrtSubprocessRunner) runner = NULL;
g_autoptr(SrtSysroot) sysroot = NULL;
SrtContainerType container_type;
glnx_autofd int original_stdout_fd = -1;
SrtX86FeatureFlags x86_features = SRT_X86_FEATURE_NONE;
SrtX86FeatureFlags known = SRT_X86_FEATURE_NONE;
SrtSteamIssues steam_issues;
const gchar *output = NULL;
gchar *version = NULL;
const char *prefix = NULL;
const char *pkglibexecdir = NULL;
int opt;
int exit_code = EXIT_SUCCESS;
SrtLogFlags log_flags;
SrtBwrapIssues bwrap_issues;
SrtFlatpakIssues flatpak_issues;
_srt_setenv_disable_gio_modules ();
log_flags = SRT_LOG_FLAGS_OPTIONALLY_JOURNAL | SRT_LOG_FLAGS_DIVERT_STDOUT;
while ((opt = getopt_long (argc, argv, "", long_options, NULL)) != -1)
while ((opt = getopt_long (argc, argv, "v", long_options, NULL)) != -1)
{
switch (opt)
{
case OPTION_VERBOSE:
if (log_flags & SRT_LOG_FLAGS_INFO)
log_flags |= SRT_LOG_FLAGS_DEBUG;
else
log_flags |= SRT_LOG_FLAGS_INFO;
break;
case OPTION_VERSION:
/* Output version number as YAML for machine-readability,
* inspired by `ostree --version` and `docker version` */
......@@ -131,17 +242,28 @@ main (int argc,
if (optind != argc)
usage (EX_USAGE);
/* stdout is reserved for machine-readable output, so avoid having
* things like g_debug() pollute it. */
original_stdout = _srt_divert_stdout_to_stderr (&error);
if (original_stdout == NULL)
if (!_srt_util_set_glib_log_handler ("steam-runtime-check-requirements",
G_LOG_DOMAIN, log_flags,
&original_stdout_fd, NULL, &error))
{
g_warning ("%s", error->message);
g_clear_error (&error);
return EXIT_FAILURE;
}
original_stdout = fdopen (original_stdout_fd, "w");
if (original_stdout == NULL)
{
g_warning ("Unable to create a stdio wrapper for fd %d: %s",
original_stdout_fd, g_strerror (errno));
return EXIT_FAILURE;
}
else
{
original_stdout_fd = -1; /* ownership taken, do not close */
}
_srt_unblock_signals ();
x86_features = _srt_feature_get_x86_flags (NULL, &known);
......@@ -157,6 +279,137 @@ main (int argc,
goto out;
}
prefix = _srt_find_myself (NULL, &pkglibexecdir, &error);
if (prefix == NULL)
{
g_warning ("Internal error: %s", error->message);
g_clear_error (&error);
}
runner = _srt_subprocess_runner_new ();
sysroot = _srt_sysroot_new_direct (&error);
if (sysroot == NULL)
{
g_warning ("Internal error: %s", error->message);
g_clear_error (&error);
container_type = SRT_CONTAINER_TYPE_UNKNOWN;
}
else
{
container_info = _srt_check_container (sysroot);
container_type = srt_container_info_get_container_type (container_info);
}
switch (container_type)
{
case SRT_CONTAINER_TYPE_PRESSURE_VESSEL:
g_info ("Already under pressure-vessel, not checking bwrap functionality.");
break;
case SRT_CONTAINER_TYPE_FLATPAK:
_srt_container_info_check_issues (container_info, sysroot, runner);
flatpak_issues = srt_container_info_get_flatpak_issues (container_info);
if (flatpak_issues & SRT_FLATPAK_ISSUES_SUBSANDBOX_LIMITED_BY_SETUID_BWRAP)
{
output = flatpak_needs_unprivileged_bwrap;
exit_code = EX_OSERR;
goto out;
}
if (flatpak_issues & SRT_FLATPAK_ISSUES_TOO_OLD)
{
output = flatpak_too_old;
exit_code = EX_OSERR;
goto out;
}
if (flatpak_issues & SRT_FLATPAK_ISSUES_SUBSANDBOX_DID_NOT_INHERIT_DISPLAY)
{
output = flatpak_needs_display;
exit_code = EX_OSERR;
goto out;
}
if (flatpak_issues & (SRT_FLATPAK_ISSUES_SUBSANDBOX_UNAVAILABLE
| SRT_FLATPAK_ISSUES_SUBSANDBOX_TIMED_OUT))
{
output = flatpak_needs_subsandbox;
exit_code = EX_OSERR;
goto out;
}
break;
case SRT_CONTAINER_TYPE_DOCKER:
case SRT_CONTAINER_TYPE_PODMAN:
case SRT_CONTAINER_TYPE_SNAP:
case SRT_CONTAINER_TYPE_UNKNOWN:
case SRT_CONTAINER_TYPE_NONE:
default:
if (sysroot != NULL && pkglibexecdir != NULL)
{
g_autofree gchar *bwrap = NULL;
g_autofree gchar *message = NULL;
bwrap_issues = _srt_check_bwrap_issues (sysroot, runner, &bwrap, &message);
if (bwrap != NULL)
{
g_info ("Found bwrap at \"%s\"", bwrap);
g_warn_if_fail (!(bwrap_issues & SRT_BWRAP_ISSUES_CANNOT_RUN));
if (bwrap_issues & SRT_BWRAP_ISSUES_SETUID)
g_info ("\"%s\" is setuid root", bwrap);
if (bwrap_issues & SRT_BWRAP_ISSUES_SYSTEM)
g_info ("\"%s\" is a system copy", bwrap);
}
else
{
if (bwrap_issues & SRT_BWRAP_ISSUES_NO_UNPRIVILEGED_USERNS_CLONE)
{
output = need_unprivileged_userns_clone;
exit_code = EX_OSERR;
goto out;
}
if (bwrap_issues & SRT_BWRAP_ISSUES_MAX_USER_NAMESPACES_ZERO)
{
output = need_max_user_namespaces;
exit_code = EX_OSERR;
goto out;
}
g_warn_if_fail (bwrap_issues & SRT_BWRAP_ISSUES_CANNOT_RUN);
g_warning ("%s", message);
output = cannot_run_bwrap;
exit_code = EX_OSERR;
goto out;
}
}
else
{
_srt_log_warning ("Unable to locate srt-bwrap or open root "
"directory, not checking functionality.");
}
}
steam_issues = _srt_steam_check (_srt_const_strv (environ),
~SRT_STEAM_ISSUES_DESKTOP_FILE_RELATED,
NULL);
if (steam_issues & SRT_STEAM_ISSUES_INSTALLED_IN_USR)
{
output = installed_in_usr;
exit_code = EX_OSERR;
goto out;
}
g_info ("No problems detected");
out:
if (output != NULL)
{
......@@ -167,10 +420,8 @@ out:
g_warning ("Unable to write final newline: %s", g_strerror (errno));
}
if (fclose (original_stdout) != 0)
if (fclose (g_steal_pointer (&original_stdout)) != 0)
g_warning ("Unable to close stdout: %s", g_strerror (errno));
g_free (version);
return exit_code;
}
......@@ -20,17 +20,23 @@ steam-runtime-check-requirements - perform checks to ensure that the Steam clien
# OPTIONS
**--verbose**, **-v**
: Show more information on standard error.
If repeated, produce debug output.
**--version**
: Instead of performing the checks, write in output the version number as
YAML.
# OUTPUT
If all the Steam client requirements are met the output will be empty.
If all the Steam client requirements are met the output on standard output
will be empty.
Otherwise if some of the checks fails, the output will have a human-readable
message explaining what failed.
Otherwise if some of the checks fails, the output on standard output
will have a human-readable message explaining what failed.
Unstructured diagnostic messages appear on standard error.
# EXIT STATUS
......
......@@ -22,6 +22,7 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
srt_bin = []
uninstalled_env_vars += {'SRT_BIN_PATH': meson.current_build_dir()}
# Programs that only need glibc
libc_programs = [
......@@ -172,6 +173,18 @@ if build_man_pages
endforeach
endif
bubblewrap_subproject = subproject(
'bubblewrap',
default_options : [
'build_rpath=' + pkglibexec_rpath,
'bwrapdir=' + pkglibexecdir,
'install_rpath=' + pkglibexec_rpath,
'program_prefix=srt-',
'tests=false',
],
)
srt_bin += bubblewrap_subproject.get_variable('bwrap')
test_depends += srt_bin
# vim:set sw=2 sts=2 et:
......@@ -746,12 +746,18 @@ jsonify_container (JsonBuilder *builder,
{
g_autoptr(SrtContainerInfo) container_info = srt_system_info_check_container (info);
SrtContainerType type = SRT_CONTAINER_TYPE_UNKNOWN;
SrtBwrapIssues bwrap_issues;
const char *bwrap_messages;
const char *bwrap_path;
const gchar *flatpak_version = NULL;
const gchar *host_directory = NULL;
type = srt_container_info_get_container_type (container_info);
flatpak_version = srt_container_info_get_flatpak_version (container_info);
host_directory = srt_container_info_get_container_host_directory (container_info);
bwrap_issues = srt_container_info_get_bwrap_issues (container_info);
bwrap_path = srt_container_info_get_bwrap_path (container_info);
bwrap_messages = srt_container_info_get_bwrap_messages (container_info);
json_builder_set_member_name (builder, "container");
json_builder_begin_object (builder);
......@@ -759,14 +765,51 @@ jsonify_container (JsonBuilder *builder,
json_builder_set_member_name (builder, "type");
jsonify_enum (builder, SRT_TYPE_CONTAINER_TYPE, type);
if (type != SRT_CONTAINER_TYPE_NONE)
switch (type)
{
if (flatpak_version != NULL)
{
json_builder_set_member_name (builder, "flatpak_version");
json_builder_add_string_value (builder, flatpak_version);
}
case SRT_CONTAINER_TYPE_FLATPAK:
json_builder_set_member_name (builder, "flatpak_issues");
json_builder_begin_array (builder);
jsonify_flags (builder, SRT_TYPE_FLATPAK_ISSUES,
srt_container_info_get_flatpak_issues (container_info));
json_builder_end_array (builder);
if (flatpak_version != NULL)
{
json_builder_set_member_name (builder, "flatpak_version");
json_builder_add_string_value (builder, flatpak_version);
}
break;
case SRT_CONTAINER_TYPE_DOCKER:
case SRT_CONTAINER_TYPE_PODMAN:
case SRT_CONTAINER_TYPE_PRESSURE_VESSEL:
case SRT_CONTAINER_TYPE_SNAP:
case SRT_CONTAINER_TYPE_UNKNOWN:
case SRT_CONTAINER_TYPE_NONE:
default:
json_builder_set_member_name (builder, "bubblewrap_issues");
json_builder_begin_array (builder);
jsonify_flags (builder, SRT_TYPE_BWRAP_ISSUES, bwrap_issues);
json_builder_end_array (builder);
/* Don't log the path to bwrap in the common case that it's
* our bundled one and it worked successfully */
if (bwrap_path != NULL
&& (verbose || bwrap_issues != SRT_BWRAP_ISSUES_NONE))
{
json_builder_set_member_name (builder, "bubblewrap_path");
json_builder_add_string_value (builder, bwrap_path);
}
if (bwrap_messages != NULL)
_srt_json_builder_add_array_of_lines (builder, "bubblewrap_messages", bwrap_messages);
break;
}
if (type != SRT_CONTAINER_TYPE_NONE)
{
json_builder_set_member_name (builder, "host");
json_builder_begin_object (builder);
{
......
......@@ -417,6 +417,29 @@ keys:
**unknown** (if we appear to be in a container but the type is
unknown), or **none** (if we do not appear to be in a container).
**bubblewrap_issues**
: An array of flags describing potential problems with **bwrap**(1),
such as not having the necessary system configuration to be able
to create new user namespaces as an unprivileged user.
This key is not provided if the container **type** is **flatpak**,
because we do not expect to be able to run **bwrap**(1)
successfully inside a Flatpak sandbox.
**bubblewrap_path**
: The path to the **bwrap**(1) executable that was used.
This key is not provided unless either **--verbose** was
used, or a problem was detected.
**bubblewrap_messages**
: Human-readable array of lines with diagnostic messages related
to **bwrap**(1), if any.
This key is not provided if the array would be empty.
**flatpak_issues**
: An array of flags describing potential problems with Flatpak,
such as a version that is too old or cannot create subsandboxes.
This key is not provided if the container **type** is not **flatpak**.
**flatpak_version**
: The version string describing the Flatpak container. This key is
optional and is not provided if it could not be determined or if the
......
......@@ -226,7 +226,7 @@ class Environment:
] + args,
)
def setup(self, args: List[str]) -> None:
def deps(self, args: List[str]) -> None:
self.populate_depots()
for suite, image in self.oci_images.items():
......@@ -236,10 +236,12 @@ class Environment:
elif self.docker:
subprocess.run(self.docker + ['pull', image], check=True)
def setup(self, args: List[str]) -> None:
subprocess.run(
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / 'host'),
'-Db_lundef=false',
'-Db_sanitize=address,undefined',
......@@ -262,6 +264,7 @@ class Environment:
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / 'i386'),
'-Db_lundef=false',
'-Db_sanitize=address,undefined',
......@@ -284,6 +287,7 @@ class Environment:
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / 'host-no-asan'),
'-Dbin=true',
'-Dlibcurl_compat=true',
......@@ -302,6 +306,7 @@ class Environment:
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / 'coverage'),
'-Db_coverage=true',
'-Dbin=true',
......@@ -319,6 +324,7 @@ class Environment:
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / 'doc'),
'-Dgtk_doc=enabled',
'-Dman=enabled',
......@@ -331,6 +337,7 @@ class Environment:
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / 'clang'),
'--native-file=build-aux/meson/clang.txt',
'-Db_lundef=false',
......@@ -355,6 +362,7 @@ class Environment:
[
'meson',
'setup',
'--wipe',
str(self.abs_builddir_parent / f'{suite}-x86_64'),
'-Dbin=true',
'-Dlibcurl_compat=true',
......@@ -518,7 +526,15 @@ def main() -> int:
parser.add_argument('--srcdir', default='.')
parser.add_argument(
'command',
choices=('setup', 'clean', 'build', 'test', 'install', 'all'),
choices=(
'deps',
'setup',
'clean',
'build',
'test',
'install',
'all',
),
)
parser.add_argument('args', nargs=argparse.REMAINDER)
args = parser.parse_args()
......@@ -529,7 +545,9 @@ def main() -> int:
srcdir=args.srcdir,
)
if args.command == 'setup':
if args.command == 'deps':
env.deps(args.args)
elif args.command == 'setup':
env.setup(args.args)
elif args.command == 'clean':
env.clean(args.args)
......
......@@ -49,6 +49,7 @@ def setup(args):
# type: (typing.Any) -> None
common_options = [
'--wipe',
'-Dgtk_doc=disabled',
'-Dlibcurl_compat=true',
'-Dman=disabled',
......
steam-runtime-tools (0.20240219.0) UNRELEASED; urgency=medium
steam-runtime-tools (0.20240313.0) UNRELEASED; urgency=medium
* steam-runtime-system-info:
- Do the same functional tests on bwrap that were previously only
done in s-r-check-requirements (steamrt/tasks#406)
- Do a functional test on flatpak-portal subsandboxes
(steamrt/tasks#406)
* steam-runtime-check-requirements:
- Emit more specific messages for several common bwrap problems
(steamrt/tasks#406)
- Detect several common Flatpak problems (steamrt/tasks#406)
* pressure-vessel:
- Treat $BWRAP as less-preferred than pv-bwrap. The order we try is now:
$PRESSURE_VESSEL_BWRAP > pv-bwrap > $BWRAP > system bwrap
instead of the previous:
$PRESSURE_VESSEL_BWRAP > $BWRAP > pv-bwrap > system bwrap
* tests: Improve unit test coverage
-- Simon McVittie <smcv@collabora.com> Wed, 13 Mar 2024 15:02:02 +0000
steam-runtime-tools (0.20240306.0) steamrt; urgency=medium
* steam-runtime-check-requirements:
- Adjust wording of messages (steamrt/tasks#406)
* pressure-vessel:
- Update libcapsule to a version that works around smaller-than-default
stack limits by using heap allocation (steam-runtime#653)
- Work around more AppArmor profile issues in snapd
(steamrt/tasks#408, canonical/steam-snap#369, canonical/steam-snap#370)
-- Simon McVittie <smcv@collabora.com> Wed, 06 Mar 2024 17:47:27 +0000
steam-runtime-tools (0.20240301.0) steamrt; urgency=medium
* steam-runtime-check-requirements:
- Diagnose some common situations that will break steamwebhelper
now that it runs under a sniper container (steamrt/tasks#406)
+ Check for a working version of bubblewrap (either our bundled copy
srt-bwrap if unprivileged processes can create new user namespaces
or a setuid-root system copy if they cannot), reporting an error
message if none can be found
+ Check whether ~/.steam/root is below /usr, reporting an error
message if it is
- Add repeatable -v option to show more info, similar to flatpak -vv
* steam-runtime-system-info:
- Add a diagnostic flag for running Steam from below /usr (just for
completeness, since Steam will no longer launch successfully in this
situation)
* pressure-vessel:
- Work around several important paths being symlinks to a non-shared
filesystem by automatically sharing their symlink targets:
- ~/.config/cef_user_data, fixing a steamwebhelper crash
(steamrt/tasks#411)
- ~/.cache, $XDG_CACHE_HOME
- ~/.config, $XDG_CONFIG_HOME
- ~/.local/share, $XDG_DATA_HOME
- ~/.local/state, $XDG_STATE_HOME
- $XDG_CONFIG_DIRS
- $XDG_DATA_DIRS
- ~/.local/share/Steam
- Unset STEAM_ZENITY on entry, and reset it to a path accessible inside
the container runtime before running the game (steamrt/tasks#397)
- If the Steam Deck's system tracing developer option is enabled,
......@@ -15,6 +72,7 @@ steam-runtime-tools (0.20240219.0) UNRELEASED; urgency=medium
- Only build pressure-vessel during development builds, or if targeting
Steam Runtime 1.0 'scout' (which is the source of the official
binary releases, for maximum cross-distro compatibility)
- Adjust for rename of pv-bwrap to srt-bwrap
* Steam Linux Runtime 1.0 (scout):
- Remove workaround for a mid 2021 configuration change
* steam-runtime-launcher-service --alongside-steam:
......@@ -39,9 +97,10 @@ steam-runtime-tools (0.20240219.0) UNRELEASED; urgency=medium
- Use libglnx's backport of g_fdwalk_set_cloexec() everywhere, for
better async-signal-safety
- Factor out basic libc-based utility functions into a static library
- Better automated test coverage
* Documentation updates
-- Simon McVittie <smcv@collabora.com> Tue, 27 Feb 2024 15:17:05 +0000
-- Simon McVittie <smcv@collabora.com> Fri, 01 Mar 2024 19:20:01 +0000
steam-runtime-tools (0.20240212.0) steamrt; urgency=medium
......
usr/libexec/steam-runtime-tools-0/*
usr/libexec/steam-runtime-tools-0/*-linux-gnu*
usr/libexec/steam-runtime-tools-0/launch-options.py
usr/libexec/steam-runtime-tools-0/shaders
usr/bin/steam-runtime-identify-library-abi
usr/bin/steam-runtime-steam-remote
usr/bin/steam-runtime-urlopen
usr/libexec/steam-runtime-tools-0/srt-bwrap
......@@ -93,7 +93,7 @@ The container runtime framework has the same
as Flatpak, as a result of using much of the same code to start its
containers.
The container runtime framework will use its own included copy of the
[bubblewrap][] tool, `pv-bwrap`, if possible.
[bubblewrap][] tool, `srt-bwrap`, if possible.
In operating systems where a setuid version of the bubblewrap executable
is required, it is assumed to be available in the `PATH` as `bwrap`, or
installed at `/usr/local/libexec/flatpak-bwrap`, `/usr/libexec/flatpak-bwrap`
......
......@@ -23,7 +23,7 @@
project(
'steam-runtime-tools', 'c',
version : '0.20240212.0',
version : '0.20240306.0',
default_options: [
'c_std=c99',
'warning_level=2',
......@@ -33,7 +33,7 @@ project(
api_major = '0'
abi_major = '0'
abi_minor = '20240212.0'
abi_minor = '20240306.0'
gnome = import('gnome')
pkg = import('pkgconfig')
......@@ -231,7 +231,7 @@ libcap_dep = dependency(
if not libcap_dep.found()
libcap_dep = c_compiler.find_library(
'cap',
required : get_option('pressure_vessel') and get_option('bin'),
required : get_option('bin'),
)
endif
......
......@@ -103,13 +103,16 @@ EXECUTABLES = [
'pressure-vessel-adverb',
'pressure-vessel-try-setlocale',
'pressure-vessel-wrap',
'pv-bwrap',
'pv-verify',
'steam-runtime-launch-client',
'steam-runtime-launcher-interface-0',
'steam-runtime-launcher-service',
'steam-runtime-system-info',
]
LIBEXEC_EXECUTABLES = [
'launch-options.py',
'srt-bwrap',
]
def install(src, dst, mode=0o644):
......@@ -328,10 +331,10 @@ def main():
if not os.path.exists(path):
path = '/usr/libexec/steam-runtime-tools-0'
for tool in ['launch-options.py']:
for exe in LIBEXEC_EXECUTABLES:
install_exe(
os.path.join(path, tool),
os.path.join(inst_pkglibexecdir, tool),
os.path.join(path, exe),
os.path.join(inst_pkglibexecdir, exe),
)
for arch in architectures:
......
......@@ -477,13 +477,14 @@ pv_bwrap_append_adjusted_exports (FlatpakBwrap *to,
FlatpakBwrap *from,
const char *home,
SrtSysroot *interpreter_root,
PvBwrapFlags bwrap_flags,
SrtBwrapFlags bwrap_flags,
GError **error)
{
g_autofree int *fds = NULL;
/* Bypass FEX-Emu transparent rewrite by using
* "/proc/self/root" as the root path. */
g_autoptr(SrtSysroot) root = NULL;
gboolean is_snap_env;
gsize n_fds;
gsize i;
......@@ -492,6 +493,10 @@ pv_bwrap_append_adjusted_exports (FlatpakBwrap *to,
g_return_val_if_fail (home != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
is_snap_env = (g_getenv ("SNAP") != NULL
&& g_getenv ("SNAP_NAME") != NULL
&& g_getenv ("SNAP_REVISION") != NULL);
fds = flatpak_bwrap_steal_fds (from, &n_fds);
for (i = 0; i < n_fds; i++)
flatpak_bwrap_add_fd (to, fds[i]);
......@@ -549,6 +554,17 @@ pv_bwrap_append_adjusted_exports (FlatpakBwrap *to,
opt,
(const char *) from->argv->pdata[i + 1]);
if (is_snap_env
&& g_str_equal (opt, "--tmpfs")
&& g_str_has_prefix (from->argv->pdata[i + 1], "/snap/steam"))
{
g_warning ("Filtering out %s %s to work around "
"https://github.com/canonical/steam-snap/issues/370",
opt, (const char *) from->argv->pdata[i + 1]);
i += 2;
continue;
}
flatpak_bwrap_add_args (to, opt, from->argv->pdata[i + 1], NULL);
i += 2;
......@@ -565,6 +581,16 @@ pv_bwrap_append_adjusted_exports (FlatpakBwrap *to,
const char *from_dest = from->argv->pdata[i + 2];
gboolean skip_real_root = FALSE;
if (is_snap_env
&& g_str_equal (from_src, "/var/lib/snapd/desktop"))
{
g_warning ("Filtering out %s %s %s to work around "
"https://github.com/canonical/steam-snap/issues/369",
opt, from_src, from_dest);
i += 3;
continue;
}
/* If we're using FEX-Emu or similar, Flatpak code might think it
* has found a particular file either because it's in the rootfs,
* or because it's in the real root filesystem.
......@@ -645,7 +671,7 @@ pv_bwrap_append_adjusted_exports (FlatpakBwrap *to,
* (Debian 11 or older) won't support --perms. Fall back to
* creating mount-points with the default permissions if
* necessary. */
if (bwrap_flags & PV_BWRAP_FLAGS_HAS_PERMS)
if (bwrap_flags & SRT_BWRAP_FLAGS_HAS_PERMS)
flatpak_bwrap_add_args (to, opt, perms, NULL);
else
g_debug ("Ignoring \"--perms %s\" because bwrap is too old",
......
......@@ -27,18 +27,11 @@
#include "environ.h"
#include "flatpak-bwrap-private.h"
#include "flatpak-exports-private.h"
#include "steam-runtime-tools/bwrap-internal.h"
#include "steam-runtime-tools/glib-backports-internal.h"
#include "steam-runtime-tools/resolve-in-sysroot-internal.h"
#include "steam-runtime-tools/steam-internal.h"
typedef enum
{
PV_BWRAP_FLAGS_SYSTEM = (1 << 0),
PV_BWRAP_FLAGS_SETUID = (1 << 1),
PV_BWRAP_FLAGS_HAS_PERMS = (1 << 2),
PV_BWRAP_FLAGS_NONE = 0
} PvBwrapFlags;
gboolean pv_bwrap_run_sync (FlatpakBwrap *bwrap,
int *exit_status_out,
GError **error);
......@@ -75,7 +68,7 @@ gboolean pv_bwrap_append_adjusted_exports (FlatpakBwrap *to,
FlatpakBwrap *from,
const char *home,
SrtSysroot *interpreter_root,
PvBwrapFlags bwrap_flags,
SrtBwrapFlags bwrap_flags,
GError **error);
void pv_bwrap_container_env_to_subsandbox_argv (FlatpakBwrap *flatpak_subsandbox,
......
......@@ -167,6 +167,8 @@ pressure_vessel_wrap_lib = static_library(
'graphics-provider.h',
'runtime.c',
'runtime.h',
'wrap-context.c',
'wrap-context.h',
'wrap-discord.c',
'wrap-discord.h',
'wrap-flatpak.c',
......@@ -283,18 +285,6 @@ if build_man_pages
endforeach
endif
bubblewrap_subproject = subproject(
'bubblewrap',
default_options : [
'build_rpath=' + pv_rpath,
'bwrapdir=' + pv_bindir,
'install_rpath=' + pv_rpath,
'program_prefix=pv-',
'tests=false',
],
)
pv_bin += bubblewrap_subproject.get_variable('bwrap')
test_depends += pv_bin
# vim:set sw=2 sts=2 et:
This diff is collapsed.
/*
* Copyright © 2014-2019 Red Hat, Inc
* Copyright © 2017-2024 Collabora Ltd.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#pragma once
#include "steam-runtime-tools/glib-backports-internal.h"
#include "steam-runtime-tools/resolve-in-sysroot-internal.h"
#include "steam-runtime-tools/utils-internal.h"
#include "pressure-vessel/wrap-interactive.h"
typedef struct _PvWrapContext PvWrapContext;
typedef struct _PvWrapContextClass PvWrapContextClass;
typedef enum
{
TRISTATE_NO = 0,
TRISTATE_YES,
TRISTATE_MAYBE
} Tristate;
typedef enum
{
PRELOAD_VARIABLE_INDEX_LD_AUDIT,
PRELOAD_VARIABLE_INDEX_LD_PRELOAD,
} PreloadVariableIndex;
typedef struct
{
PreloadVariableIndex which;
gchar *preload;
} WrapPreloadModule;
typedef struct
{
GStrv env_if_host;
GStrv filesystems;
gchar *freedesktop_app_id;
gchar *graphics_provider;
gchar *home;
GArray *pass_fds;
GArray *preload_modules;
gchar *runtime;
gchar *runtime_base;
gchar *steam_app_id;
gchar *variable_dir;
gchar *write_final_argv;
double terminate_idle_timeout;
double terminate_timeout;
PvShell shell;
PvTerminal terminal;
Tristate share_home;
gboolean batch;
gboolean copy_runtime;
gboolean deterministic;
gboolean devel;
gboolean gc_runtimes;
gboolean generate_locales;
gboolean import_vulkan_layers;
gboolean launcher;
gboolean only_prepare;
gboolean remove_game_overlay;
gboolean share_pid;
gboolean single_thread;
gboolean systemd_scope;
gboolean test;
gboolean verbose;
gboolean version;
gboolean version_only;
} PvWrapOptions;
struct _PvWrapContext
{
GObject parent_instance;
gchar **original_argv;
gchar **original_environ;
PvWrapOptions options;
gboolean is_flatpak_env;
int original_argc;
};
#define PV_TYPE_WRAP_CONTEXT \
(pv_wrap_context_get_type ())
#define PV_WRAP_CONTEXT(o) \
(G_TYPE_CHECK_INSTANCE_CAST ((o), PV_TYPE_WRAP_CONTEXT, PvWrapContext))
#define PV_IS_WRAP_CONTEXT(o) \
(G_TYPE_CHECK_INSTANCE_TYPE ((o), PV_TYPE_WRAP_CONTEXT))
#define PV_WRAP_CONTEXT_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS ((o), PV_TYPE_WRAP_CONTEXT, PvWrapContextClass))
#define PV_WRAP_CONTEXT_CLASS(c) \
(G_TYPE_CHECK_CLASS_CAST ((c), PV_TYPE_WRAP_CONTEXT, PvWrapContextClass))
#define PV_IS_WRAP_CONTEXT_CLASS(c) \
(G_TYPE_CHECK_CLASS_TYPE ((c), PV_TYPE_WRAP_CONTEXT))
GType pv_wrap_context_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (PvWrapContext, g_object_unref)
PvWrapContext *pv_wrap_context_new (GError **error);
gboolean pv_wrap_options_parse_environment (PvWrapOptions *self,
GError **error);
gboolean pv_wrap_context_parse_argv (PvWrapContext *self,
int *argcp,
char ***argvp,
GError **error);
gboolean pv_wrap_options_parse_argv (PvWrapOptions *self,
int *argcp,
char ***argvp,
GError **error);
gboolean pv_wrap_options_parse_environment_after_argv (PvWrapOptions *self,
SrtSysroot *interpreter_root,
GError **error);
......@@ -263,6 +263,55 @@ expose_steam (FlatpakExports *exports,
return TRUE;
}
/* Paths that go along with the home directory: if we are sharing $HOME
* between host and container, then we also share these, but if we are
* not sharing $HOME, then we do not. */
static const char * const shared_like_home_absolute[] =
{
/* Common FHS or FHS-adjacent mount points for removable media */
"/media",
"/mnt",
"/run/media",
/* Typical FHS directories that do not have any other mapping */
"/home",
"/opt",
"/srv",
/* We always export /tmp for now (see pv_bwrap_use_host_os() and
* pv_share_temp_dir()) and it seems odd
* to share /tmp with the host, but not /var/tmp.
* We don't do this when not sharing the home directory, since
* in that case the replacement home directory provides /var/tmp
* as a symlink or bind-mount pointing to its .cache/tmp,
* consistent with Flatpak. */
"/var/tmp",
};
/* Relative paths in the home directory that are somewhat likely
* to be symbolic links to some other location, like
* /home/me/.config -> /ssd/me/.config.
* To avoid weird issues where the container has a dangling symlink,
* we explicitly add these to the FlatpakExports. */
static const char * const shared_like_home_relative[] =
{
/* Generic, mostly the defaults for XDG base directories.
* See also pv_bind_and_propagate_from_environ(), which
* handles their values from the environment if overridden.
* We handle .config even if XDG_DATA_HOME is different, and so on,
* because it's common (albeit wrong) for applications to ignore the
* environment variable and hard-code its default. */
".cache",
".config",
".local/share",
".local/state",
".var",
/* Steam-specific */
".config/cef_user_data",
".local/share/Steam",
};
gboolean
pv_wrap_use_home (PvHomeMode mode,
const char *real_home,
......@@ -272,6 +321,8 @@ pv_wrap_use_home (PvHomeMode mode,
PvEnviron *container_env,
GError **error)
{
size_t i;
g_return_val_if_fail (real_home != NULL, FALSE);
g_return_val_if_fail (exports != NULL, FALSE);
g_return_val_if_fail (bwrap_home_arguments != NULL, FALSE);
......@@ -285,39 +336,21 @@ pv_wrap_use_home (PvHomeMode mode,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
real_home);
/* If we are sharing the home directory with the host, also share
* common mount points for removable media. */
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/media");
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/mnt");
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/run/media");
/* If we are sharing the home directory with the host, also share
* typical FHS directories that do not have any other mapping. */
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/home");
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/opt");
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/srv");
/* We always export /tmp for now (see below) and it seems odd
* to share /tmp with the host, but not /var/tmp.
* We don't do this when not sharing the home directory, since
* in that case the replacement home directory provides /var/tmp
* as a symlink or bind-mount pointing to its .cache/tmp,
* consistent with Flatpak. */
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
"/var/tmp");
for (i = 0; i < G_N_ELEMENTS (shared_like_home_absolute); i++)
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
shared_like_home_absolute[i]);
for (i = 0; i < G_N_ELEMENTS (shared_like_home_relative); i++)
{
g_autofree gchar *path = NULL;
path = g_build_filename (real_home, shared_like_home_relative[i],
NULL);
flatpak_exports_add_path_expose (exports,
FLATPAK_FILESYSTEM_MODE_READ_WRITE,
path);
}
/* TODO: All of ~/.steam has traditionally been read/write when not
* using a per-game home directory, but does it need to be? Maybe we
......
......@@ -26,6 +26,7 @@
#include "steam-runtime-tools/glib-backports-internal.h"
#include "steam-runtime-tools/libdl-internal.h"
#include "steam-runtime-tools/log-internal.h"
#include "steam-runtime-tools/subprocess-internal.h"
#include "steam-runtime-tools/utils-internal.h"
#include "steam-runtime-tools/virtualization-internal.h"
#include "libglnx.h"
......@@ -38,182 +39,17 @@
#include "supported-architectures.h"
#include "utils.h"
static gchar *
find_system_bwrap (void)
{
static const char * const flatpak_libexecdirs[] =
{
"/usr/local/libexec",
"/usr/libexec",
"/usr/lib/flatpak"
};
g_autofree gchar *candidate = NULL;
gsize i;
candidate = g_find_program_in_path ("bwrap");
if (candidate != NULL)
return g_steal_pointer (&candidate);
for (i = 0; i < G_N_ELEMENTS (flatpak_libexecdirs); i++)
{
candidate = g_build_filename (flatpak_libexecdirs[i],
"flatpak-bwrap", NULL);
if (g_file_test (candidate, G_FILE_TEST_IS_EXECUTABLE))
return g_steal_pointer (&candidate);
else
g_clear_pointer (&candidate, g_free);
}
return NULL;
}
static gboolean
test_bwrap_executable (const char *bwrap_executable,
PvBwrapFlags test_features,
GLogLevelFlags log_level)
{
g_autoptr(GPtrArray) argv = g_ptr_array_sized_new (10);
int wait_status;
g_autofree gchar *child_stdout = NULL;
g_autofree gchar *child_stderr = NULL;
g_autoptr(GError) local_error = NULL;
GError **error = &local_error;
g_ptr_array_add (argv, (char *) bwrap_executable);
if (test_features & PV_BWRAP_FLAGS_HAS_PERMS)
{
g_ptr_array_add (argv, (char *) "--perms");
g_ptr_array_add (argv, (char *) "0700");
g_ptr_array_add (argv, (char *) "--dir");
g_ptr_array_add (argv, (char *) "/");
}
g_ptr_array_add (argv, (char *) "--bind");
g_ptr_array_add (argv, (char *) "/");
g_ptr_array_add (argv, (char *) "/");
g_ptr_array_add (argv, (char *) "true");
g_ptr_array_add (argv, NULL);
/* We use LEAVE_DESCRIPTORS_OPEN and set CLOEXEC in the child_setup,
* to work around a deadlock in GLib < 2.60 */
if (!g_spawn_sync (NULL, /* cwd */
(gchar **) argv->pdata,
NULL, /* environ */
G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
flatpak_bwrap_child_setup_cb, NULL,
&child_stdout,
&child_stderr,
&wait_status,
error))
{
g_log (G_LOG_DOMAIN, log_level, "Cannot run %s: %s",
bwrap_executable, local_error->message);
g_clear_error (&local_error);
return FALSE;
}
else if (wait_status != 0)
{
g_log (G_LOG_DOMAIN, log_level, "Cannot run %s: wait status %d",
bwrap_executable, wait_status);
if (child_stdout != NULL && child_stdout[0] != '\0')
g_log (G_LOG_DOMAIN, log_level, "Output:\n%s", child_stdout);
if (child_stderr != NULL && child_stderr[0] != '\0')
g_log (G_LOG_DOMAIN, log_level, "Diagnostic output:\n%s", child_stderr);
return FALSE;
}
else
{
g_debug ("Successfully ran: %s --bind / / true", bwrap_executable);
return TRUE;
}
}
static gchar *
check_bwrap (const char *tools_dir,
gboolean only_prepare,
PvBwrapFlags *flags_out)
{
g_autofree gchar *local_bwrap = NULL;
g_autofree gchar *system_bwrap = NULL;
const char *tmp;
g_return_val_if_fail (tools_dir != NULL, NULL);
tmp = g_getenv ("PRESSURE_VESSEL_BWRAP");
if (tmp == NULL)
tmp = g_getenv ("BWRAP");
if (tmp != NULL)
{
/* If the user specified an environment variable, then we don't
* try anything else. */
g_info ("Using bubblewrap from environment: %s", tmp);
if (!only_prepare
&& !test_bwrap_executable (tmp, PV_BWRAP_FLAGS_NONE,
SRT_LOG_LEVEL_FAILURE))
return NULL;
return g_strdup (tmp);
}
local_bwrap = g_build_filename (tools_dir, "pv-bwrap", NULL);
/* If our local copy works, use it. If not, keep relatively quiet
* about it for now - we might need to use a setuid system copy, for
* example on Debian 10, RHEL 7, Arch linux-hardened kernel. */
if (only_prepare
|| test_bwrap_executable (local_bwrap, PV_BWRAP_FLAGS_NONE,
G_LOG_LEVEL_DEBUG))
return g_steal_pointer (&local_bwrap);
g_assert (!only_prepare);
system_bwrap = find_system_bwrap ();
/* Try the system copy: if it exists, then it should work, so print failure
* messages if it doesn't work. */
if (system_bwrap != NULL
&& test_bwrap_executable (system_bwrap, PV_BWRAP_FLAGS_NONE,
SRT_LOG_LEVEL_FAILURE))
{
if (flags_out != NULL)
*flags_out |= PV_BWRAP_FLAGS_SYSTEM;
return g_steal_pointer (&system_bwrap);
}
/* If there was no system copy, try the local copy again. We expect
* this to fail, and are really just doing this to print error messages
* at the appropriate severity - but if it somehow works, great,
* I suppose? */
if (test_bwrap_executable (local_bwrap, PV_BWRAP_FLAGS_NONE,
SRT_LOG_LEVEL_FAILURE))
{
g_warning ("Local bwrap executable didn't work first time but "
"worked second time?");
return g_steal_pointer (&local_bwrap);
}
return NULL;
}
gchar *
pv_wrap_check_bwrap (const char *tools_dir,
gboolean only_prepare,
PvBwrapFlags *flags_out)
pv_wrap_check_bwrap (gboolean only_prepare,
SrtBwrapFlags *flags_out,
GError **error)
{
PvBwrapFlags flags = PV_BWRAP_FLAGS_NONE;
g_autofree gchar *bwrap = check_bwrap (tools_dir, only_prepare, &flags);
g_autoptr(SrtSubprocessRunner) runner = NULL;
g_autofree gchar *bwrap = NULL;
const char *argv[] = { NULL, "--version", NULL };
struct stat statbuf;
runner = _srt_subprocess_runner_new ();
bwrap = _srt_check_bwrap (runner, only_prepare, flags_out, error);
if (bwrap == NULL)
return NULL;
......@@ -223,24 +59,6 @@ pv_wrap_check_bwrap (const char *tools_dir,
argv[0] = bwrap;
pv_run_sync (argv, NULL, NULL, NULL, NULL);
if (stat (bwrap, &statbuf) < 0)
{
g_warning ("stat(%s): %s", bwrap, g_strerror (errno));
}
else if (statbuf.st_mode & S_ISUID)
{
g_info ("Using setuid bubblewrap executable %s (permissions: %o)",
bwrap, _srt_stat_get_permissions (&statbuf));
flags |= PV_BWRAP_FLAGS_SETUID;
}
if (test_bwrap_executable (bwrap, PV_BWRAP_FLAGS_HAS_PERMS,
G_LOG_LEVEL_DEBUG))
flags |= PV_BWRAP_FLAGS_HAS_PERMS;
if (flags_out != NULL)
*flags_out = flags;
return g_steal_pointer (&bwrap);
}
......@@ -1256,6 +1074,8 @@ typedef enum
ENV_MOUNT_FLAGS_COLON_DELIMITED = (1 << 0),
ENV_MOUNT_FLAGS_DEPRECATED = (1 << 1),
ENV_MOUNT_FLAGS_READ_ONLY = (1 << 2),
ENV_MOUNT_FLAGS_IF_HOME_SHARED = (1 << 3),
ENV_MOUNT_FLAGS_USR_QUIET = (1 << 4),
ENV_MOUNT_FLAGS_NONE = 0
} EnvMountFlags;
......@@ -1285,10 +1105,25 @@ static const EnvMount known_required_env[] =
{ "STEAM_COMPAT_TOOL_PATH", ENV_MOUNT_FLAGS_DEPRECATED },
{ "STEAM_COMPAT_TOOL_PATHS", ENV_MOUNT_FLAGS_COLON_DELIMITED },
{ "STEAM_EXTRA_COMPAT_TOOLS_PATHS", ENV_MOUNT_FLAGS_COLON_DELIMITED },
{ "XDG_CACHE_HOME", ENV_MOUNT_FLAGS_IF_HOME_SHARED },
{ "XDG_CONFIG_HOME", ENV_MOUNT_FLAGS_IF_HOME_SHARED },
{ "XDG_CONFIG_DIRS",
ENV_MOUNT_FLAGS_IF_HOME_SHARED
| ENV_MOUNT_FLAGS_COLON_DELIMITED
| ENV_MOUNT_FLAGS_USR_QUIET },
{ "XDG_DATA_HOME", ENV_MOUNT_FLAGS_IF_HOME_SHARED },
{ "XDG_DATA_DIRS",
ENV_MOUNT_FLAGS_IF_HOME_SHARED
| ENV_MOUNT_FLAGS_COLON_DELIMITED
| ENV_MOUNT_FLAGS_USR_QUIET },
{ "XDG_STATE_HOME", ENV_MOUNT_FLAGS_IF_HOME_SHARED },
};
static void
bind_and_propagate_from_environ (FlatpakExports *exports,
bind_and_propagate_from_environ (SrtSysroot *sysroot,
const char * const *current_env,
PvHomeMode home_mode,
FlatpakExports *exports,
PvEnviron *container_env,
const char *variable,
EnvMountFlags flags)
......@@ -1304,7 +1139,11 @@ bind_and_propagate_from_environ (FlatpakExports *exports,
g_return_if_fail (exports != NULL);
g_return_if_fail (variable != NULL);
value = g_getenv (variable);
if (home_mode != PV_HOME_MODE_SHARED
&& (flags & ENV_MOUNT_FLAGS_IF_HOME_SHARED))
return;
value = _srt_environ_getenv (current_env, variable);
if (value == NULL)
return;
......@@ -1338,7 +1177,7 @@ bind_and_propagate_from_environ (FlatpakExports *exports,
if (values[i][0] == '\0')
continue;
if (!g_file_test (values[i], G_FILE_TEST_EXISTS))
if (!_srt_sysroot_test (sysroot, values[i], SRT_RESOLVE_FLAGS_NONE, NULL))
{
g_info ("Not bind-mounting %s=\"%s%s%s\" because it does not exist",
variable, before, values[i], after);
......@@ -1355,7 +1194,15 @@ bind_and_propagate_from_environ (FlatpakExports *exports,
}
if (flatpak_has_path_prefix (canon, "/usr"))
g_warning_once ("Binding directories that are located under \"/usr/\" is not supported!");
{
if (!(flags & ENV_MOUNT_FLAGS_USR_QUIET))
g_warning_once ("Binding directories that are located under \"/usr/\" is not supported!");
else
g_debug ("Ignoring %s=\"%s%s%s\" because it is below /usr",
variable, before, values[i], after);
continue;
}
g_info ("Bind-mounting %s=\"%s%s%s\" from the current env as %s=\"%s%s%s\" in the host",
variable, before, values[i], after,
......@@ -1370,7 +1217,9 @@ bind_and_propagate_from_environ (FlatpakExports *exports,
}
}
if (changed || g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR))
if (changed
|| _srt_sysroot_test (sysroot, "/.flatpak-info",
SRT_RESOLVE_FLAGS_NONE, NULL))
{
g_autofree gchar *joined = g_strjoinv (":", values);
......@@ -1383,7 +1232,10 @@ bind_and_propagate_from_environ (FlatpakExports *exports,
* a Flatpak subsandbox
*/
void
pv_bind_and_propagate_from_environ (FlatpakExports *exports,
pv_bind_and_propagate_from_environ (SrtSysroot *sysroot,
const char * const *current_env,
PvHomeMode home_mode,
FlatpakExports *exports,
PvEnviron *container_env)
{
gsize i;
......@@ -1398,7 +1250,8 @@ pv_bind_and_propagate_from_environ (FlatpakExports *exports,
{
/* If we're using bubblewrap directly, we can and must make
* sure that all required directories are bind-mounted */
bind_and_propagate_from_environ (exports, container_env,
bind_and_propagate_from_environ (sysroot, current_env, home_mode,
exports, container_env,
known_required_env[i].name,
known_required_env[i].flags);
}
......@@ -1407,9 +1260,11 @@ pv_bind_and_propagate_from_environ (FlatpakExports *exports,
/* If we're using a Flatpak subsandbox, we have no choice but to
* rely on the fact that any directory available to the parent app
* is also going to be available to the subsandbox */
g_return_if_fail (home_mode == PV_HOME_MODE_SHARED);
pv_environ_setenv (container_env,
known_required_env[i].name,
g_getenv (known_required_env[i].name));
_srt_environ_getenv (current_env,
known_required_env[i].name));
}
}
}