Kann eine Datei über ihren Inode abgerufen werden?

27

Ich habe die folgenden Befehle in der angegebenen Reihenfolge ausgeführt:

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

Ich bin aus diesem Test zu dem Schluss gekommen, dass der Befehl rmtatsächlich nur den Dateinamen ( ain diesem Test) anstelle der Datei entfernt, da der Inode noch vorhanden ist und über einen anderen Dateinamen ( b) abgerufen werden kann .

Meine Frage ist, ob, wenn eine Datei fest mit nur einem Dateinamen verknüpft ist, wenn zur Datei rmausgeführt wird, die echte Datei (dh der Inode) vollständig entfernt wird? Und wenn nicht, kann ein Datei-Inode ohne Dateinamen und nur über den Inode abgerufen werden?

user43312
quelle
Klingt für mich betriebssystemspezifisch.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams. Du meinst es kommt auf die Version an?
user43312
Nein, ich meine, es hängt vom Betriebssystem ab. Jeder hat andere (wenn überhaupt ) Möglichkeiten, das VFS zu nutzen.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams Hast du eine Idee zu RHL oder RHEL?
user43312
1
@ BruceEdiger Os X macht das irgendwie. Sie können auf ein Dateisystemobjekt zugreifen, indem Sie eine "Dateireferenz-URL" verwenden, die sich im Wesentlichen aus der Dateisystemnummer und der Knotennummer zusammensetzt. Es wird jedoch nicht offiziell unterstützt, diese selbst zu erstellen. Stattdessen erhalten Sie eine "Dateireferenz-URL" für eine Datei und verwenden diese anstelle des Pfadnamens für nachfolgende Zugriffe in derselben Laufzeitsitzung, sodass Ihre Anwendung nicht mehr merkt, dass die Datei auf demselben Volume an einen anderen Ort verschoben wird.
Analoge Datei

Antworten:

29

Wenn Sie versuchen, eine Datei über ihren Inode zu öffnen, wird die Verzeichnisüberquerung umgangen. Die Verzeichnisdurchquerung ist erforderlich, um die Berechtigungen der Datei und der dazu führenden Verzeichnisse zu bestimmen. Ohne Directory Traversal kann der Kernel nicht feststellen, ob der aufrufende Prozess auf die Datei zugreifen darf.

Es wurde ein Patch für den Linux-Kernel vorgeschlagen, mit dem über einen Dateideskriptor ein Link zu einer Datei erstellt werden kann . Es wurde abgelehnt, weil die sichere Implementierung extrem schwierig gewesen wäre .

Unter Linux (und wahrscheinlich auch unter anderen Unix-Varianten aus demselben Grund) können Sie keine Verknüpfung zu einer gelöschten Datei erstellen. Wenn also eine Datei keinen Namen mehr hat, können Sie keine neue hinzufügen.¹ Sie können eine gelöschte öffnen Datei durch Öffnen der Magic Links unter /proc/$pid/fd/.

Wenn eine Datei keinen Link mehr hat und nicht mehr geöffnet ist, ist sie nicht mehr vorhanden und der zuvor von ihren Daten verwendete Speicherplatz kann jederzeit zurückgefordert werden.

¹ Möglicherweise können Sie dies tun, indem Sie die Bytes direkt im Dateisystem dateisystemabhängig drehen, z. B. mit debugfsext2 / ext3 / ext4. Dies erfordert den Zugriff auf das Gerät, auf dem das Dateisystem eingehängt ist (dh normalerweise kann es nur Root versuchen). Während Debugfs über Inode auf eine Datei zugreifen können, hilft dies nicht, wenn die Datei gelöscht wird: Die Datei wird wirklich gelöscht, wenn die Anwendung sie schließt, und das Ausführen von Debugfs im Lese- / Schreibmodus auf einem bereitgestellten Dateisystem ist ein Rezept für Katastrophe.

Gilles 'SO - hör auf böse zu sein'
quelle
11

Unter Linux bietet debugfsder interaktive Debugger für lndas Dateisystem ext2 / ext3 / ext4 einen Befehl, der eine Inode-Nummer annehmen filespecund eine neue feste Verbindung zur entsprechenden Datei herstellen kann. In der Praxis erfordert dies jedoch, dass die nicht verknüpfte Datei von einem Prozess geöffnet bleibt und ein offener Dateideskriptor in beibehalten wird /proc/[pid]/fd/[n]. Der Versuch, dies für eine gelöschte Datei zu tun, führt höchstwahrscheinlich zu einer Beschädigung des Dateisystems.

Dies liegt daran, dass, um sicherzustellen, dass ext3 (und in der Erweiterung ext4) eine Verknüpfung nach einem Absturz sicher wiederherstellen können , die Blockzeiger im Inode auf Null gesetzt werden , während ext2 diese Blöcke in den Blockbitmaps nur als unbenutzt markiert und die inode als "gelöscht" und lässt die Blockzeiger in Ruhe. Da das Dateisystem jedoch mit Lese- und Schreibzugriff bereitgestellt werden muss, um die feste Verknüpfung zu erstellen, wurden die für die gelöschte Datei reservierten Blöcke möglicherweise bereits neu zugewiesen.

Vor der Kernel-Version 2.6.39 konnte mit der in GNU coreutils 8.0 eingeführten Option eine nicht verknüpfte Datei über einen offenen Dateideskriptor wiederhergestellt werden, wenn sich sowohl die nicht verknüpfte Datei als auch der neue Hardlink auf einem tmpfs- Dateisystem befanden . Diese Funktion wurde seitdem deaktiviert , da, wie Gilles betonte, Sicherheitsaspekte bei der Erstellung von Hardlinks direkt aus einem Dateideskriptor heraus berücksichtigt wurden.ln -L|--logical/proc/[pid]/fd/[n]

Thomas Nyman
quelle
Ich habe gerade versucht ln -L, eine gelöschte Datei aus / proc wiederherzustellen und habe den Fehler erhalten: "Keine solche Datei oder kein solches Verzeichnis", daher glaube ich nicht, dass dies tatsächlich unterstützt wird. Ich habe Coreutils 8.21.
Wingedsubmariner
1
ln -Ltut nicht, was du sagst. Es sagt , lndass , wenn die Quelle eine symbolische Verknüpfung ist, sollte es das Ziel hart verknüpfen. Die symbolischen Links in /proc/$pid/fdsind speziell, und das feste Verknüpfen eines (deleted)Links funktioniert nicht.
Gilles 'SO- hör auf böse zu sein'
Es debugfshilft auch nicht, wenn die Datei gelöscht wurde - es sei denn, Sie möchten riskieren, dass sie im Lese- / Schreibmodus auf einem bereitgestellten Dateisystem ausgeführt wird, wodurch wahrscheinlich das gesamte Dateisystem vollständig zerstört wird.
Gilles 'SO- hör auf böse zu sein'
Aktualisiert die Antwort in Bezug auf ln -L. Früher war /proc/[pid]/fd/[n]es unter bestimmten Umständen möglich, feste Verknüpfungen zu erstellen , dies wurde jedoch inzwischen behoben.
Thomas Nyman
1
debugfs's lnist wirklich niedrig und erstellt nur einen Namen, aktualisiert die Anzahl nicht und hebt die Markierung der Blöcke als nicht verwendet auf, sodass es sehr gefährlich ist . Bevorzugen debugfs‚s undeldie das alles. Achtung: debugfswird nicht ausgeführt wird auf einem Dateisystem gemountet , wenn Sie eine Chance auf dem Brennen FS zu Asche nehmen.
Lloeki
9

Die Befehle 'ln' und 'rm' haben seit Anfang der 1970er Jahre in jedem UNIX-Dateisystem genau so funktioniert. Mac OSX, BSD und Linux erben alle dieses ursprüngliche Design.

Eine UNIX-Datei selbst hat keinen Namen, nur eine Inode- Nummer oder eine Inum. Sie können jedoch nur über einen Eintrag in einer speziellen "Verzeichnis" -Datei darauf zugreifen, die der fraglichen inum einen Namen zuordnet. Sie können die Inum nicht direkt angeben.

Ein Verzeichnis ist selbst eine Datei, so dass Sie auch zugreifen , müssen sie durch (anderes) Verzeichnis und so weiter, durch eine Reihe von Verzeichnisnamen durch Schrägstriche begrenzt (/) als „Pfadname“ bekannt. Ein Pfad beginnt im "aktuellen Arbeitsverzeichnis" des Prozesses, es sei denn, der Name beginnt mit einem "/". In diesem Fall beginnt er mit dem Stammverzeichnis des Dateisystems. Wenn der Pfadname beispielsweise keine "/" -Zeichen enthält, wird ein Eintrag im aktuellen Verzeichnis erwartet.

Eine Nicht-Verzeichnis-Datei kann eine beliebige Anzahl von Pfadnamen haben, die als "harte Verknüpfungen" bezeichnet werden. Sie bleibt bestehen, bis alle Pfadnamen entfernt wurden und der letzte Prozess die Datei geschlossen hat. Dann wird die Datei tatsächlich gelöscht und ihr Speicherplatz als zur Wiederverwendung verfügbar markiert. Das heißt, Sie können eine einfach verknüpfte Datei erstellen () oder öffnen () und dann die Verknüpfung aufheben (), sodass sie nicht mehr im Namensraum des Dateisystems angezeigt wird. Die Datei bleibt jedoch bestehen, bis Sie sie schließen. Dies ist nützlich für temporäre Arbeitsdateien, die von keinem anderen Programm gelesen werden.

Obwohl Verzeichnisse über Inode-Nummern verfügen, lassen die meisten Dateisysteme keine festen Verknüpfungen zu. Sie können nur in einem anderen Verzeichnis angezeigt werden. (Eine ungewöhnliche Ausnahme ist das Mac OSX HFS + -Dateisystem. Dadurch können Time Machine-Sicherungen ausgeführt werden.) Sie können weiterhin "Softlinks" zu Verzeichnissen (oder anderen Dateien) erstellen. Ein Softlink ähnelt einem Verzeichniseintrag, enthält jedoch keinen inum, sondern einen anderen Pfadnamen.

Jede UNIX-Datei verfügt über Eigentümer-, Gruppen- und Zugriffsberechtigungen. Es ist notwendig, aber nicht ausreichend, dass Sie die Datei öffnen können. Sie müssen außerdem für jedes Verzeichnis in dem Pfadnamen, auf den Sie verweisen, mindestens über Ausführungsberechtigungen verfügen. Aus diesem Grund gibt es keine Standardmethode zum Öffnen einer UNIX-Datei anhand ihrer Inode-Nummer. das würde einen wichtigen, weit verbreiteten Sicherheitsmechanismus umgehen.

Dies erklärt jedoch nicht, warum es für einen (privilegierten) Root- Benutzer keine Standardmethode zum Öffnen einer Datei nach Inode-Nummer gibt, da die Berechtigungsprüfung ohnehin umgangen wird. Dies wäre für bestimmte Systemverwaltungsfunktionen wie z. B. Sicherungen sehr nützlich. Meines Wissens existieren solche Mechanismen, aber sie sind alle dateisystemspezifisch. Es gibt keine allgemeine Möglichkeit, dies für ein UNIX-Dateisystem zu tun.

Phil Karn
quelle
1
Das Weiterleiten /ist stumm, daher wird es als "Schrägstrich" ausgesprochen.
Strg-Alt-Delor
4

Die Frage kann theoretisch (was mit erreicht werden kann debugfs) oder pragmatisch (Notfallsituation) gestellt werden. Im letzteren Fall gehe ich davon aus, dass die Absicht darin besteht, den Tag zu retten und den Inhalt der Datei möglicherweise dringend wiederherzustellen (so bin ich auf diese Frage gestoßen, und ich denke, dass sie immer noch relevant und nützlich ist).

Da es keine Kernel-API gibt, debugfssollte diese nicht auf einem Live-Dateisystem ausgeführt werden, da sie die FS-Struktur direkt manipuliert. Um es live zu machen, müssen Sie sich daher einen anderen Dateinamen besorgen. Angenommen, die Datei ist noch von einem Prozess (einem beliebigen Prozess) geöffnet, können Sie nach den immer praktischen Dateideskriptoren in den folgenden Abschnitten suchen /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

Tipps:

  • Wenn Sie Zweifel an der richtigen fd haben, können Sie Befehle wie fileauf sie ausführen
  • Wenn ein Prozess in die Datei schreibt, müssen Sie diesen Prozess so schnell wie möglich beenden, da Sie sonst nicht die neuesten Daten erhalten. Ein (ungetesteter) Trick könnte darin bestehen, die Datei mit einem anderen Prozess schreibgeschützt über das fd zu öffnen (versuchen Sie tail -f < /proc/$pid/fd/$fd > /dev/null, den Schreibvorgang zu beenden, damit er sauber beendet wird, und das fd des neuen Prozesses zu verwenden.
Lloeki
quelle
2
Das sollte tail -f < /proc/...im zweiten Tipp stehen.
Murray Jensen
Oder verwenden Sie, tail -c +0 -f um es an erster Stelle zu kopieren, anstatt cat, wenn der Schreibvorgang nur angehängt wird (kein Zurücksuchen und Neuschreiben). Beenden Sie den anderen Prozess zuvor tailund warten Sie tail, bis die Datei fertig ist.
Peter Cordes