ファイルはそのiノードで取得できますか?


27

次のコマンドを指定された順序で実行しました。

$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b

このテストから、コマンドはrm実際にファイルではなくファイル名(aこのテストでは)のみを削除すると結論付けましたb

私の質問は、ファイルが1つのファイル名のみにハードリンクrmされている場合、そのファイルに対して実行されると、実際のファイル(つまりiノード)は完全に削除されますか?そうでない場合、ファイルiノードはファイル名なしで、iノードのみを介して取得できますか?


OS固有のサウンドです。
イグナシオバスケス-アブラムス

@Ignacio Vazquez-Abrams。バージョンに依存するということですか?
user43312

いいえ、オペレーティングシステムに依存します。それぞれに(もしあれ)VFSを利用する異なる方法があります。
イグナシオバスケス-エイブラムス

@Ignacio Vazquez-Abrams RHLまたはRHELについて何かご存知ですか?
user43312

1
@BruceEdiger Os X sort-ofはそれを行います。基本的に、ファイルシステム番号とノード番号から構築される「ファイル参照URL」を使用して、ファイルシステムオブジェクトにアクセスできます。ただし、それらを自分で作成することは公式にはサポートされていません。代わりに、ファイルの「ファイル参照URL」を取得し、同じランタイムセッションでの以降のアクセスにパス名の代わりにそれを使用して、アプリケーションが同じボリューム上の他の場所に移動されるファイルに気付かないようにします。
アナログファイル

回答:


29

iノードを介してファイルを開こうとすると、ディレクトリトラバーサルがバイパスされます。ディレクトリトラバーサルは、ファイルとそれにつながるディレクトリの権限を決定するために必要です。ディレクトリトラバーサルがないと、カーネルには呼び出しプロセスがファイルへのアクセスを許可されているかどうかを判断する方法がありません。

ファイル記述子からファイルへのリンクを作成できるようにLinuxカーネルに提案されたパッチがありました。これを安全に実装することは非常に難しいので拒否されました

Linux(およびおそらく同じ理由で他のUNIXバリアントでも)では、削除されたファイルへのリンクを作成できないため、ファイルに名前がなくなった場合、ファイルを再度追加することはできません。¹削除済みファイルを開くことができます。の下にある魔法のリンクを開いてファイルを開きます/proc/$pid/fd/

ファイルにリンクがなく、開いていない場合、そのファイルはもはや存在せず、そのデータによって以前使用されていたスペースはいつでも再利用できます。

¹ たとえばdebugfs、ext2 / ext3 / ext4のように、ファイルシステムに依存する方法でファイルシステム内のバイトを直接調整することで、これを実行できる場合があります。これには、ファイルシステムがマウントされているデバイスへのアクセスが必要です(つまり、通常、rootのみが試行できます)。ただし、debugfsはiノードでファイルにアクセスできますが、ファイルが削除されても役に立ちません。アプリケーションがファイルを閉じると、ファイルは本当に削除され、マウントされたファイルシステムでdebugfsを実行すると、災害。


11

Linuxではdebugfs、インタラクティブなext2 / ext3 / ext4ファイルシステムデバッガーはln、iノード番号を取得filespecし、対応するファイルへの新しいハードリンクを作成できるコマンドを提供します。ただし実際には、リンクされていないファイルはプロセスによって開かれたままである必要があり、開いているファイル記述子をに維持します/proc/[pid]/fd/[n]。削除されたファイルでこれを実行しようとすると、ほとんどの場合、ファイルシステムが破損します。

これは、ext3(および拡張ext4)がクラッシュ後にリンク解除を安全に再開できるようにするために、実際にinode内のブロックポインターをゼロで消去しますが、 ext2はこれらのブロックをブロックビットマップで未使用としてマークし、 iノードを「削除済み」としてブロックポインターをそのままにします。それでも、ハードリンクを作成するためにファイルシステムを読み書き可能にマウントする必要があるため、削除されたファイル用に予約されたブロックはすでに再割り当てされている可能性があります。

カーネルバージョン2.6.39より前は、GNU coreutils v8.0で導入されたオプションを使用して、リンクされていないファイルと新しいハードリンクの両方がtmpfsファイルシステムにある場合、開いているファイル記述子を介してリンクされていないファイルを回復できました。Gillesが指摘したように、ファイル記述子から直接ハードリンクを作成できるようにするためのセキュリティ上の考慮事項のため、この機能は無効になっています。ln -L|--logical/proc/[pid]/fd/[n]


ln -L/ procから削除されたファイルを回復するために使用しようとしましたが、「No such file or directory」というエラーが表示されたため、実際にこれをサポートしているとは思いません。coreutils 8.21があります。
wingedsubmariner

1
ln -Lあなたが言うことをしません。それは伝えlnソースがシンボリックリンクであれば、それは難しいターゲットをリンクする必要があること。のシンボリックリンク/proc/$pid/fdは特別なものであり、(deleted)リンクのハードリンクは機能しません。
ジル 'SO-悪である停止'

またdebugfs、ファイルが削除された場合は役に立ちません。マウントされたファイルシステムでファイルを読み書きモードで実行するリスクがない限り、ファイルシステム全体が完全に破損する可能性があります。
ジル「SO-停止されて悪」

に関する回答を更新しましたln -L。以前/proc/[pid]/fd/[n]は、特定の特別な状況でハードリンクを使用してハードリンクを作成することが可能でしたが、これは修正されています。
トーマスナイマン

1
debugfsさんはln本当に低レベルであり、唯一の名前を作成し、数を更新しないし、それはですので、未使用として、ブロックマークを解除、非常に危険。好むdebugfsundelデことのすべてを。警告:debugfsされて実行されないあなたが灰にあなたのFSを燃焼でチャンスを取りたい場合を除きには、ファイルシステムをマウント。
-Lloeki

9

'ln'および 'rm'コマンドは、1970年代初頭からすべてのUNIXファイルシステムでこのように機能していました。Mac OSX、BSD、およびLinuxはすべて、この元の設計を継承しています。

UNIXファイル自体には名前はなく、iノード番号またはinum のみがあります。ただし、問題のイナムに名前を関連付ける特別な「ディレクトリ」ファイルのエントリを介してのみアクセスできます。inumを直接指定することはできません。

ディレクトリ自体はファイルなので、「パス名」と呼ばれるスラッシュ(/)で区切られた一連のディレクトリ名を使用し、(別の)ディレクトリなどからもアクセスする必要があります。パスがプロセスの「現在の作業ディレクトリ」で始まりますが、名前が「/」で始まっていない場合は、ファイルシステムのルートディレクトリで始まります。たとえば、パス名に「/」文字が含まれていない場合、現在のディレクトリのエントリであると想定されます。

非ディレクトリファイルには、「ハードリンク」として知られているパス名、任意の数を持つことができ、それがされるまで存在し続けるだろう、すべてのパス名のが削除されている、最後のプロセスがファイルを閉じました。その後、ファイルは実際に削除され、そのスペースは再利用可能としてマークされます。つまり、単一リンクファイルを作成(または開く)してからunlink()すると、ファイルシステムの名前空間に表示されなくなりますが、ファイルは閉じるまで存在し続けます。これは、他のプログラムによって読み取られない一時的なスクラッチファイルに役立ちます。

ディレクトリにはinode番号がありますが、ほとんどのファイルシステムはディレクトリへのハードリンクを許可していません。他の1つのディレクトリにのみ表示できます。(1つの珍しい例外はMac OSX HFS +ファイルシステムです。これにより、Time Machineバックアップが機能します。)ディレクトリ(またはその他のファイル)への「ソフトリンク」を作成できます。ソフトリンクは、inumではなく別のパス名を含むことを除いて、ディレクトリエントリに似ています。

すべてのUNIXファイルには、所有者、グループ、およびアクセス許可があります。ファイルを開くことは必要ですが、十分ではありません。また、それを参照するために使用するパス名のすべてのディレクトリに対して、少なくとも実行権限が必要です。そのため、UNIXファイルをそのiノード番号で開く標準的な方法はありません。これは、広く使用されている重要なセキュリティメカニズムをバイパスします。

ただし、ルート(特権)ユーザーがiノード番号でファイルを開く標準的な方法がない理由は説明されていません。とにかくアクセス許可のチェックがバイパスされるためです。これは、バックアップなどの特定のシステム管理機能に非常に役立ちます。私の知る限り、そのようなメカニズムは存在しますが、それらはすべてファイルシステム固有のものです。UNIXファイルシステムに対して一般的な方法はありません。


1
フォワードイン/はサイレントなので、「スラッシュ」と発音されます。
ctrl-alt-delor

4

質問は、理論的に(で達成できるdebugfs)または実用的に(緊急事態)取ることができます。後者の場合、意図は日を保存し、おそらく緊急にファイルのコンテンツを復元することだと思います(これが私がこの質問にたどり着いた方法なので、今でも関連性があり有用であると思います)。

カーネルAPI debugfsがないため、FS構造を直接操作するため、ライブファイルシステム上で実行しないでください。したがって、ライブで実行するには、別のファイル名を取得する必要があります。ファイルが何らかのプロセス(任意のプロセス)によってまだ開かれていると仮定すると、次の場所にある便利なファイル記述子に到達できます/proc

$ lsof -F pf "$PWD/a" | sed 's/^p//' # find pid and file descriptor number of any process having the file open
$ pid=1234
$ ls -l /proc/$pid/fd/* | grep "$PWD/a" # find file descriptor number
$ fd=42
$ cat /proc/$pid/fd/$fd > "$PWD/a.restored" # read contents to a new filename

ヒント:

  • あなたは右のFDについて疑問を持っている場合は、次のようなコマンドを実行することができfile、その上を
  • ファイルに書き込むプロセスがある場合は、できるだけ早くそのプロセスを停止してください。停止しないと、最新のデータを取得できません。(テストされていない)トリックは、他のプロセスでfdを介して読み取り専用でファイルを開くことです(try tail -f < /proc/$pid/fd/$fd > /dev/null、書き込みプロセスを終了してきれいに終了し、新しいプロセスのfdを使用します)。

2
それはtail -f < /proc/...2番目のヒントにあるはずです。
マレージェンセン

または、書き込みプロセスが追加のみを行う場合(シークを戻して書き換えない場合)、の代わりに最初にコピーするために使用 tail -c +0 -fしますcat。前tailに他のプロセスをtail終了し、ファイルの終わりに到達するまで待ちます。
ピーターコーデス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.