Skip to content

Commit

Permalink
Do not mount the entire root filesystem
Browse files Browse the repository at this point in the history
- Only mount the runtime system paths, WINE prefix, game, proton and winetricks cache directory. The winetricks and its descendent processes should have no reason to see anything else
  • Loading branch information
R1kaB3rN committed May 3, 2024
1 parent 338d83b commit 1d40adb
Showing 1 changed file with 22 additions and 13 deletions.
35 changes: 22 additions & 13 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -847,25 +847,29 @@ def set_cpu_topology_limit(core_limit: int, ignore_user_setting: bool = False) -

def run_in_sandbox(cmd: list[str], env: dict[str, str]=None) -> int:
"""Run a command within a sandbox.
The command will run in an environment that is isolated from the host.
The command will run in an temporary environment that is isolated from the
host where only the path to the Proton, WINE prefix and game directory are
read-write and visible to the running command
When the parent process of the command dies, all of its children will die
with it. A dictionary that contains the user's environment variables is
optional, otherwise the global session environment variables are passed by
default
"""
sandbox_bin = '/usr/libexec/steam-runtime-tools-0/srt-bwrap'
sandbox_bin = Path('/usr/libexec/steam-runtime-tools-0/srt-bwrap')
env = env or dict(protonmain.g_session.env)
pfx = protonprefix()
pfx = os.path.expanduser(os.environ.get("STEAM_COMPAT_DATA_PATH") or "")
proton = protondir()
game = get_game_install_path()
winetricks_cache = Path.home().joinpath(".cache", "winetricks").as_posix()
rootfs = []

if not proton or not pfx:
log.warn("WINEPREFIX or PROTONPATH is not set or empty")
log.warn("Will not execute command")
return 1

if not os.path.exists(sandbox_bin):
if not sandbox_bin.is_file():
log.warn(
f'Failed to find sandboxing tool in {os.environ.get("PRESSURE_VESSEL_RUNTIME")}'
)
Expand All @@ -879,7 +883,7 @@ def run_in_sandbox(cmd: list[str], env: dict[str, str]=None) -> int:
return retc

# Don't execute in a sandbox when using a Flatpak
if os.environ.get('FLATPAK_ID') and os.path.exists(sandbox_bin):
if os.environ.get('FLATPAK_ID') and sandbox_bin.is_file():
log.info(f'Flatpak environment detected: {os.environ.get("FLATPAK_ID")}')
log.info('Will not execute command in a sandbox')
return subprocess.run(
Expand All @@ -888,14 +892,19 @@ def run_in_sandbox(cmd: list[str], env: dict[str, str]=None) -> int:
env=env,
).returncode

# Mount the entire filesystem read-only and unshare all namespaces except
# the network
# The path to the WINE prefix, Proton directory and the game directory
# will be remounted read-write
# Mount the root filesystem read-only except for the home directory
# The home directory will be invisible except the path to the WINE prefix,
# Proton, the game and winetricks cache directory
for path in Path("/").glob("*"):
if path.name != "home":
posix_path = path.as_posix()
rootfs.append("--ro-bind")
rootfs.append(posix_path)
rootfs.append(posix_path)

# Unshare all namespaces except the network
opts = [
'--ro-bind',
'/',
'/',
*rootfs,
'--tmpfs',
'/tmp',
'--dev',
Expand All @@ -916,7 +925,7 @@ def run_in_sandbox(cmd: list[str], env: dict[str, str]=None) -> int:
proton,
'--bind',
game,
game
game,
'--bind-try',
winetricks_cache,
winetricks_cache
Expand Down

0 comments on commit 1d40adb

Please sign in to comment.