Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot access filesystem outside container on Sniper runtime #717

Open
stormytuna opened this issue Nov 19, 2024 · 9 comments
Open

Cannot access filesystem outside container on Sniper runtime #717

stormytuna opened this issue Nov 19, 2024 · 9 comments

Comments

@stormytuna
Copy link

Your system information

Please describe your issue in as much detail as possible:

Some Steam games (in this case tModLoader) have development tools that rely on the user installing sdks or other software on their system (in this case dotnet). Previously we could locate these tools by running the which command. Is there a way for our game to enable read access to [portions of] the host filesystem, or a way to execute processes outside the sandbox?

@smcv
Copy link
Contributor

smcv commented Nov 20, 2024

I'm writing this with an audience of app/game maintainers in mind more than end users, so if you're a gamer but not an app/game/mod developer, it might not be 100% relevant to you - it might be more relevant to @Chicken-Bones and other tModLoader contributors.

a way to execute processes outside [the Steam Linux Runtime]

This is technically already possible, but the way it works bypasses all of the things that Steam does to try to help to make your app/game portable between different distributions - so it will be up to your app/game to deal with all the various possible error conditions (not just the obvious "there is no foobar in the PATH", but also "there is a foobar but it doesn't work", "there is a foobar but its directory layout is totally different", "there is a foobar but it's 10 years old", and 10 years from now, "there is a foobar but it's 10 years newer than my codebase expected").

I'm going to look at improving the documentation around this, so that we can point developers and mod authors towards it, while making sure that the risks and limitations are documented in the same place as how to achieve it. Right now I'm intentionally being non-specific, until we have the improved documentation in place; but I wanted to respond here first and say that a plan does exist.

Wherever possible I'd recommend treating this facility as something that is available for debugging and development, but is not critical-path for the basic end-user-facing functionality of whatever app/game is in use. If I'm reading correctly, tModLoader wants .Net for mod developers (perhaps to run a C# compiler or similar?), but users who just want to run a modded game don't need it? That's probably a reasonable way to use this - mod developers presumably have lower expectations about perfect compatibility with arbitrary distros several years into the past or future.

For the core functionality of the app/game itself, the design is a lot like Flatpak: the only things you can count on are whatever is provided as part of the runtime (which notably doesn't include .Net or other "big" language frameworks like Java), and whatever is bundled in the app/game.

If the use-case for this is something non-interactive like a compiler, providing it as a Docker/Podman/Toolbx container image outside the scope of Steam or SLR might be an alternative to integrating it into a Steam app/game? The official SDK for building apps/games that run under SLR is not provided via Steam either, because Steam isn't really designed for that: we provide a Docker/Podman/Toolbx image because that's often a better fit for that sort of developer-facing use-case.

the sandbox

The Steam Linux Runtime is a container, but not a sandbox: there is no meaningful security boundary (the most it does is to protect against accidents). For issues like this one, that's a good thing - it means we can provide the mechanism you're asking for, without having to say "no, because that would be a security vulnerability".

to enable read access to [portions of] the host filesystem

You actually already have read access to most of the host filesystem, but you can't simply run arbitrary commands from it, because the container's library stack is set up to be compatible with SLR 3.0, rather than being compatible with whatever host system the user might be using (and sometimes those can be mutually exclusive, because Linux distributions aren't fully compatible with each other).

@Chicken-Bones
Copy link

You have understood our requirements perfectly. Ideally the game itself would continue to run in the compatibility environment even for modders, and only external tooling which we do not ship (primarily the dotnet sdk for building C#) would be executed in the host system.

Even though it would be possible to ship a dotnet sdk as an optional component, we would rather reference the one on the user's system, providing them more control over their toolchain and keeping it in line with other development software they may have such as IDEs.

@smcv
Copy link
Contributor

smcv commented Nov 29, 2024

Ideally the game itself would continue to run in the compatibility environment even for modders, and only external tooling which we do not ship (primarily the dotnet sdk for building C#) would be executed in the host system.

That is certainly something that you could do. The way you can do this, which I alluded to above, is now documented:

https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/docs/slr-for-game-developers.md#running-commands-outside-the-container

If you're familiar with Flatpak, the way this works is very similar to flatpak-spawn --host (which is not allowed for most Flatpak apps because it would be a sandbox escape, but our use-case in SLR is not intended to be a security boundary, therefore we allow it).

Or, if you're not familiar with Flatpak, you can think of it as being a bit like running a sshd on the host system, and using a ssh client inside the SLR container to connect to it. (It doesn't use the ssh protocol, but the idea is vaguely similar.)

As with ssh and flatpak-spawn, if you make use of this mechanism, you'll have to coordinate between two different "worlds", with different views of the filesystem: the one inside the container, and the one on the outside where you run dotnet.

If the use-case for this is something non-interactive like a compiler, providing it as a Docker/Podman/Toolbx container image outside the scope of Steam or SLR might be an alternative to integrating it into a Steam app/game?

This continues to be something you could consider as an alternative way to support mod developers.

@Chicken-Bones
Copy link

Thankyou for the documentation. I was able to follow the instructions to execute commands on the host on a Linux machine, however I had trouble when running some tests under WSL2.

When running:
Process.Start (UseShellExecute = False): "steam-runtime-launch-client" --alongside-steam --host -- which dotnet
Our log files show the following native error
<3>steam-runtime-launch-client[4719]: E: Can't find session bus: Failed to execute child process ?dbus-launch? (No such file or directory)

Running the following in a terminal on the host also shows the error

cb@MOCHI:~$ .steam/debian-installation/steamapps/common/SteamLinuxRuntime_sniper/run -- steam-runtime-launch-client --alongside-steam --host -- which dotnet
steam-runtime-launch-client[5092]: E: Can't find session bus: Failed to execute child process “dbus-launch” (No such file or directory)

@smcv
Copy link
Contributor

smcv commented Jan 23, 2025

Yes, this feature requires a working D-Bus session bus (and I'm sure there are other Steam features that do, too). If WSL2 doesn't normally provide one of them, it might help to run your debugging session as something like

dbus-run-session -- bash -i

which will give you a session bus as long as that shell is running; and then run Steam from inside that environment.

Steam-for-Linux is designed to run on an actual Linux desktop system; if it runs successfully on WSL2 as well then that's a bonus, but WSL2 has some limitations that mean not everything is going to work.

@smcv
Copy link
Contributor

smcv commented Jan 23, 2025

cb@MOCHI:~$ .steam/debian-installation/steamapps/common/SteamLinuxRuntime_sniper/run

If you are launching a sniper container directly, without using Steam, then steam-runtime-launch-client --alongside-steam will not work without some additional setup. It requires a service that is normally run automatically by Steam.

You can provide a mockup of this service by running something like this, inside the same D-Bus session as all the commands that will try to talk to it:

steam-runtime-launcher-service --alongside-steam &

and waiting for it to start (it will show some information on standard output when it is ready for use).

@Chicken-Bones
Copy link

Thanks, I was able to upgrade my WSL2 testing environment with dbus and everything worked (We tested on a real linux system prior, WSL is just easier for development).

Our game currently uses xdg-open to open URLs and folders on the filesystem, what's the recommended alternative for these two? Should we also use steam-runtime-launch-client --alongside-steam --host?

@smcv
Copy link
Contributor

smcv commented Jan 24, 2025

If your engine/runtime library has an API to do what you want to do without launching a subprocess, I'd recommend trying that first. For example SDL has SDL_OpenURL() (which I think currently just runs xdg-open on Linux, but future versions might do something cleverer or more efficient, and if so, you'll automatically benefit from that when the runtime gets upgraded).

The next best thing is that you can/should keep using the xdg-open command. The container runtime has a reimplementation of xdg-open which does its best to send your URL or filename out of the container to the host system somehow; it's currently implemented by sending http(s): and steam: URLs to Steam (which will probably work on WSL) and other URL types like file: to xdg-desktop-portal (unlikely to work on WSL without extra setup). I suppose we could make it do the equivalent of steam-runtime-launch-client --alongside-steam --host -- xdg-open ... as a last resort.

Please try to avoid using steam-runtime-launch-client unless you do genuinely need arbitrary code execution: it's intended as a developer/debugging tool rather than something that would be used for gameplay, and it makes it very easy to accidentally do non-portable or non-future-proof things.

@Chicken-Bones
Copy link

Thankyou for your advice, it will be followed. I verified that xdg-open continues to work seamlessly on standard Linux systems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants