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

Use steam runtime to execute proton-wine (copied from old repo) #3

Closed
user23498723452 opened this issue Feb 22, 2019 · 15 comments
Closed

Comments

@user23498723452
Copy link

user23498723452 commented Feb 22, 2019

Source:
Sirmentio/protontricks#39

Impacting my copy of protontricks from here as of a few days ago.

OS: Ubuntu 18.04.1 LTS
Steam Proton version: 3.16.7 Beta
GPU: AMD RX550


Proton wine is built against the steam runtime and a number of issues with winetricks/wineserver/winebus etc arise if they are ran on a system with incomplete, or mismatching library versions. For example, steam-runtime and thus proton-wine-3.16 is built against libpng-12 while ubuntu 18.04 has libpng-16.

My execution looked like this to get the whole of protontricks into the runtime:

$HOME/.steam/ubuntu12_32/steam-runtime/run.sh protontricks 359320


Here is my actual command for Snow:

$HOME/.steam/steam/ubuntu12_32/steam-runtime/run.sh protontricks 244930

@Matoking
Copy link
Owner

Matoking commented Feb 22, 2019

I've created a steam_runtime branch with a new option to run the script under Steam Runtime using the --runtime flag. The branch also has a fix where the PATH environment variable is updated to favor wine binaries located under the active Proton installation instead of the system-wide ones, which could potentially cause issues, though I haven't come across any.

You can install it with

python3 -m pip install git+https://github.com/Matoking/protontricks.git@steam_runtime

and then try running the command

protontricks --runtime 244930 <something>

to see if it works properly.


On another note, I tried testing a few Proton prefixes using the Steam Runtime, but each of them causes winetricks to fail with the following error message:

/mnt/LinuxDataSSD_C/SteamLibrary/steamapps/common/Proton 3.16 Beta/dist/bin/wine cmd.exe /c echo '%ProgramFiles%' returned empty string, error message "wine client error:0: version mismatch 573/572.
Your wine binary was not upgraded correctly,
or you have an older one somewhere in your PATH.
Or maybe the wrong wineserver is still running?"

This happens even if no wine-related binaries are running on the system and even if the game is recently installed and hasn't been touched with winetricks prior to this. Interestingly enough,
running protontricks with Steam Runtime returns Wine executable (version 4.2) corresponding to my system-wide installation:

protontricks --runtime -c "wine --version" 251110

whereas running this without Steam Runtime returns the Wine version corresponding to Proton Wine (3.16):

protontricks -c "wine --version" 251110

PATH environment variable is set the same way in both situations, so the LD_LIBRARY_PATH variable that is set by Steam Runtime's run.sh script is somehow messing this up; if I unset it, winetricks works as it should and the Wine version is 3.16 in both cases.

It could be related to how Arch Linux has packaged Steam, but I haven't researched this issue further for now.

@admalledd
Copy link
Contributor

Just pre-pending to the string for subprocess.call doesn't seem right to my memory (its been a while though since I did python) and that it is best to always have the command be a list/tuple. However when I try to hack that in (and use command=runtime_cmd+shlex.split(args.command)) I get problems with the "shell=True" bit. My feeling is your issue lies around in that, since the runtime doesn't touch PATH, and LD_LIBRARY_PATH should certainly not be mucking it up such that it returns anything system wide when set. Did you pin in steam-runtime some wine.so files?

However, the original code you have (pending fixes/hacks for #4) works fine for me. I am able to run winetricks successfully now that I add --runtime. (Previously, since I lack most of wine's dependancies since I don't have a system installed version, winetricks would fail/error all over the place depending on which library was missing)

PS: maybe protontricks should use the same environment variables to auto-inject steam-runtime?

From reading steam.sh:

STEAM_RUNTIME=1 force enabled, STEAM_RUNTIME=0, force disabled, STEAM_RUNTIME=, custom runtime root path, STEAM_RUNTIME=, enabled automatically

@Matoking
Copy link
Owner

Matoking commented Feb 23, 2019

Just pre-pending to the string for subprocess.call doesn't seem right to my memory (its been a while though since I did python) and that it is best to always have the command be a list/tuple.

The string is used in this case because we want the -c option to support arbitrary shell syntax like wget A; chmod +x A; ./A;. An example is a script created here. For non-shell use cases it's better to pass it as a list. Per the subprocess documentation:

The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence.

Regardless, the fix here is a bit hacky; it's probably better to add a parameter to call_command instead of appending the run.sh script everywhere.

PS: maybe protontricks should use the same environment variables to auto-inject steam-runtime?

From reading steam.sh:

STEAM_RUNTIME=1 force enabled, STEAM_RUNTIME=0, force disabled, STEAM_RUNTIME=, custom runtime root path, STEAM_RUNTIME=, enabled automatically

Sounds like a good idea if I can get the Steam Runtime working in protontricks.

@Matoking
Copy link
Owner

Matoking commented Feb 24, 2019

I ran strace with both Steam Runtime on and off and it seems like Steam Runtime's run.sh is causing the wrong library to be discovered. Namely, when searching for libwine.so.1:

With --runtime, the first match is in /usr/lib32/libwine.so.1 (incorrect)

Without --runtime, it looks for it in <PROTON INSTALL DIR>/dist/lib/libwine.so.1 (correct).

The LD_LIBRARY_PATH that run.sh generates is the following (the culprit here is the /usr/lib32):
LD_LIBRARY_PATH=/home/matoking/.steam/root/ubuntu12_32/steam-runtime/pinned_libs_32:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/pinned_libs_64:/usr/lib32:/usr/lib32/libva1:/usr/lib:/usr/lib/libva1:/usr/lib/R/lib:/usr/lib/libfakeroot:/usr/lib/libgig:/usr/lib/libstrangle/lib32:/usr/lib/libstrangle/lib64:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/i386/lib/i386-linux-gnu:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/i386/lib:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/i386/usr/lib:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/amd64/lib/x86_64-linux-gnu:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/amd64/lib:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/lib/x86_64-linux-gnu:/home/matoking/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/lib:

@admalledd
Copy link
Contributor

Hrm, sounds like something we could maybe tweak/detect via the STEAM_RUNTIME_PREFER_HOST_LIBRARIES=0 environment variable for run.sh?

Mine with default/unset:

/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/pinned_libs_32:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/pinned_libs_64:/usr/lib/x86_64-linux-gnu/libfakeroot:/lib/i386-linux-gnu:/usr/lib/i386-linux-gnu:/usr/local/lib:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib32:/usr/lib32:/lib:/usr/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/lib/i386-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/usr/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/lib/x86_64-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/lib/x86_64-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/lib:

and with STEAM_RUNTIME_PREFER_HOST_LIBRARIES=0, note this has bash giving complaints about old/missing libraries on its startup:

bash: /home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/lib/x86_64-linux-gnu/libtinfo.so.5: no version information available (required by bash) /home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/lib/i386-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/i386/usr/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/lib/x86_64-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/lib:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/lib/x86_64-linux-gnu:/home/admalledd/.steam/root/ubuntu12_32/steam-runtime/amd64/usr/lib:

I actually have no proper recommendation here: by default we should just let run.sh do its thing per the users ENV they already setup. However it seems that having a system-wide wine installed breaks its assumptions for proton' paths. Buggar.

@Matoking
Copy link
Owner

I noticed the run.sh script has a --print-steam-runtime-library-paths command that simply prints the value it would use for LD_LIBRARY_PATH. Taking that value and prepending Proton installation's library directories to it seems to make Steam Runtime run even on my system with a system-wide Wine installation.

Please give it a try.

@user23498723452
Copy link
Author

I notice that PATH is being modified. (unless I'm misreading the code). Is there anyway to accomplish this without doing so?

@Matoking
Copy link
Owner

I notice that PATH is being modified. (unless I'm misreading the code). Is there anyway to accomplish this without doing so?

Is that a problem in certain scenarios? The point is that wineserver, wine-preloader launch the correct Proton-specific executables instead of the system-wide ones.

@user23498723452
Copy link
Author

user23498723452 commented Feb 25, 2019

This is a gaming platform. Making that the first place checked for execution of code seems quite risky - given the higher likelihood of malicious third party code (than say OS binaries). People write scripts and code that can make some bad decisions. This covers anything like mods and unknown package dependencies.

@Matoking
Copy link
Owner

Matoking commented Feb 25, 2019

This is a gaming platform. Making that the first place checked for execution of code seems quite risky - given the higher likelihood of malicious third party code (than say OS binaries). People write scripts and code that can make some bad decisions. This covers anything like mods and unknown package dependencies.

The PATH environment variable is only changed for the duration of the call, and only in the context of the executed command.

I find the malware angle unlikely: if the attacker had access to the user's home directory, it would be far easier to dump something malicious in ~/.bashrc instead of ~/.steam/steamapps/common/Proton 3.16/dist/bin on the off-chance something placed there will be executed later.

The directory in question also doesn't contain any binaries except those related to Wine (wine, wine-preloader, wine64, wine64-preloader and wineserver to be exact), so I don't see danger in a 3rd party script running the wrong executable; the whole point of using protontricks is limiting changes to game-specific Wine prefixes and the Proton flavored version of Wine they use.

There's also the option of creating temporary aliases in the context of the call (eg. alias winetricks=<PROTON_PATH>/dist/bin/winetricks), but that would likely only cause confusion with commands like whereis.

@user23498723452
Copy link
Author

That is a reasonable response in my layman's understanding. I at least wanted to raise my concern on it. Thanks for your thoughtful response!

@admalledd
Copy link
Contributor

Note: if STEAM_RUNTIME is fully unset it doesn't exist in the os.environ dictionary at all, like on my system. Thus an error of:

File "/home/admalledd/dev/one_offs/protontricks/src/protontricks/cli.py", line 133, in main
    steam_runtime_path = find_steam_runtime_path(steam_root=steam_root)
File "/home/admalledd/dev/one_offs/protontricks/src/protontricks/steam.py", line 194, in find_steam_runtime_path
    if os.environ["STEAM_RUNTIME"] == "0":
File "/usr/lib/python3.6/os.py", line 669, in __getitem__
    raise KeyError(key) from None
KeyError: 'STEAM_RUNTIME'

Probably change those to os.environ.get()? and some tweaks to steam.py:find_steam_runtime_path() since the .get() will return None and os.path.isdir() does not like that.

Hacky diff once again, probably find a better way:

diff --git a/src/protontricks/cli.py b/src/protontricks/cli.py
index 90c1dbb..8b54b21 100755
--- a/src/protontricks/cli.py
+++ b/src/protontricks/cli.py
@@ -128,7 +128,7 @@ def main():
    steam_runtime_path = None
    runtime_enabled = False

-    if os.environ["STEAM_RUNTIME"] != "0" and not args.no_runtime:
+    if os.environ.get("STEAM_RUNTIME") != "0" and not args.no_runtime:
        runtime_enabled = True
        steam_runtime_path = find_steam_runtime_path(steam_root=steam_root)

diff --git a/src/protontricks/steam.py b/src/protontricks/steam.py
index 502628c..41d687f 100644
--- a/src/protontricks/steam.py
+++ b/src/protontricks/steam.py
@@ -191,16 +191,11 @@ def find_steam_runtime_path(steam_root):
    Find the Steam Runtime either using the STEAM_RUNTIME env or
    steam_root
    """
-    if os.environ["STEAM_RUNTIME"] == "0":
+    if os.environ.get("STEAM_RUNTIME") == "0":
        # User has disabled Steam Runtime
        logger.info("STEAM_RUNTIME is 0. Disabling Steam Runtime.")
        return None
-    elif os.path.isdir(os.environ["STEAM_RUNTIME"]):
-        # User has a custom Steam Runtime
-        logger.info(
-            "Using custom Steam Runtime at %s", os.environ["STEAM_RUNTIME"])
-        return os.environ["STEAM_RUNTIME"]
-    elif os.environ["STEAM_RUNTIME"] in ["1", ""]:
+    elif os.environ.get("STEAM_RUNTIME") in ["1", "", None]:
        # User has enabled Steam Runtime or doesn't have STEAM_RUNTIME set;
        # default to enabled Steam Runtime in either case
        steam_runtime_path = os.path.join(
@@ -209,6 +204,11 @@ def find_steam_runtime_path(steam_root):
        logger.info(
            "Using default Steam Runtime at %s", steam_runtime_path)
        return steam_runtime_path
+    elif os.path.isdir(os.environ.get("STEAM_RUNTIME")):
+        # User has a custom Steam Runtime
+        logger.info(
+            "Using custom Steam Runtime at %s", os.environ.get("STEAM_RUNTIME"))
+        return os.environ.get("STEAM_RUNTIME")

    logger.error(
        "Path in STEAM_RUNTIME doesn't point to a valid Steam Runtime!")

Otherwise, seems to be working? Although I have no steam apps needing complex winetricks at the moment so I can only check that basics work like dotnet45 into an empty prefix.

@Matoking
Copy link
Owner

Thanks, I tested the script with that value set to a path, 1 and an empty value, but I didn't have the idea to test the scenario where it doesn't exist. I force pushed a commit with that issue fixed, which hopefully means that this issue is done except for the changelog, which I'll update shortly.

@user23498723452
Copy link
Author

user23498723452 commented Feb 27, 2019

I'm unable to fully test (my original issue was unable to uninstall an app - which I'm not going to try to repeat), but it appears to load fine (no errors in console) and I can access the Uninstaller and regedit without issue.

Thanks @Matoking @admalledd for your help on this issue!

Matoking added a commit that referenced this issue Feb 27, 2019
The 'run.sh' script included with Steam Runtime causes the wrong
libwine.so.1 file to be discovered if system Wine is installed due to
the script creating LD_LIBRARY_PATH env var that disregards the Proton
installation.

To prevent this, use the script's `--print-steam-runtime-library-paths`
command to print the library paths for use with LD_LIBRARY_PATH and then
prepend them with the Proton installation's own library directories.
This ensures the Proton installation's libwine.so.1 is used instead.

protontricks also now supports STEAM_RUNTIME env var used with Steam.
Steam Runtime is enabled by default.
@Matoking
Copy link
Owner

I tested this fix out on a Kubuntu 18.04 VM and everything seems to check out. Everything checks out, so I've merged this to master.

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

No branches or pull requests

3 participants