
Steam for Linuxのバグ、予期せぬ「rm -rf "/"*」 43
ストーリー by headless
全滅 部門より
全滅 部門より
Steam for LinuxでSteamのデータ保存用ディレクトリを別の場所に移動した結果、ユーザーのファイルがすべて消去されてしまったというバグリポートが出されている(Neowinの記事、
本家/.)。
このユーザーは「~/.local/share/steam」フォルダーを別のドライブに移動し、元の場所にシンボリックリンクを張った。その結果Steamが起動しなくなり、新しい場所を指定しても解決せずにSteamはクラッシュ。再起動すると自動的に再インストールが行われ問題は解決したように見えたが、ルートディレクトリ以下すべての場所(マウントされている外付けドライブも含む)から、このユーザーのファイルが再帰的に消去されてしまっていたという。
同様のトラブルに遭遇した他のユーザーが、Steamのスクリプトで見つかった問題点を指摘している。スクリプトはある時点でデータの保存場所を「$STEAMROOT」にセットし、後で「rm -rf "$STEAMROOT/"*」を実行する。しかし、データの保存場所が移動されると「$STEAMROOT」が空の文字列を返すため、「rm -rf "/"*」が実行され、予期しない削除が実行されるというものだ。
このユーザーは「~/.local/share/steam」フォルダーを別のドライブに移動し、元の場所にシンボリックリンクを張った。その結果Steamが起動しなくなり、新しい場所を指定しても解決せずにSteamはクラッシュ。再起動すると自動的に再インストールが行われ問題は解決したように見えたが、ルートディレクトリ以下すべての場所(マウントされている外付けドライブも含む)から、このユーザーのファイルが再帰的に消去されてしまっていたという。
同様のトラブルに遭遇した他のユーザーが、Steamのスクリプトで見つかった問題点を指摘している。スクリプトはある時点でデータの保存場所を「$STEAMROOT」にセットし、後で「rm -rf "$STEAMROOT/"*」を実行する。しかし、データの保存場所が移動されると「$STEAMROOT」が空の文字列を返すため、「rm -rf "/"*」が実行され、予期しない削除が実行されるというものだ。
相変わらず欧米の連中は(ry (スコア:5, すばらしい洞察)
そこはわれわれが14年前に [din.or.jp]通過した場所だ。
Re: (スコア:0)
PSO2「せやな」
ところがどっこい日本の連中も(ry (スコア:0)
嫌な事件だったね・・・
http://pso2.jp/players/news/?id=2136&page=35 [pso2.jp]
※自分は、いつもスケジューラー使ってアップデートさせているのだけど、たまたまスケジュールを止めていたタイミングで難を逃れたというのがアレ。
コードレビューで気付くだろ! (スコア:3)
と、とある ./j ユーザが申しております。
Re:コードレビューで気付くだろ! (スコア:2)
「環境変数のチェック処理がない!チェック処理が無いのはバグだ。直せ!」
外部モジュールからの入力は信頼するなというポリシーをチームで共有していたら、
こんな指摘をできていたかもしれませんね。
環境変数が期待する入力かどうかをチェックする処理があるかを指摘するのは
たやすいですが、将来的に誰かが期待する入力でない処理を混入させてしまう
ことがないかまで考慮したうえで、問題ないと判断するのは困難でしょう。
入力の検証コードを書くのは面倒ですが、入力がプログラムの寿命を迎えるまで
信頼できる内容であると保証させるほうがもっと面倒なんです。
Re: (スコア:0)
外部モジュールからの入力は信頼するな
チェック処理を「余計なことする奴」と散々な評価頂いた基幹系を思い出すなぁ。
それまでのWindows系ではやるのが当たり前でしたので、文化の違いなんだろな。。
Re: (スコア:0)
Windows系とか関係なく、変な話ではない。
基幹系というより、ネットワーク的に閉じているとか、ユーザに解放している範囲が違うとかでしょう。
文化で片付けずに何故それをチェックするべきか、という判断基準がないか考えてみましょう。
Re: (スコア:0)
いやいや、
「(既にチェックしているから)余計な物」
と断定できるならば、既に何をどこでチェックしているかのチェックリストがあって、
メンバー全員で共有されてるはず。
されてないとすれば、そのチェック機能は既に機能してないのだから、
各個にチェックしないといけない。
「という判断基準がないか考えてみましょう。(きり)」
なんて寝言ほざいてる時点で、もはや末期。
Re:コードレビューで気付くだろ! (スコア:2)
dot-slash に気付いた者だけが石を投げよ。
Re: (スコア:0)
そこは最初に気がついたw
rm -rf file. * (スコア:3)
と、なぜか間違ってスペースを入れたあとに,*を書いたこと。みんなあるよね。
Re:rm -rf file. * (スコア:2, 参考になる)
rm -rf temp /* テンポラリを削除 */
#危険シェル芸
Re: (スコア:0)
Re: (スコア:0)
実際にありました。ホームディレクトリがなくなりました。(遠い目w
Re: (スコア:0)
そんな経緯で共用のvax780を落とした覚えが。
#ご家族でしょうか?その度はどうもすいませんでした。
危なかった (スコア:1)
>「~/.local/share/steam」フォルダーを別のドライブに移動し、元の場所にシンボリックリンクを張った
俺も同じことやってるけど問題は起きてない。Steamクライアントの再インストールしたらヤバかったのか。
Re:危なかった (スコア:1)
シンボリックリンクって意外に癖があって, プログラムの組み方次第では期待したとおりに動かない(例えばディレクトリだけを参照してエントリの種別を判定するとか, シンボリックリンクの親ディレクトリの参照だとか)なんてことがままあるので, 安易には使わない方が良いです.
ディレクトリツリーの一部を, 容量の問題や書き込み権の関係で, 他のファイルシステムに移したい場合, 今ならnullfs [freebsd.org]やbindfs [bindfs.org]を使うほうが問題に引っかかる可能性が少ないと思います.
対策 (スコア:1)
> スクリプトはある時点でデータの保存場所を「$STEAMROOT」にセットし、後で「rm -rf "$STEAMROOT/"*」を実行する。しかし、データの保存場所が移動されると「$STEAMROOT」が空の文字列を返すため、「rm -rf "/"*」が実行され、予期しない削除が実行されるというものだ。
こう聞くと自分もうっかり書いてしまいそうなミスに見えますが、
同じようなケースで事故を回避するベストプラクティスはどんな感じですかね。
Re:対策 (スコア:2)
Shell Scriptを使わない
本当に安易に使わないほうが良いのかもしれません
Re:対策 (スコア:2, 参考になる)
私が20数年前に先輩から聞いていまでも注意していることとして以下があります。
・シェルスクリプト、Cなどいかなる状況でもパス文字列の先頭を/にしないこと(絶対パスではなく相対パスにするべし)
これは最悪ルートからファイルを削除することになるため。
・あるディレクトリ以下のファイル、ディレクトリをすべて削除したい場合、対象ディレクトリにcdで移動してからファイルを削除、上位ディレクトリに移動してからrmdirでディレクトリを削除すること
・ファイル数が不定の場合、パイプするときにはかならずxargsを用いるべし
これだけでは防げないかもしれませんがいまのところ重要ファイルを削除した経験はないです。
Re:対策 (スコア:1)
test -z "$STEAMROOT" やら test -n "$STEAMROOT" やらでチェックするんじゃないっすかね.
Re: (スコア:0)
STEAMROOT="/tmp "
Re: (スコア:0)
STEAMROOT="/"
Re: (スコア:0)
まず、消す直前に意図したものがあるのかチェックしてないのは致命的。
ディレクトリがあるのかもそうだけど、自分が作ったものならどんなファイルがそこにあるか知ってるはずだろ。ものぐさせずに*じゃなく全部の名前を書くべき。
そして、STEAMROOTを保存するときに、/を付けた状態で保存してないのもミスの原因。必ず/を付けてコマンド打つなら保存するときにつけるべき。
でも、Sym-linkしてあってもシェルベースではファイルがないということはないのでは。
このSTEAMROOTとかをCのバイナリで作ったなら、その中でlstatしてないのかもね。これもまぁよくあるバグ。
Re: (スコア:0)
bashならスクリプトの先頭に set -u しておく。
というか、自分なら未定義の変数を空文字列として展開する言語を使用しない。
Re:対策 (スコア:2)
今回の場合、変数は未定義ではなく空文字列に定義されていたので、 set -u じゃ防げないと思うよ。ただし、僕は議論をちゃんと追っておらず、どうして空文字列に定義されていたのかは知らないので、理由によっては空文字列に定義する部分で set -u されていれば防げた可能性はあるけど (でもぱっと見ではそうは見えない。どちらかというと set -e の方が関係ありそう)。
rsyncでやった (スコア:1)
昔rsyncで同じことしましたね。
デーモンはメモリー内で生きてましたが、ファイルが何もないという状態・・
Dropboxで解決 (スコア:1)
あと、rm を "mv {} ~/gomi" にエイリアスに、という古典的な方法とか。
デーモンをroot権限で実行するなと何度言ったらわかるのか (スコア:0)
このバグとれてもセキュリティホールに怯える日々はかわらねぇだろうが。
Re: (スコア:0)
自分がオーナーのファイルがすべて消えたって読んだけど。
Re: (スコア:0)
ああ、ルート以下の*自分の*ファイルか。見落とした。
Re: (スコア:0)
でーもんなこと言ったって
馬鹿は死ななきゃ治らんともいうし
# 死んでも治らんから繰り返されてまうんかな
仕様です (スコア:0)
Steamだけに
蒸気が如く消えました
# 常軌を逸したジョークであってほしかった
Re: (スコア:0)
Steamだけに
「蒸気にしてやったぜ~」
#と、上機嫌(^o^)/
Steamのバグというより (スコア:0)
Ubuntuのバグというべきでしょうね。rmコマンドにセーフティかけてないとは。
Re: (スコア:0)
明示的に -f オプションをつけてるのにそれでもバグといいたいなら rm のバグというべきでしょ。
他ならいいけどUbuntuではダメとかいちいち理屈が成り立ってない。
Re: (スコア:0)
初心者にありがちなんだけど、具体的な小細工を思いつかないのに「適切に」「正しく」っていうのは逃げだから。
rm に rm -rf / を防止する機能は既にある。何でもかんでも動かなくしたところで意味は無い。
rm -rf 最強伝説 (スコア:0)
rmコマンドって初心者にコマンドライン操作の危険性を示す例としてよく上げられるけど、
結局スクリプトやプログラム組んでたら注意しなければならないんだし
コンピュータってこういうものだと理解させる良い教材だと思うけどな。
いっそのこと (スコア:0)
-f付けても対象が/なら強制的に確認メッセージ出すようにすればいいんじゃないの?
/消すのに確認メッセージ出すんじゃねーよ!なんて人居ないでしょ?
Re:いっそのこと (スコア:1)
GNU coreutilsのrmはそうなってるが、今回の件は rm -rf /bin /boot /etc ... /var に展開されてるってことだ
Re: (スコア:0)
rmを使うのは人だけでは無いので。
確認を求められることは無いだろうという前提のプログラムは困ったことになるかもしれません。
Re: (スコア:0)
/ 指定でrm使う理由ってのが思いつかない。
どちらかというと「機能最小に抑えるために、そんな個別事例に安全弁なんてつけたくない」
という方がまだ理解できる。
Re: (スコア:0)
無理やり考えれば、最小権限だけど広範囲にファイルをばらまくようなプログラムが吐き出したものを掃除するときとか。
# rmそのものに安全弁はいらんだろというのがUNIX文化