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

wrap: Remove obsolete shell script implementation

parent fbcaebb7
No related branches found
No related tags found
No related merge requests found
......@@ -95,7 +95,6 @@ SCRIPTS = [
'pressure-vessel-test-ui',
'pressure-vessel-unruntime',
'pressure-vessel-unruntime-test-ui',
'pressure-vessel-wrap.sh'
]
EXECUTABLES = [
'pressure-vessel-wrap'
......
......@@ -107,7 +107,6 @@ supported_warning_cflags = c_compiler.get_supported_arguments(project_warning_cf
add_project_arguments(supported_warning_cflags, language : 'c')
scripts = [
'pressure-vessel-wrap.sh',
'pressure-vessel-test-ui',
'pressure-vessel-unruntime',
'pressure-vessel-unruntime-test-ui',
......
......@@ -104,14 +104,6 @@ class Gui:
row += 1
self.script_check = Gtk.CheckButton.new_with_label(
'Use old shell script version of pressure-vessel-wrap'
)
self.script_check.set_active(False)
self.grid.attach(self.script_check, 1, row, 1, 1)
row += 1
self.share_home_check = Gtk.CheckButton.new_with_label(
'Share real home directory'
)
......@@ -243,17 +235,13 @@ class Gui:
def run_cb(self, _ignored=None):
# type: (typing.Any) -> None
if self.script_check.get_active():
wrap = 'pressure-vessel-wrap.sh'
else:
wrap = 'pressure-vessel-wrap'
argv = [
'env',
'G_MESSAGES_DEBUG=all',
os.path.join(
os.path.dirname(sys.argv[0]),
wrap,
'pressure-vessel-wrap'
),
]
......
......@@ -119,10 +119,6 @@ if [ -n "${PRESSURE_VESSEL_WRAP_GUI+set}" ]; then
exec "${here}/pressure-vessel-test-ui" ${options+"${options[@]}"} "$@"
fi
if [ -n "${PRESSURE_VESSEL_WRAP_SHELL+set}" ]; then
exec "${here}/pressure-vessel-wrap.sh" ${options+"${options[@]}"} "$@"
fi
exec "$here/pressure-vessel-wrap" ${options+"${options[@]}"} "$@"
# vim:set sw=4 sts=4 et:
#!/bin/bash
# pressure-vessel-wrap — run a program in a container that protects $HOME,
# optionally using a Flatpak-style runtime
#
# Copyright © 2017-2019 Collabora Ltd.
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
set -e
set -o pipefail
set -u
shopt -s nullglob
me="$0"
me="$(readlink -f "$0")"
here="${me%/*}"
me="${me##*/}"
if [ -n "${PRESSURE_VESSEL_WRAP_NATIVE+set}" ]; then
exec "${here}/pressure-vessel-wrap-c" "$@"
fi
if [ -n "${STEAM_RUNTIME+set}" ]; then
echo "$me: This program should not be run in the Steam Runtime." >&2
echo "$me: Use pressure-vessel-unruntime instead." >&2
exit 2
fi
# If bwrap isn't installed as a standalone binary on the PATH, see
# whether we have a copy of Flatpak configured with the bundled
# bubblewrap (--without-system-bubblewrap). If we do, use that one.
if [ -z "${BWRAP:-}" ]; then
if ! BWRAP="$(command -v bwrap)"; then
for dir in /usr/local/libexec /usr/libexec /usr/lib/flatpak; do
if [ -x "$dir/flatpak-bwrap" ]; then
BWRAP="$dir/flatpak-bwrap"
break
fi
done
if [ -z "${BWRAP:-}" ] && [ -x "${here}/bwrap" ]; then
BWRAP="${here}/bwrap"
fi
fi
fi
declare -a bwrap_options
declare -a multiarch_tuples
declare -a wrapped_command
declare -a original_argv
declare -a ld_preload
declare -a env_if_host
original_argv=("$@")
env_if_host=()
fake_home=
freedesktop_app_id=
host_fallback=
ld_preload=()
interactive=
runtime=
share_home=yes
steam_app_id="${SteamAppId-}"
tmpdir=
verbose=
xterm=
multiarch_tuples=(x86_64-linux-gnu i386-linux-gnu)
# Pop the pressure-vessel-wrap options from $@, leaving the command
# and arguments.
usage () {
code="$1"
shift
if [ "$code" -ne 0 ]; then
exec >&2
fi
echo
echo "Usage: $me [OPTIONS] [--] COMMAND [ARGS...]"
echo
echo "Run COMMAND [ARGS...] in a container that protects \$HOME."
echo
echo "The current working directory will be writeable for COMMAND,"
echo "unless it is the real home directory."
echo
echo "Options:"
echo "--share-home Use the real home directory. [Default]"
echo "--unshare-home Use a fake home directory, chosen"
echo " automatically according to"
echo " --freedesktop-app-id,"
echo " --steam-app-id, \$SteamAppId."
echo "--home=HOME Use HOME as home directory. Implies"
echo " --unshare-home."
echo
echo "--env-if-host=VAR=VAL Set VAR=VAL if COMMAND is run with"
echo " /usr from the host system, but not if"
echo " it is run with /usr from RUNTIME."
echo "--freedesktop-app-id=ID Make --unshare-home default to"
echo " ~/.var/app/ID as home directory."
echo " ID is com.example.MyApp or similar."
echo " This interoperates with Flatpak."
echo "--host-fallback Run COMMAND on the host system if we"
echo " cannot run it in a container."
echo "--interactive Run an interactive shell instead of"
echo " COMMAND. Executing \"\$@\" in that"
echo " shell will run COMMAND [ARGS]."
echo "--host-ld-preload=MODULE Add MODULE from host system to"
echo " LD_PRELOAD when executing COMMAND."
echo "--runtime=RUNTIME Mount the given sysroot or"
echo " merged /usr in the container,"
echo " and augment it with the host"
echo " system's graphics stack."
echo "--steam-app-id=123 Make --unshare-home use"
echo " ~/.var/app/com.steampowered.App123"
echo " as home directory."
echo " [Default: \$SteamAppId]"
echo "--verbose Be more verbose."
echo "--xterm Same as --interactive, but run an"
echo " xterm in the container."
echo
exit "$code"
}
getopt_temp="help"
getopt_temp="${getopt_temp},env-if-host:"
getopt_temp="${getopt_temp},freedesktop-app-id:"
getopt_temp="${getopt_temp},home:"
getopt_temp="${getopt_temp},host-fallback"
getopt_temp="${getopt_temp},host-ld-preload:"
getopt_temp="${getopt_temp},interactive"
getopt_temp="${getopt_temp},runtime:"
getopt_temp="${getopt_temp},share-home"
getopt_temp="${getopt_temp},steam-app-id:"
getopt_temp="${getopt_temp},unshare-home"
getopt_temp="${getopt_temp},verbose"
getopt_temp="${getopt_temp},xterm"
getopt_temp="$(getopt -o '' --long "$getopt_temp" -n "$me" -- "$@")"
eval "set -- $getopt_temp"
unset getopt_temp
while [ "$#" -gt 0 ]; do
case "$1" in
(--env-if-host)
case "$2" in
(*=*)
;;
(*)
echo "$me: --env-if-host argument must be VAR=VALUE" >&2
exit 2
;;
esac
env_if_host+=("$2")
shift 2
;;
(--freedesktop-app-id)
freedesktop_app_id="$2"
shift 2
;;
(--steam-app-id)
steam_app_id="$2"
shift 2
;;
(--home)
fake_home="$2"
share_home=
shift 2
;;
(--host-fallback)
host_fallback=yes
shift
;;
(--host-ld-preload)
ld_preload+=("host:$2")
shift 2
;;
(--interactive)
interactive=yes
shift
;;
(--runtime)
runtime="$2"
shift 2
;;
(--share-home)
share_home=yes
shift
;;
(--unshare-home)
share_home=
shift
;;
(--verbose)
verbose=yes
shift
;;
(--xterm)
xterm=yes
shift
;;
(--help)
usage 0
# not reached
;;
(--)
shift
break
;;
(--*)
echo "$me: unknown option: $1" >&2
usage 2
# not reached
;;
(*)
break
;;
esac
done
if [ "$#" -eq 0 ]; then
echo "$me: an executable to run is required" >&2
exit 2
fi
if [ -n "$verbose" ]; then
echo "Original argv:" >&2
# Deliberately not expanding $0 in format string
# shellcheck disable=SC2016
printf '\t$0: %q\n' "$0" >&2
for arg in "${original_argv[@]}"; do
printf '\t$@: %q\n' "$arg" >&2
done
echo "Current working directory:" >&2
printf '\tLogical: %q\n' "$(pwd -L)" >&2
printf '\tPhysical: %q\n' "$(pwd -P)" >&2
echo "Environment variables:" >&2
env | sed -e 's/^/\t/' >&2
echo "Wrapped command:" >&2
for arg in "$@"; do
printf '\t%q\n' "$arg" >&2
done
fi
if [ -n "$xterm" ]; then
{
# Yes, this weird quoting is really what I mean. Shells within
# shells...
# shellcheck disable=SC2016
wrapped_command=(xterm -e sh -c 'echo; echo "$1: Starting interactive shell (original command is in \"\$@\")"; echo; shift; exec "$@"' sh "$me" bash -i -s "$@")
}
elif [ -n "$interactive" ]; then
exec </dev/tty
exec >/dev/tty
exec 2>/dev/tty
echo "$me: Starting interactive shell (original command is in \"\$@\")">&2
wrapped_command=(bash -i -s "$@")
else
wrapped_command=("$@")
fi
# Make sure wrapped_command is something we can validly pass to env(1)
case "${wrapped_command[0]}" in
(*=*)
wrapped_command=(sh -c 'exec "$@"' sh "${wrapped_command[@]}")
;;
esac
if [ -z "$BWRAP" ] || ! "$BWRAP" --bind / / true; then
echo "$me: Cannot find bwrap or it doesn't work" >&2
if [ -z "$host_fallback" ]; then
exit 1
fi
echo "$me: Falling back to executing '${wrapped_command[*]}' directly" >&2
exec env -- ${env_if_host+"${env_if_host[@]}"} "${wrapped_command[@]}"
fi
if "$BWRAP" --help 2>&1 | grep -F '[--]' >/dev/null 2>/dev/null; then
bwrap_end_of_options="--"
else
# bwrap doesn't support the -- syntax, but we ensured that
# wrapped_command is not treated as an environment variable
# expansion by env, so this is OK
bwrap_end_of_options="env"
fi
cleanup () {
if [ -n "$tmpdir" ]; then
rm -fr "$tmpdir"
fi
}
trap cleanup EXIT
tmpdir="$(mktemp -d)"
scratch="${tmpdir}/scratch"
mkdir "$scratch"
bwrap_options=()
# Protect the controlling terminal from the app/game, unless we are
# running an interactive shell in which case that would break its
# job control.
if [ -z "$interactive" ]; then
bwrap_options+=(--new-session)
fi
overrides=
for t in "${multiarch_tuples[@]}"; do
overrides="${overrides:+"$overrides:"}/overrides/lib/$t"
done
if [ -n "$runtime" ]; then
bwrap_options+=(--setenv LD_LIBRARY_PATH "$overrides")
fi
declare -a bind_usr_result
bind_usr () {
local tree="$1"
local dest="$2"
local dir
bind_usr_result=()
if [ -d "$tree/usr" ]; then
bind_usr_result+=(--ro-bind "$tree/usr" "$dest/usr")
else
bind_usr_result+=(--ro-bind "$tree" "$dest/usr")
fi
for dir in "$tree"/lib* "$tree"/bin "$tree"/sbin; do
if [ -d "$dir" ]; then
local basename
basename="$(basename "$dir")"
if [ -d "$tree/usr" ]; then
bind_usr_result+=(--ro-bind "$dir" "$dest/$basename")
else
bind_usr_result+=(--symlink "usr/$basename" "$dest/$basename")
fi
fi
done
for etc in "/etc/ld.so.cache" "/etc/alternatives"; do
if [ -e "$tree$etc" ]; then
bind_usr_result+=(--ro-bind "$tree$etc" "$dest$etc")
fi
done
}
if [ -n "$runtime" ]; then
uid="$(id -u)"
bind_usr "$runtime" /
bwrap_options+=("${bind_usr_result[@]}")
bwrap_options+=(--setenv XDG_RUNTIME_DIR "/run/user/$uid")
bwrap_options+=(--proc /proc)
bwrap_options+=(--ro-bind /sys /sys)
bwrap_options+=(--tmpfs /run)
bwrap_options+=(--tmpfs /tmp)
bwrap_options+=(--tmpfs /var)
bwrap_options+=(--symlink ../run /var/run)
for dir in /etc /var/cache /var/lib; do
if [ -d "$runtime$dir" ]; then
for member in "$runtime$dir"/*; do
member="$(basename "$member")"
# These paths from the container aren't made available
case "$dir/$member" in
(/etc/group|/etc/passwd)
break
;;
(/etc/host.conf|/etc/hosts|/etc/localtime)
break
;;
(/etc/machine-id|/etc/resolv.conf)
break
;;
(/var/lib/dbus|/var/lib/dhcp|/var/lib/sudo|/var/lib/urandom)
break
;;
esac
if target="$(readlink "$runtime$dir/$member")"; then
bwrap_options+=(--symlink "$target" "$dir/$member")
else
bwrap_options+=(--ro-bind "$runtime$dir/$member" \
"$dir/$member")
fi
done
fi
done
# Take the machine ID from the host
if [ -e /etc/machine-id ]; then
bwrap_options+=(--ro-bind /etc/machine-id /etc/machine-id)
bwrap_options+=(--symlink /etc/machine-id /var/lib/dbus/machine-id)
elif [ -e /var/lib/dbus/machine-id ]; then
bwrap_options+=(--ro-bind /var/lib/dbus/machine-id /etc/machine-id)
bwrap_options+=(--symlink /etc/machine-id /var/lib/dbus/machine-id)
fi
# Take the timezone from the host
if target="$(readlink /etc/localtime)" && \
[ "${target#/usr/}" != "$target" ]; then
bwrap_options+=(--symlink "$target" /etc/localtime)
elif [ -e /etc/localtime ]; then
bwrap_options+=(--ro-bind /etc/localtime /etc/localtime)
fi
for file in resolv.conf host.conf hosts passwd group; do
if [ -e "/etc/$file" ]; then
bwrap_options+=(--ro-bind "/etc/$file" "/etc/$file")
fi
done
# Simplified version of flatpak run --socket=X11
if [ -n "${DISPLAY-}" ]; then
bwrap_options+=(--bind /tmp/.X11-unix /tmp/.X11-unix)
bwrap_options+=(--setenv DISPLAY "$DISPLAY")
fi
for xauth in "${XAUTHORITY-}" "$HOME/.Xauthority"; do
if [ -n "$xauth" ] && [ -e "$xauth" ]; then
bwrap_options+=(--ro-bind "$xauth" "/run/user/$uid/Xauthority")
bwrap_options+=(--setenv XAUTHORITY "/run/user/$uid/Xauthority")
break
fi
done
# Simplified version of flatpak run --socket=wayland
if [ -n "${XDG_RUNTIME_DIR-}" ] && \
[ -S "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY:="wayland-0"}" ]; then
bwrap_options+=(--bind "$XDG_RUNTIME_DIR/${WAYLAND_DISPLAY}" \
"/run/user/$uid/$WAYLAND_DISPLAY")
fi
# Simplified version of flatpak run --socket=pulseaudio, modified to
# support the SteamOS system-wide PulseAudio instance
if false; then # FIXME
if [ -n "${XDG_RUNTIME_DIR-}" ] && \
[ -S "$XDG_RUNTIME_DIR/pulse/native" ]; then
bwrap_options+=(--bind "$XDG_RUNTIME_DIR/pulse/native" \
"/run/user/$uid/pulse/native")
bwrap_options+=(--setenv PULSE_SERVER "unix:/run/user/$uid/pulse/native")
elif [ -S /var/run/pulse/native ]; then
bwrap_options+=(--bind /var/run/pulse/native \
"/run/user/$uid/pulse/native")
bwrap_options+=(--setenv PULSE_SERVER "unix:/run/user/$uid/pulse/native")
fi
fi
# Simplified version of flatpak run --socket=system-bus
if [ -n "${DBUS_SYSTEM_BUS_ADDRESS-}" ]; then
path="$(perl -e '$_ = shift; print $1 if m/^unix:path=([^,;]*)/' \
"$DBUS_SYSTEM_BUS_ADDRESS")"
if [ -n "$path" ] && [ -S "$path" ]; then
bwrap_options+=(--bind "$path" /var/run/dbus/system_bus_socket)
bwrap_options+=(--unsetenv DBUS_SYSTEM_BUS_ADDRESS)
else
echo "$me: warning: Unable to parse DBUS_SYSTEM_BUS_ADDRESS" \
"\"$DBUS_SYSTEM_BUS_ADDRESS\"" >&2
fi
elif [ -S /var/run/dbus/system_bus_socket ]; then
bwrap_options+=(--bind /var/run/dbus/system_bus_socket \
/run/dbus/system_bus_socket)
fi
# Simplified version of flatpak run --socket=system-bus
if [ -n "${DBUS_SESSION_BUS_ADDRESS-}" ]; then
path="$(perl -e '$_ = shift; print $1 if m/^unix:path=([^,;]*)/' \
"$DBUS_SESSION_BUS_ADDRESS")"
if [ "${DBUS_SESSION_BUS_ADDRESS#*abstract=}" != "$DBUS_SESSION_BUS_ADDRESS" ]; then
: # Do nothing: abstract Unix sockets can pass through
elif [ -n "$path" ] && [ -S "$path" ]; then
bwrap_options+=(--bind "$path" "/run/user/$uid/bus")
bwrap_options+=(--setenv DBUS_SESSION_BUS_ADDRESS \
"unix:path=/run/user/$uid/bus")
else
echo "$me: warning: Unable to parse DBUS_SESSION_BUS_ADDRESS" \
"\"$DBUS_SESSION_BUS_ADDRESS\"" >&2
fi
elif [ -n "${XDG_RUNTIME_DIR-}" ] && \
[ -S "$XDG_RUNTIME_DIR/bus" ]; then
bwrap_options+=(--bind "$XDG_RUNTIME_DIR/bus" \
"/run/user/$uid/bus")
bwrap_options+=(--setenv DBUS_SESSION_BUS_ADDRESS \
"unix:path=/run/user/$uid/bus")
fi
dri_path=
for t in "${multiarch_tuples[@]}"; do
# This has the side-effect of testing whether we can run
# binaries for this architecture
if ldso="$("$here/${t}-capsule-capture-libs" --print-ld.so)"; then
dri_path="${dri_path:+"$dri_path:"}/overrides/lib/$t/dri"
mkdir -p "$tmpdir/overrides/lib/$t"
bind_usr "$runtime" "$scratch"
"$BWRAP" \
--ro-bind / / \
--bind "$tmpdir/overrides" "$tmpdir/overrides" \
--tmpfs "$scratch" \
"${bind_usr_result[@]}" \
"$here/${t}-capsule-capture-libs" \
--container="$scratch" \
--link-target="/run/host" \
--dest="$tmpdir/overrides/lib/$t" \
--provider="/" \
gl:
# If we are going to use the host system's libc6 (likely)
# then we have to use its ld.so too.
if [ -L "$tmpdir/overrides/lib/$t/libc.so.6" ]; then
real_path_in_host="$(readlink -f "$ldso")"
real_path_in_runtime="$("$BWRAP" \
--ro-bind / / \
--bind "$tmpdir/overrides" "$tmpdir/overrides" \
--tmpfs "$scratch" \
"${bind_usr_result[@]}" \
"$here/${t}-capsule-capture-libs" \
--resolve-ld.so="$scratch")"
if [ -d "$runtime/usr" ] || \
[ "$real_path_in_runtime#/usr/" != "$real_path_in_runtime" ]; then
bwrap_options+=(--ro-bind "$real_path_in_host" \
"$real_path_in_runtime")
else
# /lib, /lib64 are just going to be symlinks anyway
bwrap_options+=(--ro-bind "$real_path_in_host" \
"/usr$real_path_in_runtime")
fi
# We should also pick up its locale archives.
if [ -e /usr/lib/locale ]; then
bwrap_options+=(--ro-bind /usr/lib/locale /usr/lib/locale)
fi
if [ -e /usr/share/i18n ]; then
bwrap_options+=(--ro-bind /usr/share/i18n /usr/share/i18n)
fi
fi
# /lib, /lib32 or /lib64
libQUAL="$(dirname "$ldso")"
for dir in "/lib/$t" "/usr/lib/$t" "$libQUAL" "/usr$libQUAL"; do
if [ -d "$dir/dri" ]; then
mkdir -p "$tmpdir/overrides/lib/$t/dri"
"$BWRAP" \
--ro-bind / / \
--bind "$tmpdir/overrides" "$tmpdir/overrides" \
--tmpfs "$scratch" \
"${bind_usr_result[@]}" \
"$here/${t}-capsule-capture-libs" \
--container="$scratch" \
--link-target="/run/host" \
--dest="$tmpdir/overrides/lib/$t" \
--provider="/" \
"only-dependencies:if-exists:path-match:$dir/dri/*.so"
# Deliberately not expanding $1, $2 in sh -c
# shellcheck disable=SC2016
"$BWRAP" \
--ro-bind / / \
--tmpfs /run \
--ro-bind / /run/host \
--bind "$tmpdir/overrides" "$tmpdir/overrides" \
sh -c 'ln -fns "$1"/* "$2"' \
sh "/run/host$dir/dri" "$tmpdir/overrides/lib/$t/dri"
fi
# S3TC or S2TC support for Mesa
if [ -e "$dir/libtxc_dxtn.so" ]; then
"$BWRAP" \
--ro-bind / / \
--bind "$tmpdir/overrides" "$tmpdir/overrides" \
--tmpfs "$scratch" \
"${bind_usr_result[@]}" \
"$here/${t}-capsule-capture-libs" \
--container="$scratch" \
--link-target="/run/host" \
--dest="$tmpdir/overrides/lib/$t" \
--provider="/" \
"path-match:$dir/libtxc_dxtn.so"
fi
done
fi
done
bwrap_options+=(--setenv LIBGL_DRIVERS_PATH "$dri_path")
bwrap_options+=(--ro-bind "$tmpdir/overrides" /overrides)
bind_usr / /run/host
bwrap_options+=("${bind_usr_result[@]}")
else
# Everything comes from the root filesystem, except where
# modified below
bwrap_options+=(--bind / /)
fi
# Make /dev available
bwrap_options+=(--dev-bind /dev /dev)
if [ -d /dev/pts ]; then
bwrap_options+=(--dev-bind /dev/pts /dev/pts)
fi
if [ -d /dev/shm ]; then
bwrap_options+=(--dev-bind /dev/shm /dev/shm)
fi
# Protect other users' homes (but guard against the unlikely situation
# that they don't exist)
if [ -d /home ]; then
bwrap_options+=(--tmpfs /home)
fi
if [ -n "$share_home" ]; then
# Share the home directory, and inherit HOME and XDG_*_HOME
# from the parent process.
bwrap_options+=(--bind "$HOME" "$HOME")
else
if [ -n "$fake_home" ]; then
: # OK
elif [ -n "$freedesktop_app_id" ]; then
fake_home="$HOME/.var/app/$freedesktop_app_id"
elif [ -n "$steam_app_id" ]; then
fake_home="$HOME/.var/app/com.steampowered.App$steam_app_id"
else
echo "$me: Error: --unshare-home requires --fake-home," >&2
echo "$me: --freedesktop-app-id, --steam-app-id or \$SteamAppId" >&2
exit 2
fi
# The shellcheck tool warns that -m is only applied to the deepest
# directory and not any parents created via -p, but that's fine here:
# we use a separate mkdir -p for each directory whose permissions we
# care about.
# shellcheck disable=SC2174
{
# Set up the home directory
mkdir -m700 -p "$fake_home"
bwrap_options+=(--bind "$fake_home" "$HOME")
bwrap_options+=(--bind "$fake_home" "$fake_home")
# Set up /var/tmp, XDG_*_HOME like Flatpak does
mkdir -m700 -p "$fake_home/.cache"
mkdir -m700 -p "$fake_home/.cache/tmp"
if [ ! -e "$fake_home/cache" ]; then
ln -fns .cache "$fake_home/cache"
fi
bwrap_options+=(--bind "$fake_home/.cache/tmp" /var/tmp)
bwrap_options+=(--setenv XDG_CACHE_HOME "$fake_home/.cache")
mkdir -m700 -p "$fake_home/.config"
if [ ! -e "$fake_home/config" ]; then
ln -fns .config "$fake_home/config"
fi
bwrap_options+=(--setenv XDG_CONFIG_HOME "$fake_home/.config")
mkdir -m700 -p "$fake_home/.local"
mkdir -m700 -p "$fake_home/.local/share"
if [ ! -e "$fake_home/data" ]; then
ln -fns .local/share "$fake_home/data"
fi
bwrap_options+=(--setenv XDG_DATA_HOME "$fake_home/.local/share")
}
# These might be API entry points, according to .steam/steam/steam.sh.
# On the host system they're symlinks to a real location, but in a
# container it's easier to bind-mount them (this follows symlinks).
# TODO: We probably want to hide part or all of root, steam, steambeta?
for api in bin bin32 bin64 root sdk32 sdk64 steam steambeta; do
dir="$HOME/.steam/$api"
if [ -d "$dir" ]; then
bwrap_options+=(--ro-bind "$dir" "$dir")
fi
done
# steamclient.so relies on this for communication with Steam
if [ -e "$HOME/.steam/steam.pid" ]; then
bwrap_options+=(--ro-bind "$HOME/.steam/steam.pid" "$HOME/.steam/steam.pid")
fi
# Make sure Steam IPC is available (TODO: do we need this? do we need more?)
if [ -e "$HOME/.steam/steam.pipe" ]; then
bwrap_options+=(--bind "$HOME/.steam/steam.pipe" "$HOME/.steam/steam.pipe")
fi
fi
# We need the LD_PRELOADs from Steam visible at the paths that were
# used for them, which might be their physical rather than logical
# locations
adjusted_ld_preload=
for preload in ${ld_preload+"${ld_preload[@]}"}; do
# Currently the only preloaded modules we support are ones that come
# from the host.
preload="${preload#host:}"
if [ -e "$preload" ]; then
case "$preload" in
(/usr/*|/lib*)
if [ -n "$runtime" ]; then
# We can't write here, so redirect them to the
# corresponding locations in /run/host
bwrap_options+=(--ro-bind "$preload" "/run/host$preload")
adjusted_ld_preload="${adjusted_ld_preload:+"$adjusted_ld_preload:"}/run/host$preload"
else
bwrap_options+=(--ro-bind "$preload" "$preload")
adjusted_ld_preload="${adjusted_ld_preload:+"$adjusted_ld_preload:"}$preload"
fi
;;
(*)
bwrap_options+=(--ro-bind "$preload" "$preload")
adjusted_ld_preload="${adjusted_ld_preload:+"$adjusted_ld_preload:"}$preload"
;;
esac
elif [ -n "$preload" ]; then
echo "$me: LD_PRELOAD module '$preload' does not exist" >&2
fi
done
# Make sure the current working directory (the game we are going to
# run) is available. Some games write here.
PWD_L="$(pwd -L)"
if test "$HOME" -ef "$PWD_L"; then
# Keep quiet about this if we're sharing $HOME anyway
if [ -z "$share_home" ]; then
echo "$me: Not making real $PWD_L available to container because it is" \
"the home directory" >&2
fi
else
bwrap_options+=(--bind "$PWD_L" "$PWD_L")
fi
bwrap_options+=(--chdir "$PWD_L")
PWD_P="$(pwd -P)"
if test "$PWD_P" = "$PWD_L"; then
: # Nothing special to do
elif test "$HOME" -ef "$PWD_P"; then
# Keep quiet about this if we're sharing $HOME anyway
if [ -z "$share_home" ]; then
echo "$me: Not making real $PWD_P available to container because it is" \
"the home directory" >&2
fi
else
bwrap_options+=(--bind "$PWD_P" "$PWD_P")
fi
# Put the caller's LD_PRELOAD and search paths back.
if [ -n "$adjusted_ld_preload" ]; then
bwrap_options+=(--setenv LD_PRELOAD "$adjusted_ld_preload")
else
bwrap_options+=(--unsetenv LD_PRELOAD)
fi
if "$BWRAP" --help 2>&1 | grep unshare-uts >/dev/null; then
# Set a standard hostname for the container to make it easier
# to see which shell is which
bwrap_options+=(--hostname pressure-vessel --unshare-uts)
fi
# Potential future expansion: use --unshare-pid for more isolation
# Put Steam Runtime environment variables back, if /usr is mounted
# from the host.
if [ -z "$runtime" ]; then
# We need libraries from the Steam Runtime, so make sure that's visible
# (it should never need to be read/write though)
for env in ${env_if_host+"${env_if_host[@]}"}; do
case "$env" in
(STEAM_RUNTIME=/*)
value="${env#STEAM_RUNTIME=}"
bwrap_options+=(--ro-bind "$value" "$value")
;;
esac
done
wrapped_command=(env -- ${env_if_host+"${env_if_host[@]}"} "${wrapped_command[@]}")
fi
# Replace this process with bwrap, which replaces itself with the
# desired command (unless exec fails)
if [ -n "$verbose" ]; then
echo "$BWRAP options:">&2
for x in "${bwrap_options[@]}"; do
printf '\t%q\n' "$x" >&2
done
echo "$me: '$BWRAP ${bwrap_options[*]} $bwrap_end_of_options ${wrapped_command[*]}'" >&2
fi
e=0
"$BWRAP" "${bwrap_options[@]}" $bwrap_end_of_options "${wrapped_command[@]}" || e=$?
if [ "$e" -eq 0 ]; then
if [ -n "$verbose" ]; then
echo "$me: '$BWRAP ${bwrap_options[*]} $bwrap_end_of_options ${wrapped_command[*]}': successful" >&2
fi
else
echo "$me: failed to execute '$BWRAP ${bwrap_options[*]} $bwrap_end_of_options ${wrapped_command[*]}': exec status $e" >&2
fi
exit "$e"
# vim:set sw=4 sts=4 et:
......@@ -89,7 +89,6 @@ MULTIARCH = [
]
SCRIPTS = [
'pressure-vessel-unruntime',
'pressure-vessel-wrap.sh',
]
LD_SO = [
('x86_64-linux-gnu', '/lib64/ld-linux-x86-64.so.2'),
......
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