Moved ~/.local/share/steam. Ran steam. It deleted everything on system owned by user. #3671

Closed
keyvin opened this Issue Jan 14, 2015 · 262 comments

Comments

Projects
None yet

keyvin commented Jan 14, 2015

Edit: Please stop posting stupid image memes or unhelpful messages. This interferes with Valve's ability to sift through the noise and see if anyone can figure out what triggers it.

This may not be a common problem because I change all sorts of configuration about my system. The script in question does something in a really, really stupid way, but it probably doesn't trigger the fail scenario for every system because...

Original Bug:
I am not sure what happened. I moved the folder in the title to a drive mounted under /media/user/BLAH and symlinked /home/user/.local/steam to the new location.

I launched steam. It did not launch, it offered to let me browse, and still could not find it when I pointed to the new location. Steam crashed. I restarted it.

It re-installed itself and everything looked great. Until I looked and saw that steam had apparently deleted everything owned by my user recursively from the root directory. Including my 3tb external drive I back everything up to that was mounted under /media.

Everything important, for the most part, was in the cloud. It is a huge hassle, but it is not a disaster. If there is the chance that moving your steam folder can result in recursively deleting everything in the directory tree you should probably just throw up an error instead of trying to point to other stuff. Or you know, allow the user to pick an install directory initially like on windows.

My system is ubuntu 14.04, and the drive I moved it to was ntfs if its worth anything.

doofy commented Jan 15, 2015

I am impressed how calm you stay about this. This is terrible. I just lost my home directory. All i did was start steam.sh with STEAM_DEBUG=1. I will investigate this and report back.

edit1: I suspect steam.sh got some bugs(does not check own variables) and when it tried to do scary things it crapped himself.
Line 468: rm -rf "$STEAMROOT/"*

edit2: It gets better. Seems on windows Steam is overeager too! https://support.steampowered.com/kb_article.php?ref=9609-OBMP-2526 (The warning part is interesting. Because everybody reads this before uninstalling...)

Tele42 commented Jan 15, 2015

I agree, that line minimally requires an exists and not null check for $STEAMROOT

keyvin commented Jan 15, 2015

#scary!

As an ex programmer, that really makes me chuckle. Can I at least get an apology from whoever committed that comment without adding a fix?

This also happened to me a few weeks ago, my entire home was deleted by the steam.sh script.

introduced here Sep 10, 2013 indrora/steam_latest@21cc141 line 359

rm -rf "$STEAMROOT/"* could be evaluated as rm -rf "/"* if $STEAMROOT is empty

but what exactly caused this? i've symlinked ~/.local/share/steam to, so i am a bit afraid to start steam :/

TcM1911 commented Jan 15, 2015

pythoneer,

I believe the issue starts on line 19:

# figure out the absolute path to the script being run a bit
# non-obvious, the ${0%/*} pulls the path out of $0, cd's into the
# specified directory, then uses $PWD to figure out where that
# directory lives - and all this in a subshell, so we don't affect
# $PWD

STEAMROOT="$(cd "${0%/*}" && echo $PWD)"
STEAMDATA="$STEAMROOT"

This probably returns as empty which mean: rm -rf "$STEAMROOT/"* is the same ass rm -rf "/"*.

TcM1911,

that's my guess, too.

@ghost

ghost commented Jan 15, 2015

@keyvin @d00fy :
Line proceeded by # Scary! comment is in reset_steam() function, which is executed if and only if steam.sh is invoked with --reset as first argument.

Did any of you deliberately invoked that script with that option? If yes, why did you do it? What were you trying to achieve?

Removing user data is obviously wrong, no doubt about it. But if this happens only when user requests certain action, scope of that issue is somewhat limited.

jthill commented Jan 15, 2015

Yeah, they kinda need a readlink in there.

STEAMROOT=$(readlink -nf "${0%/*}")

jthill commented Jan 15, 2015

@minio Not "only if". reset_steam is also invoked by removing your .steam directory, since that sets INITIAL_LAUNCH

@minio A script accidentally running rm -rf /* is unacceptable in any scenario.

it is like bumblebee all over again!
MrMEEE/bumblebee-Old-and-abbandoned#123

I encountered Steam behaviour like with «--reset» for several times:
when I added «--reset» AND when I didn't. So — not «only if», can
confirm this, even having not deleted ~/.steam/ dir, too.

wonder what the code path is to hit that rm without --reset

indrora commented Jan 15, 2015

Can confirm; I have Steam bounded in an SELinux context ("Steam") and SELinux spits out:

Context violation: process /home/indrora/.local/share/Steam/ubuntu12_32/steam is only allowed in context steam_context, attempted to remove /boot/efi/grub/efistub

Ooops. I'll write a patch and PR it 🍺

@johnv-valve johnv-valve self-assigned this Jan 15, 2015

Owner

johnv-valve commented Jan 15, 2015

Does anybody have reliable repro steps for this? I can easily add the checks for STEAMROOT being empty, but I would also like to fix the root cause if possible.

rcxdude commented Jan 15, 2015

It will definitely fail if you run steam.sh as bash steam.sh. I don't know if that's the cause in this case. In terms of root cause, I would say you should use set -e, set -u, and similar options in order to make the script less likely to silently ignore errors.

ayust commented Jan 15, 2015

Using ${STEAMROOT:?} instead of $STEAMROOT would have helped, too.

(For those not familiar, ${FOO:?} is identical to $FOO except that it errors out automatically if $FOO is empty or unset.)

Which is the same thing that would have happened had the unnecessary '/*' not been there anyway, it would have errored out. Its not necessary because the rm was set to recursive already...

if [ ! -z "${STEAMROOT}" ]; then
   rm -rf "${STEAMROOT}"
fi

rcxdude commented Jan 16, 2015

Here is a patch which enables set -e, set -u, and a few others, and then fixes up all the places where undefined variables are expected to be (as far as I can tell): https://gist.github.com/rcxdude/1f6257e0a965147a462c

mablae commented Jan 16, 2015

@rcxdude Come on. We are on github here. Do that in a PR please! Do not post whole patch files into issues... 👎

@mablae There is no code on this repo, there is nothing to send in a PR against. A gist wouldn't have gone astray though 😄

slnovak commented Jan 16, 2015

@rcxdude: Please link to a Gist.

sdt16 commented Jan 16, 2015

@mablae How about instead of being a jerk, you link @rcxdude to some documentation.

Tele42 commented Jan 16, 2015

@johnv-valve regardless of tracking down the cause of this, this rm line must be protected from future accidental gremlins due to the severity of the fail scenario.

mablae commented Jan 16, 2015

@dannyfallon Oh, sorry then...
@sdt16 I am sorry. Thought the code was on this repo ... Didn't wanted to be a "jerk" :)

Wapaca commented Jan 16, 2015

Does it happen only if you move ~/.local/share/steam ? #scary! :s

The idiomatic way to do this in Bash is to use default variables as in ,"${var:-/sane/path}" or "${var:?}" as was already mentioned. While using set -u or similar could have prevented this mistake, it's lazy and considered bad style.

doofy commented Jan 16, 2015

If steam really wants to act like a package manager it should only delete files created by itself.

@soren121 +1

ryenus commented Jan 16, 2015

Shell scripts can also have tests, see shunit2. I wish I used it instead of making mini/naive one myself.

damm commented Jan 16, 2015

it's 2015; I think we can do better than complex badly written shell scripts.

rm is dangerous; you should never use rm ${macro}/

@d00fy Steam is essentially a package manager for your games.

@ju2wheels your snippet has a spurious 'D' in it, 'STEAMROOT' versus 'STEAMDROOT' -- so ${STEAMDROOT} will be empty and that code is going to end up starting at the current directory and doing a recursive delete from there.

Could be almost as bad depending what the current directory is. Let's hope nobody copy/pastes that snippet for actual use.

@mpnordland I think that's what he said.

neko commented Jan 16, 2015

Is this the new bumblebee?

nhuerta commented Jan 16, 2015

I hope no one is running this as root

@d00fy I'm going to make the argument that while Steam is certainly at fault, you should definitely be using off site backups for this exact reason.

I hope no one is running this as root

On a typical desktop Linux system that would only make it marginally worse - reinstalling the OS is less of a problem than losing all your data from $HOME

keyvin commented Jan 16, 2015

@john-valve You are more than welcome to any log files that a data recovery service can get from the drive, as long as you give me a copy of everything. I do not have a large drive to undelete to, so the data that wasn't in the cloud is. Mad props for #Scary though

@nicatronTg Yes, I should need to have a complete back up rotation of dailies, four weeklies, and 12 monthlies so that I can feel safe and secure running steam for linux.

nhuerta commented Jan 16, 2015

@DanielGibson Sure, as long as you didn't mount other partitions rw somewhere else

@carlosmcevilly even if they did it would be better than the existing code thats there ;-) , it will just fail and not take the world with it. But.... but... i fixed my typo ;-) , thx.

Hmm.. when I was copying .steam from an older installation to a newer installation of Kubuntu, I saw in stdout messages like "running rm -rf " when I was running it (after the rm -rf it installed Steam again with the 200MB download). Though of course I didn't lose any data.

@keyvin This is somewhat OT but to recovery your data, immediately stop using the external drive and run something like PhotoRec or TestDisk or if the drive has important files you can even use a program like ddrescue to copy the drive. If you haven't used the drive since the data loss then most of your data should be recoverable.

pixelb commented Jan 16, 2015

Note there is also protection against this within GNU rm itself. I.E. this would have protected the / dir at least:

rm -rf "$STEAMROOT/" && mkdir "$STEAMROOT"

But it's best leave out the / in any case as it's redundant

rm -rf "$STEAMROOT" && mkdir "$STEAMROOT"

Bash-isms are the problem here:

(cd `dirname $0`; STEAMROOT=`pwd`)

If dirname and pwd aren't in your "$PATH" then fuck you.

hachre commented Jan 16, 2015

My condolences, @keyvin. I lost all my data like this in 1998 due to a SuSE Linux installation script having exactly this bug in it as well. Back then I lost my Linux, my Windows, and all my data and I only learned what backups are really for from that incident...

@TcM1911 Determining the path of the script being invoked, in a fully portable (w.r.t. platforms) and completely reliable manner, even in the face of symlinks, is a tricky problem and all too easy to get wrong. The only bullet proof way of doing it, of which I'm aware, is provided below (assumes bash); could be prepended to any script needing this functionality.

#!/bin/bash

script_path () {
    local scr_path=""
    local dir_path=""
    local sym_path=""
    # get (in a portable manner) the absolute path of the current script
    scr_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && scr_path=$scr_path/$(basename -- "$0")
    # if the path is a symlink resolve it recursively
    while [ -h $scr_path ]; do
        # 1) cd to directory of the symlink
        # 2) cd to the directory of where the symlink points
        # 3) get the pwd
        # 4) append the basename
        dir_path=$(dirname -- "$scr_path")
        sym_path=$(readlink $scr_path)
        scr_path=$(cd $dir_path && cd $(dirname -- "$sym_path") && pwd)/$(basename -- "$sym_path")
    done
    echo $scr_path
}

script_dir=$(dirname -- "$(script_path)")
Member

MrSchism commented Jan 16, 2015

@sindresorhus I'd disagree with using trash instead of rm because having to rely on node just adds complexity to systems that wouldn't otherwise need node.

It's also worth mentioning that most of the linux distros I've used recently have the --preserve-root flag already available...

@tute tute referenced this issue in coreyleveen/super-pry.io Jan 16, 2015

Merged

Add warning note about security risks #1

I'd disagree with using trash instead of rm because having to rely on node just adds complexity to systems that wouldn't otherwise need node.

I know people disagree with that. That's fine. I was linking to the safeguard rm section.

I've moved my directory and symlinked it too, and I've thankfully not had such issues before. Regardless, as someone mentioned before, I'd strongly suggest adding test cases against such major bugs.

This big companies are so in the need of engineers that would even hire my grandma, and then shit happens.

Strubbl commented Jan 16, 2015

In this context, how can i remove steam from my Linux without using steam?

skybert commented Jan 16, 2015

As @d00fy said, it's amazing how calm you were about this, @keyvin. A great bug report it was too. Embarrassing as bugs like these are, it's a lot easier to take it on with reports like this one.

As others have pointed out too, this is an excellent bug for advocating using some BASH-strictness, I like to use this:

set -euo pipefail

This bug is also a good case for advocating TDD with shunit2. Make the steam script modular so that parts of it can be (unit) tested, write a test for this bug which fails and then fix it. We all do this in other "real" programming languages and there's no reason why we can't do this in BASH too. Hooking it up with CI servers like Jenkins is no problem either.

Tangentially related:

I assume all the people that moved this folder are running out of disk space/want to stuff the files elsewhere. Like myself. This is what I did on Windows just a couple days ago, I'd hope that Steam on Linux supports the same (hidden) option: http://www.rockpapershotgun.com/2012/09/11/finally-an-in-built-way-to-choose-steam-install-locations/

Basically:

  • Close Steam
  • Run steam -dev
  • Click on the new 'Console' tab
  • Enter 'install_folder_ui' (you even get tab completion)
  • Add a new path, say .. /media/steam
  • Close steam, restart without -dev

Now you can pick the location during installation ("This game? Install to my SSD. That? Ah, large slow disk is fine"). You can also move games between locations (from $path1/SteamApps/common to $path2/SteamApps/common and that will 'just work' in nearly all cases).

So, maybe Valve should make that more accessible in the UI, bypassing the need of users to mess with the default install path?

lodyb commented Jan 16, 2015

Thanks for reminding me to always check shell scripts before executing them

@darklajid changing the destination can already be done without using -dev, console, and install_folder_ui.

steam -> settings -> downloads -> steam library folders

@synapse84 Whoa - and here I kept that bookmark around, treasuring my knowledge of hidden options. :) Thanks a lot!

dsohler commented Feb 10, 2015

Solution: Just don’t delete user data. Ever.

Has this issue not been fixed yet? If it has been fixed, it should be closed. If it is not fixed, it needs more attention.

Owner

kisak-valve commented Mar 10, 2017

Yes, the issue that is tracked in this issue report was resolved.

@soredake soredake referenced this issue in lutris/lutris May 9, 2017

Closed

Allow arguments in prefix command. #564

ypid referenced this issue in hamishcoleman/thinkpad-ec Jun 22, 2017

KellerFuchs added a commit to KellerFuchs/admin-tools that referenced this issue Aug 29, 2017

ansible.cfg: Error-out on undefined variables
This sort of behaviour has been the cause for some very high-profile bugs,
like [0], and is generally not a super-safe default.

It is always possible to use the [default] filter explicitely where this sort
of behaviour is desired.

[0]: ValveSoftware/steam-for-linux#3671
[default]: https://docs.ansible.com/ansible/latest/playbooks_filters.html#defaulting-undefined-variables

@KellerFuchs KellerFuchs referenced this issue in hashbang/admin-tools Aug 29, 2017

Merged

ansible.cfg: Error-out on undefined variables #81

craig-sanders commented Sep 12, 2017

kisak-valve said that this is resolved. It's not, the "fix" doesn't do anywhere near enough sanity checking for a script that has the potential to delete the user's files.

Here's what I consider to be the absolute minimum level of sanity checking required:

(This script was written by me and is hereby placed in the public domain, or the 2-clause BSD license if you are in a jurisdiction that does not acknowledge "public domain". Do whatever you want with it, no royalties or any form of compensation or acknowledgement is expected or required, even the BSD license requirement to include a copyright notice is waived. I renounce all rights to this trivial code)

$ cat /tmp/steamhome.sh 
#!/bin/bash

# Example of a minimal fix for:
# https://github.com/valvesoftware/steam-for-linux/issues/3671
#
# Notes:
# 0. This script is public domain or, at your option, BSD-licensed.
# 1. The steam.sh script has 'STEAMROOT="$(cd $(dirname $0) && echo $PWD)"'
#    WTF! that's crazy.  assignment by side-effect (and hoping the `cd` doesn't fail),
#    is just tempting Murphy, and whoever wrote it doesn't know bash's built-in `pwd`
#    returns the current dir, as does `/bin/pwd` which has existed for decades.
# 2. in case it ever matters, FreeBSD's `stat` command is not the same as GNU's and has
#    slightly different printf-style formatting options, and their `readlink` only has
#    a `-f` option rather than `-e`, but that's adequate for this job.

STEAMDEBUG=1

dumpsteamvars() {
  # if $STEAMDEBUG is 1 display all env vars with 'STEAM' in the name
  [ "$STEAMDEBUG" == '1' ] && typeset -p  | grep STEAM
}

error() {
  # This function takes either 1 or 2 arguments, a message to print to stderr
  # (required), optionally preceded by an exit code (defaults to 1 if missing)

  local exitcode=1
  [ -n "$2" ] && exitcode="$1" && shift

  printf "FATAL: %s\n" "$1" >&2

  dumpsteamvars

  exit $exitcode
}

# SteamOS is Linux, so we can assume GNU coreutils, which includes basename,
# dirname, readlink, id, stat, etc.

# base name of the script, i.e. without the path.
STEAMCMD="$(basename "$0")"
[ -z "$STEAMCMD" ] && error 1 "STEAMCMD is empty"

# 'readlink -e' canonicalises the path/filename, resolving all symlinks
STEAMROOT="$(dirname "$(readlink -e "$0")")"
[ -z "$STEAMROOT" ] && error 2 "STEAMROOT is empty"
cd "$STEAMROOT"

STEAMUSER="$(id -u -n)"                       # login name of the user running steam
STEAMUID="$(id -u)"                           # numeric uid of that user
STEAMROOTUID="$(stat -c '%u' "$STEAMROOT")"   # numeric uid of $STEAMROOT directory's owner.
STEAMROOTOWNER="$(id -u -n "$STEAMROOTUID")"  # login name of $STEAMROOT directory's owner.

# now check for some problems that could lead to disaster and
# abort on anything even slightly dodgy.
[ -z "$STEAMUSER"                ] && error 3 "STEAMUSER is empty"
[ -z "$STEAMUID"                 ] && error 4 "STEAMUID is empty"
[ -z "$STEAMROOTUID"             ] && error 5 "STEAMROOTUID is empty"
[ "$STEAMUID" != "$STEAMROOTUID" ] && error 6 "$STEAMROOT owned by $STEAMROOTOWNER($STEAMROOTUID).  STEAMROOT should be owned by $STEAMUSER($STEAMUID)"
[ ! -e "$STEAMROOT/$STEAMCMD"    ] && error 7 "Something very odd is going on, can't find myself ($STEAMCMD is not in $STEAMROOT)"

# put more sanity checks here

echo "Everything seems to be OK"
dumpsteamvars

If I save this as /tmp/steamhome.sh and run it, I get:

$ /tmp/steamhome.sh 
FATAL: /tmp owned by root(0).  STEAMROOT should be owned by cas(1000)
declare -- STEAMCMD="steamhome.sh"
declare -- STEAMDEBUG="1"
declare -- STEAMROOT="/tmp"
declare -- STEAMROOTOWNER="root"
declare -- STEAMROOTUID="0"
declare -- STEAMUID="1000"
declare -- STEAMUSER="cas"


Exactly what it's supposed to do. If I copy it to ~/.steam/ and run it, I get:

$ cp /tmp/steamhome.sh ~/.steam/
$ ~/.steam/steamhome.sh 
Everything seems to be OK
declare -- STEAMCMD="steamhome.sh"
declare -- STEAMDEBUG="1"
declare -- STEAMROOT="/home/cas/.steam"
declare -- STEAMROOTOWNER="cas"
declare -- STEAMROOTUID="1000"
declare -- STEAMUID="1000"
declare -- STEAMUSER="cas"

Again, exactly what it's supposed to do.

And, thanks to readlink -e, if ~/.steam/steamhome.sh is a symlink to e.g. /tmp/steamhome.sh:

$ ln -sf /tmp/steamhome.sh ~/.steam/
$ ~/.steam/steamhome.sh 
FATAL: /tmp owned by root(0).  STEAMROOT should be owned by cas(1000)
declare -- STEAMCMD="steamhome.sh"
declare -- STEAMDEBUG="1"
declare -- STEAMROOT="/tmp"
declare -- STEAMROOTOWNER="root"
declare -- STEAMROOTUID="0"
declare -- STEAMUID="1000"
declare -- STEAMUSER="cas"

arno01 commented Oct 5, 2017

You are always welcomed to use a containerized Steam (no performance impact) in case you afraid it can damage anything on your system, except the Steam-related files itself of course --
https://hub.docker.com/r/andrey01/steam/

dsohler commented Oct 5, 2017

Always put Steam in a 32 bit chroot in order to run it on a recent system (64 bits of course). Only game devs want 32 bit nowadays so a chroot is necessary anyways if you don't want to clutter your system with a shitload of multiarch stuff.

If you prevent steam from deleting all your data that's a bonus, too.

mhalano commented Oct 5, 2017

In fact containers and chroot are very secure, but isn't the best option from user's POV. An application which sane scripts which doesn't delete all your files still is the best option. May be one day when Flatpak and Snap become a standard we can rethink this.

Germano0 commented Oct 9, 2017

@mhalano You have to consider that many devs on steam stop supporting Linux because they say "1% of our customers use Linux but they account for 50% of our support requests". In view of this steam should be distributed as a container to keep as much of the environment under control as possible.

Source?

dsohler commented Oct 9, 2017

An application which sane scripts which doesn't delete all your files still is the best option.

Yes, of course. But as long as the software needs 32 bit libs I'm not going to run it outside a chroot/container/whatever. I don't want to clutter my system with multiarch crap.

polkovnikov-ph commented Oct 9, 2017

"1% of our customers use Linux but they account for 50% of our support requests"

No surprise. Most of players on Windows are kids, most of players on Linux are programmers. Also these are "bug reports" and not "support requests".

Bengt commented Oct 9, 2017

@mhalano You have to consider that many devs on steam stop supporting Linux because they say "1% of our customers use Linux but they account for 50% of our support requests". In view of this steam should be distributed as a container to keep as much of the environment under control as possible.

Yeah, it is really a big problem for content creators to have an engaged audience. /s

@ohjames, but it could. There isn't a lot of finality either way without more data. These users could be finding valid bugs, in which case they are doing the developers a service.

dsohler commented Oct 10, 2017

An engaged audience does not equate to a large number of support requests.

Bug reports aren't support requests.

So some random guy said "An engaged audience does not equate to a large number of support requests" twice but I have no idea why this truism is being repeatedly asserted?

kon14 commented Oct 11, 2017

no they didn't, and you're being neither funny nor clever.

@ohjames He's just treating you with your own medicine.
Using some random dev's made up percentage fud as a fact is no better than what Garry Newman does.

But I guess now that you deleted your comments people can't actually support any of this, right?
Right, cause deleting your comments is definitely going to end this convo (whether you're being harassed justly or wrongfully).

In any case, this is all off-topic, isn't that so?

simi commented Oct 11, 2017

@kisak-valve please can you lock this? It's getting really off-topic here.

@simi, the issue is closed, but not fixed as well as it should be. Locking it is going to keep the issue from being re-opened and actually resolved.

Owner

kisak-valve commented Oct 11, 2017

I'd rather not lock issue reports if I don't need to. At this point, I'd need either a test case that causes this issue or a request from a Steam dev to re-open this issue.

Since there is over a hundred participants on this issue report, I'd like to see at least 25 thumbs up on @simi's request to lock this issue.

mhalano commented Oct 11, 2017

If Valve properly fix the problem (is not that hard) the off-topic messages go away.

@kisak-valve, @craig-sanders has shown a fix here: #3671 (comment)

hasufell commented Oct 11, 2017

@kisak-valve, @craig-sanders has shown a fix here: #3671 (comment)

Sorry, but none of you really understand the problem. The problem is not the lack of arbitrary sanity-checks, the problem is that recursive deletion is an inherently problematic operation, especially if it is non-interactive. That is also why no package manager out there will ever do rm -r in any way. You track the installed files and only ever remove known files, never directories and never recursive.

simi commented Oct 11, 2017

@kisak-valve issue was marked as closed (and by your comment also as resolved) and it is here just for annoying offtopic discussion. I don't see any reason to keep it unlocked and keep offtopic discussion. I would like to stay watching this issue, but I don't care about offtopic.

Once there will be news, you can:

  1. unlock
  2. comment as member (even it is locked)

and interested people will get notification.

h1z1 commented Oct 12, 2017

I don't know if they enjoy the publicity and free labor or what but Valve will never fix problems like this, seriously there are many threads like it on github alone. Looking at steam.sh should make anyone cry in a corner.

There are lovely assumptions like this all over the place:

 # Save the prompt in a temporary file because it can have newlines in it
    tmpfile="$(mktemp || echo "/tmp/steam_message.txt")"

That is so wrong on so many levels but they've hardcoded things everywhere. I can only imagine what the Windows client is like.

This one just boggles my mind:

    # Set up the link to the source code
     ln -sf "$STEAM_RUNTIME/source" /tmp/source
     else
          echo $"STEAM_RUNTIME couldn't download and unpack $STEAM_RUNTIME_DEBUG_URL, falling back to $STEAM_RUNTIME"

Look around those lines and cry. The RUNTIME_DEBUG_URL is based on a grep with no error checking. Isn't even over SSL. Rather hilarious thing is they explicitly force http1.0 in download_archive anyway.

My point is there are so many places this bug can surface it's no wonder Valve are unable to fix it. I wouldn't personally go near a LAN with steam running.

dsohler commented Oct 12, 2017

Conclusion: They have absolutely no idea how to develop software for Linux-based operating systems.

Conclusion: They have absolutely no idea how to develop software for Linux-based operating systems

That is correct. And it's not even so much about the poor quality shell scripting. They don't use the opensource community to their benefit. They have no understanding of the ecosystem or the community.

There are lots of people out there that would rewrite their scripts for free and even collaborate on linux-specific steam code. Apart from the tons of suggestions here, there have also been numerous PRs about making the scripts POSIX compatible and whatnot. They have been ignored.

Linux is basically a platform where you get reviews, suggestions, code and even professional help for free. Except valve doesn't use it. That's not really a problem of "oh, I let my grandma write the bash scripts that handle safe user data removal", it's your huge ignorance of the specificities of a platform and its community. Something went wrong during your "linux agenda".

But it totally makes sense given the way Valve works internally. There was employee or a group that made the project, but now they are either not interested in it or not even employed anymore. Who will merge PRs, if nobody knows the code?

@hasufell yes, keeping track of all files and deleting only known files when uninstalling is what a package manager should do.

Steam doesn't do that, and likely never will. Steam isn't a real package manager. It's a game library manager originally written for an OS where package management is an alien concept, where each program is installed by running its own installer program (and assumes it's the only program that will ever run on the system so can do whatever TF it wants to without caring about screwing up other software the user may have installed)....For all its flaws, Steam on windows is actually a great leap forward compared to that even if it does seem primitive and broken compared to standard practice on linux or mac. Hell, even on Linux you still get idiot devs telling users to ignore the package manager and just run make install or the insanely insecure curl URL | bash.

Anyway, as always, it's more useful to deal with things as they are, not as they would be in an ideal world. Without the magic ability to make steam work like a real package manager, having a bunch of paranoid sanity checks in front of anything that affects file deletion is the most useful thing to do....equalled only by:

  1. fixing all the shell coding mistakes, including:
  • The $" pointed out by @h1z1. That is not the only instance - there are 21 more in my copy of steam.sh as of today. $" is valid syntax in bash but I doubt very much that the script author's purpose was to do locale translation.
  • failure to consistently and properly double-quote variables
  • use of backticks rather than $(). and failure to double-quote $().
  1. carefully examine every instance of rm -r in the script (7 according to grep -c) and make sure they're as safe as possible given the hackish nature of the script. Perhaps even write a safe_rm wrapper function that does some sanity checking (e.g. existence and ownership of dir), before doing a recursive deletion, and use that wherever rm -r is run.

  2. the many newbie errors like:

  • #!/usr/bin/env bash. bash is always in /bin on a linux system, also on OS X. and using env to find a script interpreter is brain-damaged.
  • piping grep into grep and then into awk - this is never necessary as awk can do regular expression pattern matching all by itself, e.g. (simplified version of steam.sh line 594):
    ldd "$1" | grep X | grep -v Y | grep -v Z | awk '{print $1}'
    is better written as
    ldd "$1" | awk '/X/ && ! /Y|Z/ {print $1}'
    or perhaps even
    ldd "$1" | awk '/not found/ {print $1}'
    since that seems to be the purpose of that line.
  • failure to program defensively - i.e. don't assume anything about the environment. a Q&D hack may be OK on someone's personal system, but not for code intended for distribution to others.

These mistakes and newbie errors are just what I've noticed from a casual glance at the script. There are undoubtedly many more.

bash is always in /bin on a linux system, also on OS X.

Many Linux distros store it in /usr/bin instead, along with everything else that usually goes in /bin.

Steam doesn't do that, and likely never will. Steam isn't a real package manager.

You missed the point. It isn't actually that hard for a program to keep track of all the files it will output in a given directory. Even programs on windows are able to do that sort of thing. No one said steam should become a package manager. It should just be able to clean up after itself and while it is updating.

@aaronfranke really? name these "many distros". in fact, name one. bash has been in /bin on linux forever because that's where system-native shells belong. third-party shells tend to go in /usr/local/bin. or in some bizarre location like /usr/opt/local/where/the/fuck/is/it on solaris.

@hasufell no, i didn't miss your point. you missed mine, which is that wasting time complaining about the fact that steam isn't a real package manager and doesn't behave like one is completely pointless and useless. Deal with things as they are, not as they should be and not as you wish they were. Steam is what it is, and there's a limit to what and how much can be fixed or improved.

which is that wasting time complaining about the fact that steam isn't a real package manager and doesn't behave like one is completely pointless and useless.

No, that's not what I said. Package managers are orthogonal to the point I made, which suggests you actually didn't understand the point.

Deal with things as they are, not as they should be and not as you wish they were. Steam is what it is, and there's a limit to what and how much can be fixed or improved.

That is just wild guessing. Why would it not be possible to fix the behavior as explained? I don't see any technical limit there. Please explain what "limit" that would be.

you may think you were making some significant point, but really you were just wishing that steam was a real package manager. It isn't, and no amount of bitching about it is ever going to get Valve to devote the time and resources to make it one. There's little or no benefit to them in doing so - steam mostly functions well enough at what it is, a games library manager.

as for your "wild guessing" comment and request for an explanation of the limit - we're talking here about the steam.sh shell script, which is a wrapper around the steam application, doing environment setup and other things (like helpfully deleting all user files on certain error conditions). Rewriting the steam app so that it acts like a package manager should is way beyond the scope of fixing the obvious errors in a shell script. I would have thought that was obvious.

In case you hadn't noticed, Valve don't even acknowledge the fact that their crappy steam.sh script is still broken and puts user files at risk - there's some small hope that they might eventually do that and adopt some of the ideas and suggestions in this thread (there's some evidence they've already done that for some things), but there's no way they'll ever re-write the steam app to incorporate the basic features of a package manager.

hasufell commented Oct 15, 2017

you may think you were making some significant point, but really you were just wishing that steam was a real package manager

Again, no.

as for your "wild guessing" comment and request for an explanation of the limit - we're talking here about the steam.sh shell script

No, we are talking about steam as a whole.

Rewriting the steam app so that it acts like a package manager should is way beyond the scope of fixing the obvious errors in a shell script. I would have thought that was obvious.

Again, no. This is not about package managers. You seem to have no understanding of how the proposed technology works.

This is not about fixing half-assed shell scripts, which are already by concept wrong. This is about correctness, which is crucial when you deal with user files. Recursive deletion is never correct from an automated cleanup POV. Recursive deletion is something a user may trigger, based on his needs.

but there's no way they'll ever re-write the steam app

First, there is no rewriting of the "steam app" involved. Second, that's guessing again.

@craig-sanders

https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/

Solaris started it, Fedora was one of the first Linux distros to do it.

@aaronfranke really? name these "many distros". in fact, name one. bash has been in /bin on linux forever because that's where system-native shells belong. third-party shells tend to go in /usr/local/bin. or in some bizarre location like /usr/opt/local/where/the/fuck/is/it on solaris.

@craig-sanders: Sorry to barge in, but maybe you have to update your knowledge on this one:

And probably others already, as this merge of /bin to /usr/bin was advocated by systemd, so probably many other distros that switched to systemd will eventually follow.

dsohler commented Oct 15, 2017

No big deal since the merge to /usr/bin is done slowly and places symlinks for maintaining backwards compatibility.

2017-10-15-194019_499x65_scrot

So using /bin/bash is safe on “traditional” systems as well as on nowadays systems.

Guys, we are bike shedding solving a problem which has already had a suitable solution presented and alternatives. Discussing it ad nauseam isnt going to make Valve come out and fix it if they have no interest, we have suitably voiced opinion here. Lets post a link to some other forum (Reddit, Google groups, or elsewhere) and take the sidebar discussion there.

No big deal since the merge to /usr/bin is done slowly and places symlinks for maintaining backwards compatibility.
So using /bin/bash is safe on “traditional” systems as well as on nowadays systems.

This may be true so far, but every backwards compatibility will eventually be going away.
And this:

#!/usr/bin/env bash. bash is always in /bin on a linux system, also on OS X. and using env to find a script interpreter is brain-damaged.

is certainly outdated advice for any software maintained currently or in the future. Distributions will have to do enough patching for legacy software once such backwards compatibility is faded out.

@ju2wheels But a Half Life 3 talk didn't even have a chance to start!

Has this problem been fixed? I really want to play the metro series, but this scares the crap out of me.

dsohler commented Nov 28, 2017

@user15177 Set up a chroot for Steam and run it from there so it can do no harm to your actual system.

@craig-sanders Since you posted some cleaned-up code from the script and some good Bash scripting advice, a note: Always use the [[ ]] test syntax in Bash-specific scripts. It's safer and cleaner in all cases.

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