Article 3990 of fj.unix: Path: news2.sra.co.jp!katsu From: katsu@sra.CO.JP (WATANABE Katsuhiro) Newsgroups: fj.unix Subject: Re: =?ISO-2022-JP?B?GyRCO0s+ZTpHMC0kTjt2QlYbKEIoGyRCPEJPQxsoQik=?= Supersedes: Date: 07 Oct 1998 02:09:10 GMT Organization: Software Research Associates, Inc., Japan Lines: 294 Message-ID: <6veord$l6h$1@sranhh.sra.co.jp> References: <6570t1$7sk$1@news2.osk.3web.ne.jp> <659aj9$j6h$1@ITG-005.intacc.ne.jp> NNTP-Posting-Host: sras49.sra.co.jp Mime-Version: 1.0 (generated by tm-edit 7.47) Content-Type: text/plain; charset=ISO-2022-JP In-reply-to: Tadasuke Yamaguchi's message of 22 Nov 1997 16:22:57 GMT Originator: katsu@sras49 Xref: news2.sra.co.jp fj.unix:3990 あまりのフォローの遅さが議論の妨げになっていたらごめんなさい。 投稿時に化けた を supersedes します。 > From: tadasuke@osk3.3web.ne.jp (Tadasuke Yamaguchi) > Message-ID: <6570t1$7sk$1@news2.osk.3web.ne.jp> > Date: 22 Nov 1997 16:22:57 GMT > ところで root で rm -r / を実行した後はどうなるのでしょう? 普通に rm -r a_directory したときと特に違いはありません。 -f を指定しない場合、rm(1) -r は、 (a) ファイルの tree を depth first traversal して (b),(c) を試す。 (b) 書き込みができないファイルについてはユーザーに確認を求める。 ただし、書き込みができないディレクトリについては確認を求めない。 標準入力が端末でない場合は確認も求めない。しかる後、 (c) ファイルに対しては unlink(2)、ディレクトリに関しては rmdir(2) を試す。 といったことになるはずです。"rm -rf /" の考察ならば、(b) を 除外して考えればよいでしょう。 (a) depth first traversal 敢えてやろうと思えばディレクトリへの link(2) が可能な OS の場合、 ディレクトリ構造が tree ではなくなっていることがあり得ます。 病的な場合には cycle を含むこともありえます。cycle があると、 Directed Acyclic Graph(や tree)を仮定していて深さ優先走査を 素朴に試すような algorithm は停止しません(注)。rm(1) はどうかと いうと、ENAMETOOLONG が何らかの形で関係するエラーに途中で遭遇し、 無限ループに陥ることはないでしょう。GNU の fileutils の rm では cycle を検出し、発見したら警告を出して停止するようです。 注: 実際は、いずれ stack を食い潰して異常「終了」するでしょう。 (b) 書き込みの権限の確認 ファイルに書き込み許可があるかどうかは、stat(2) 系ではなく access(2) で検査するようになっている rm の実装がほとんどで、 その例外は GNU の古い fileutils の rm にみられます(see. http://www.sra.co.jp/people/katsu/article/#rm )。この記事で考えて いるのは uid=root の場合なので、ファイルの mode にかかわらず多くの 場合に書き込めて access() が成功します。書き込めないのは、EROFS, ETXTBSY の他に、病的な場合があります。SunOS に限っては、ETXTBSY で access() が失敗することはなく、その結果、実行中のファイルに対して rm: override protection 755 for NOW-RUNNING-COMMAND ? のように確認を求めることはありません。 (c) unlink(2) や rmdir(2) の呼びだし uid=root なので、unlink(2)、rmdir(2) はほとんどの場合成功しますが、 以下の理由で失敗することがあります。 (c-1) EBUSY (mount point)で消えないもの がある。POSIX 標準を見てみると、"/" や何らかのプロセスの カレントディレクトリを rmdir した場合、成功しても EBUSY で 失敗してもどちらでもよいことになっている。しかし、"/" を rmdir できる実装や、プロセスのカレントディレクトリを rmdir できない実装は、私は知らない。知ってる方は教えてください。 (c-2) EROFS (read-only FS)で消えないものがある。 (c-3) 空でないディレクトリが、ENOTEMPTY で消えない。カーネルが そのディレクトリは空でないと判断した理由は、(c-X) 項の いずれかであろう。ディレクトリに対して敢えてハードリンクを していた場合(それが可能な OS において)も、rmdir が ENOTEMPTY で失敗するような実装(例えば 4.3BSD)がある。 (c-4) 実行中のコマンドに対応するファイルが ETXTBSY で消えない。 (System V 系に限る) (c-5) ENAMETOOLONG 他、特異な理由で消えないものがある。 言い換えると、 ・mount point ・read-only FS のファイル ・空でないディレクトリ(やハードリンクされたディレクトリ) ・System V なら、実行中のコマンドのファイル(下記の注参照) と、/ からそこへ至る中間のディレクトリも消えないことになります。 注:SVR4 の programmer's reference manual の unlink(2) には、 SVR4> ETXTBSY The entry to be unlinked is the last link SVR4> to a pure procecdure (shared text) file SVR4> that is being executed. とあります。しかし実際には、最後のリンクでなくとも常に失敗する ようです。マニュアルに上記相当の記述があり(SVR4 でなくとも)、 実際にそのように振舞うOSをご存知の方はお教え下さい。 なお、実行中のファイルを unlink(2) できたからといって、実行中の プロセスには何も影響しません。inode の link 数は unlink で減少 しますが、ファイルの実体(on-disk inode と付随するブロック等)が 解放されるのは、in-core inode の参照数が 0 になった時だからです。 以上の基本を踏まえて、個々の記事について議論をしてみます。 > From: Masahiko Thuluoka > Message-ID: <659aj9$j6h$1@ITG-005.intacc.ne.jp> > Date: 23 Nov 1997 13:20:41 GMT > > >> ところで root で rm -r / を実行した後はどうなるのでしょう? > 自分のログインシェルのみが残って、/bin/rmも消えました。 > クラッシュした後「えぇーぃOS再インストール!」と決意したので、やってみた結果 > ですが。再インストール後に見ていて、日付が旧いので気が付きました。 > 八年を越えようかという処の自分のUNIX歴でも、唯一度この時のみです。ですから > サンプルとしては不確かですが。あの時は何を使っていたんだっけか、、。 もう少し具体的な状況を思い出していただかないと、ご自身でもお考えの 通り、不確かです。特に以下の理由で、私は納得できません。 [1] ログインシェル「のみ」が残る理由が説明できない。ETXTBSY が 何らかの形で影響する環境だったと仮定しても、それなら /bin/rm や /etc/init 他も残るはずである。 [2] FreeBSD, Linux での実験結果(後述)、その他のOSでの状況証拠と 矛盾する。 [3] 再インストール後の、しかも time stamp による比較という間接的な 観察である。 > From: tezuka@trc.rwcp.or.jp (Hiroshi Tezuka) > Message-ID: > Date: 25 Nov 1997 05:16:13 GMT > ずっと以前に、一時的に借りていた VAX11/750 を返す前日の晩に root で > "rm -fr /" をやってみたことがあります。 > どうなったかというと、全部のディレクトリ、ファイルが消えることを期待してい > たのですが、4.1BSD の rm はディレクトリを消す時には /bin/rmdir を呼んでい > たので、/bin/rmdir がなくなった時点で止まってしまいました。 この振舞いがいつまでだったかというと、 4.1BSD までと、SVR2 まで だと思います。4.2BSD で rmdir(2) システムコールが追加され、 System V も R3 ぐらいでそれに追随しました。 > From: kazu@kobe.hp.com (Kazuhisa Yokota) > Message-ID: > Date: 26 Nov 1997 04:26:18 GMT > Hiroshi Tezuka writes: > > > どうなったかというと、全部のディレクトリ、ファイルが消えることを期待してい > > たのですが、4.1BSD の rm はディレクトリを消す時には /bin/rmdir を呼んでい > > たので、/bin/rmdir がなくなった時点で止まってしまいました。 > > 4.1BSDではディレクトリを消去するのにrootの権限が必要だったのでしょうか。 > (Sys V系はそうだった) そうです。4.1BSD までは、SVR2 までと同様、/bin/rmdir が root に setuid され、その内部で unlink(2) を呼んでいました。相補的に、 /bin/mkdir も root に setuid されていて、mknod(2) を呼んでました (see. [BSD43ANS] 2.8, [SYSCALL] p.84)。 > From: kazu@kobe.hp.com (Kazuhisa Yokota) > Message-ID: > Date: 28 Nov 1997 08:14:38 GMT > Hiroshi Tezuka writes: > > > In article kazu@kobe.hp.com (Kazuhisa Yokota) writes: > >> # どうやって全部消えたことを確認するつもりだったのでしょう :-) > > > 自分の csh は動いているので、cd と echo を使えば、面倒ですが残っているファ > > イル名ぐらいはわかります。 > > BSD(というかSunOS4.Xでの経験ですが)では、実行中のプログラムファイルを > 削除するとテキストセグメントでベージフォルトが起こったときに読むべきファ > イルが無くなっているので、プロセスがクラッシュした記憶があるので何も出 > 来なくなってしまうと思ったわけです。 > > Sys V(というかHP-UXでの経験です)では、実行中のプログラムファイルは > Text file busy というエラーになって削除できません。 動作中のコマンドのファイルを unlink(2) することが可能な UNIX (BSD, SunOS 4.X, SunOS 5.X)では、動作中に unlink したからといって page が読めなく(demand paging できなく)なったり、「クラッシュ」 することはありません。何故なら、unlink(2) されて directory 上からは エントリが消えるものの、in-core の inode (vnode) の参照数が 0 ではなく、そのファイルの on-disk inode やブロックや cache は、 プロセスが終了するまでは解放されないままだからです。 (see. [UI] 8.7.4 "Vnode Reference Count") SunOS 4.1.X, 5.X で「プロセスがクラッシュ」するのは、ファイルを 「削除」した時ではなく、実行中のコマンドのファイルに書き込んだ 場合でしょう。BSD(や、System V を含む多くのOS)では、 こういう局面はあり得ません。実行中の pure executable ファイルを 書き込み用に open(2) したり、書き込み用に open(2) されている ファイルを execve(2) すると、ETXTBSY で失敗します。 (SunOS 4.0.3 がこの側面で BSD 的か SunOS 4.1.X 的か、未確認 です。SunOS 3.X も不明ですが、こちらは BSD にかなり近いので、 上書き不可の性質があるものと強く予想してます。) なお、SunOS 4.X のシステムコールの仕様は、BSD(SunOS 4.X 当時は、 主として 4.3BSD)のシステムコールの仕様と違うことがあるので、 前者の経験から後者を(または逆を)推測して議論するのは危険です。 > From: tezuka@trc.rwcp.or.jp (Hiroshi Tezuka) > Message-ID: > Date: 29 Nov 1997 01:42:56 GMT > >Sys V(というかHP-UXでの経験です)では、実行中のプログラムファイルは > >Text file busy というエラーになって削除できません。 > > 4.1BSD がどうなっていたのかは今となっては不明ですが、少なくとも 4.2BSD 以 > 降では実行中のファイルは実際には削除はされないようになっていたと思います。 > たしかに SunOS4 では削除できるのですが、なぜそうしているのかは謎です。 上の「削除されない」が、 [unlink 不可]unlink が失敗してディレクトリエントリは消えない。 という意味なら、(4.2BSD に関する部分は)誤りでしょう。ちなみに [deactivate 不可]ファイルの実体(ブロック等)は解放されない。 という意味にとると、BSD の方は正しいのですが、SunOS4 では unlink でファイル実体が直ちに消えることとなってしまい、やはり 変です。 4.X BSD 系、SunOS [345].X いずれも(大まかに言うと System V 系 以外では)、実行中のファイルを「削除」(unlink) できるはずです。 UNIX V6 まで遡ってみたところでも、削除できる (see. [LIONS]) ようでした。BSD ではできなくて SunOS でできる操作とは、 上書きでしょう。これについては既に述べた通りです。 ただ、rm(1) を使う場合に -f option をつけていないと、この記事の 最初の (b) 項でも述べた通り、 rm: override protection 755 for NOW-RUNNING-COMMAND ? などと事前に端末に確認を求めてくるので、この時点で削除を回避 できるといったことはありえるでしょう。 > From: nakano@math.ryukoku.ac.jp (Hiroshi NAKANO) > Message-ID: > Date: 01 Dec 1997 00:36:33 GMT > > In article > tezuka@trc.rwcp.or.jp (Hiroshi Tezuka) writes: > |4.1BSD がどうなっていたのかは今となっては不明ですが、少なくとも 4.2BSD 以 > |降では実行中のファイルは実際には削除はされないようになっていたと思います。 > > Text file busy (ETXTBSY) に関しては、「削除できない」ではなくて、「上 > 書きできない(書き込みモードで open できない)」ですよね。 > > |たしかに SunOS4 では削除できるのですが、なぜそうしているのかは謎です。 > > 実行中のバイナリが NFS などの上にあれば、結局どうしようも無いから ... > という理由を聞いたような気がします。 これに加えて、私は以下のような想像をしています。 かつては(病的なプログラム以外は)、テキスト空間は単一のファイル だけから充填されていました。しかし最近は、mmap(2) のおかげで、 実行するコードはいろいろなものに由来することになりました。典型的 には dynamic library (shared object) の存在です。テキスト空間を 構成するファイルへの書き込みモード open(2) や、書き込みモードで open(2) されたファイルへの PROT_EXEC での mmap(2) を全て ETXTBSY で失敗させるのは、(効率を落とさず実装するのは)面倒だった.... という面があったのではないかという想像です。 NFS(をはじめとして多様性が増加する一方のファイルシステム群)や mmap(2) に関する穴がある限り、execve(2) や open(2) でだけ ETXTBSY を検出しても仕方がないなあという気持ちもします。 [Linux をお使いの方へ] mmap(2) と ETXTBSY の関係について、言いたいことがあるのでは? なお、実際に FreeBSD や Linux で "rm -rf /" を実験した結果と考察が、 What happend when the root does "rm -rf" ? http://www.sra.co.jp/people/katsu/doc/rmrf/ にあります。内容を要約すると、 ・mount point。 ・CD-ROM や /proc FS など、read only のファイルシステム。 ・削除されなかったファイルを含むディレクトリ、すなわち "/"。 を除き、全てのファイルとディレクトリが消えました。それでも、 カーネルも起動済みのプロセス(デーモン類)も動作し続けました。 参考文献 [BSD43ANS] "UNIX 4.3BSD の設計と実装 アンサーブック"; S.J レフラー, M.K.マッキュージック著; 相田仁, 計宇生, 小池汎平訳; トッパン; ISBN 4-8101-8039-5; [LIONS] "Lions' Commentary on UNIX 6th Edition with Source Code"; John Lions 著; 岩本信一訳; アスキー; ISBN 4-7561-1844-5; [SYSCALL] "UNIXシステムコール・プログラミング"; Marc J. Rochkind 著; 福崎俊博訳; アスキー; ISBN 4-87148-260-X; [UI] "UNIX internals: the new frontiers"; Uresh Vahalia; Prentice Hall; 1996; ISBN 0-13-101908-2; -- 渡邊克宏@SRA