BEZEICHNUNG

path_resolution - Wie ein Pfadname zu einer Datei aufgelöst wird

BESCHREIBUNG

Einige UNIX/Linux-Systemaufrufe haben als Parameter einen oder mehrere Dateinamen. Ein Dateiname (oder Pfadname) wird wie folgt aufgelöst:

Schritt 1: Start des Auflösungsprozesses

Falls der Pfadname mit dem Zeichen »/« beginnt, wird das Wurzelverzeichnis des aufrufenden Prozesses als Startverzeichnis beim Nachschlagen verwandt. Ein Prozess erbt sein Wurzelverzeichnis von seinem Elternprozess. Normalerweise wird dies das Wurzelverzeichnis der Dateihierarchie sein. Durch die Verwendung des Systemaufrufs chroot(2) kann ein Prozess ein anderes Wurzelverzeichnis erhalten oder er kann mittels openat2(2) mit dem gesetzten Schalter RESOLVE_IN_ROOT temporär ein anderes Wurzelverzeichnis erhalten.
Ein Prozess kann einen komplett privaten Einhängenamensraum erhalten, falls er–oder einer seiner Vorgänger–durch einen Systemaufruf von clone(2) mit gesetztem Schalter CLONE_NEWNS gestartet wurde. Dieser handhabt den »/«-Anteil des Pfadnamens.
Falls der Pfadname nicht mit dem Zeichen »/« beginnt, ist das Nachschlage-Startverzeichnis für den Pfadauflösungsprozess das aktuelle Arbeitsverzeichnis des Prozesses – oder im Falle von Systemaufrufen im Stil von openat(2), das Argument dfd (oder das aktuelle Arbeitsverzeichnis, falls AT_FDCWD als Argument dfd übergeben wurde). Das aktuelle Arbeitsverzeicnis wird vom Elternprozess geerbt und kann mittels des Systemaufrufs chdir(2) geändert werden.
Pfadnamen, die mit dem Zeichen »/« beginnen, werden absolute Pfadnamen genannt. Alle anderen Pfadnamen heißen relative Pfadnamen.

Schritt 2: Ablaufen entlang des Pfades

Das aktuelle Nachschlageverzeichnis wird auf das Nachschlage-Startverzeichnis gesetzt. Jetzt wird für jede nicht abschließende Komponente des Pfadnamens diese im aktuellen Nachschlageverzeichnis nachgeschlagen. Hierbei ist eine Komponente eine Teilzeichenkette, die durch das Zeichen »/« abgetrennt wird.
Falls der Prozess über keine Suchberechtigungen im aktuellen Nachschlage-Verzeichnis verfügt, wird der Fehler EACCES (»Keine Berechtigung«) zurückgeliefert.
Falls die Komponente nicht gefunden wird, wird der Fehler ENOENT (»Datei oder Verzeichnis nicht gefunden«) zurückgeliefert.
Falls eine Komponente gefunden wird, aber weder ein Verzeichnis noch ein symbolischer Link ist, wird der Fehler ENOTDIR (»Ist kein Verzeichnis«) zurückgeliefert.
Falls die Komponente gefunden wird und ein Verzeichnis ist, wird das aktuelle Nachschlage-Verzeichnis auf dieses Verzeichnis gesetzt und zur nächsten Komponenten gewechselt.
Falls die Komponente gefunden wird und ein symbolischer Link ist, wird zuerst dieser symbolische Link aufgelöst (mit dem anfänglichen Nachschlage-Verzeichnis). Im Fehlerfall wird dieser Fehler zurückgeliefert. Falls das Ergebnis kein Verzeichnis ist, wird der Fehler ENOTDIR zurückgeliefert. Falls die Auflösung des symbolischen Links erfolgreich ist und ein Verzeichnis zurückliefert, wird das aktuelle Nachschlage-Verzeichnis auf dieses Verzeichnis gesetzt und zur nächsten Komponente gewechselt. Bachten Sie, dass dieser Auflösungsprozess Rekursionen enthalten kann, falls die Präfixkomponente (»dirname«) eines Pfadnamens einen Dateinamen enthält, der ein symbolischer Link ist, der sich auf ein Verzeichnis auflöst (wobei die Präfixkomponente dieses Verzeichnisses einen symbolischen Link enthalten könnte und so weiter). Um den Kernel gegen eine Stapelüberlauf und auch eine Diensteverweigerung zu schützen, gibt es Begrenzungen zur Rekursionstiefe und der maximalen Anzahl an gefolgten symbolischen Links. Ein Fehler ELOOP wird zurückgeliefert, wenn das Maximum überschritten wurde (»Zu viele Ebenen aus symbolischen Links«).
Derzeit ist in Linux die maximale Anzahl von beim Auflösen von Pfadnamen gefolgten symbolischen Links auf 40 begrenzt. In Linux vor 2.6.18 war die Begrenzung der Rekursionstiefe 5. Seit Linux 2.6.18 wurde diese Begrenzung auf 8 erhöht. In Linux 4.2 wurde der Code für die Pfadnamenauflösung überarbeitet, um die Verwendung von Rekursion zu beseitigen, so dass die einzige verbliebene Begrenzung die maximalen 40 Auflösungen für den gesamten Pfadnamen ist.
Die Auflösung symbolischer Links während dieser Stufe kann mittels openat2(2) durch den gesetzten Schalter RESOLVE_NO_SYMLINKS verhindert werden.

Schritt 3: Finden des finalen Eintrags

Das Nachschlagen der finalen Komponente des Pfadnamens erfolgt genau wie der von allen anderen Komponenten, wie im vorherigen Schritt beschrieben, mit zwei Unterschieden: (i) die finale Komponente muss kein Verzeichnis sein (zumindest soweit, wie der Pfadauflösungsprozess betroffen ist – es mag ein Verzeichnis oder keines sein müssen, abhängig von den Anforderungen des spezifischen Systemaufrufs) und (ii) es ist nicht unbedingt ein Fehler, falls die Komponente nicht gefunden wird – vielleicht wird sie gerade erstellt. Die Details der Behandlung des abschließenden Eintrags werden in den Handbuchseiten der jeweiligen Systemaufrufe beschrieben.

. und ..

Herkömmlicherweise hat jedes Verzeichnis zwei Einträge (».« und »..«), die sich auf das Verzeichnis selbst bzw. sein übergeordnetes Verzeichnis beziehen.
Der Pfadauflösungsprozess wird annehmen, dass diese zwei Einträge ihre konventionelle Bedeutung haben, unabhängig davon, ob sie im physischen Dateisystem tatsächlich vorhanden sind.
Sie können nicht höher als die Wurzel aufsteigen: »/..« ist zu »/« identisch.

Einhängepunkte

Nach einem Befehl mount Gerät Pfad bezieht sich der Pfadname »Pfad« auf die Wurzel der Dateisystemhierarchie auf dem Gerät »Gerät« und nicht auf etwas, worauf es sich vorher bezog.
Sie können sich außerhalb des eingehängten Dateisystems bewegen: »Pfad/..« bezieht sich auf das übergeordnete Verzeichnis von »Pfad« außerhalb der Dateisystemhierarchie von »Gerät«.
Durchlauf von Einhängepunkten kann mittels openat2(2) mit dem gesetzten Schalter RESOLVE_NO_XDEV verhindert werden (beachten Sie allerdings, dass dies auch den Durchlauf von Bind-Einhängungen beschränkt).

Abschließende Schrägstriche

Falls ein Pfadname mit einem »/« endet, der die Auflösung der vorherigen Komponente gemäß Schritt 2 erzwingt: die Komponente vor dem Schrägstrich existiert entweder und wird zu einem Verzeichnis aufgelöst oder sie benennt ein Verzeichnis, das sofort nach der Auflösung des Pfadnamens erstellt werden soll. Andernfalls wird ein abschließender »/« ignoriert. Falls die letzte Komponente des Pfadnamens ein symbolischer Link ist, hängt es vom Systemaufruf ab, ob die Datei, auf die referenziert wird, ein symbolischer Link ist oder das Ergebnis der Pfadauflösung seiner Inhalte. Beispielsweise wird der Systemaufruf lstat(2) auf einem symbolischen Link agieren, während stat(2) auf der Datei agiert, auf die der symbolische Link zeigt.

Längenbeschränkung

Es gibt eine maximale Länge für Pfadnamen. Falls der Pfadname (oder ein Zwischenpfadname, der beim Auflösen von symbolischen Links erhalten wurde) zu lang ist, wird ein Fehler ENAMETOOLONG zurückgeliefert (»Der Dateiname ist zu lang«).

Leere Pfadnamen

Im ursprünglichen UNIX bezogen sich leere Pfadnamen auf das aktuelle Verzeichnis. Heutzutage beschließt POSIX, dass ein leerer Pfadname nicht erfolgreich aufgelöst werden darf. Linux liefert in diesem Fall ENOENT zurück.

Berechtigungen

Die Berechtigungsbits einer Datei bestehen aus drei Gruppen von drei Bits: siehe chmod(1) und stat(2). Die erste Gruppe der drei wird verwandt, wenn die effektive Benutzerkennung des aufrufenden Prozesses identisch zu der Eigentümerkennung der Datei ist. Die zweite Gruppe der drei wird verwandt, wenn die Gruppenkennung der Datei entweder mit der effektiven Gruppenkennung des aufrufenden Prozesses übereinstimmt oder eine der ergänzenden Gruppenkennungen des aufrufenden Prozesses ist (wie durch setgroups(2) gesetzt). Falls nichts davon zutrifft, wird die dritte Gruppe verwandt.
Von den drei verwandten Bits bestimmt das erste Bit die Leseberechtigung, das zweite die Schreibberechtigung und das letzte die Ausführberechtigung im Falle von gewöhnlichen Dateien oder die Suchberechtigung im Falle von Verzeichnissen.
Linux verwendet fsuid anstelle der effektiven Benutzerkennung bei Berechtigungsprüfungen. Normalerweise ist die fsuid identisch mit der effektiven Benutzerkennung, aber die fsuid kann mit dem Systemaufruf setfsuid(2) geändert werden.
(Hier steht »fsuid« für etwas wie »Dateisystembenutzerkennung«. Das Konzept wurde für die Implementierung von NFS-Servern im Benutzerbereich zu einem Zeitpunkt benötigt, zu dem ein Prozess ein Signal zu einem anderen Prozess mit der gleichen effektiven Benutzerkennung senden konnte. Dies ist jetzt veraltet. Niemand sollte setfsuid(2) verwenden.)
Auf ähnliche Weise verwendet Linux die fsgid (»Dateisystemgruppenkennung«) anstelle der effektiven Gruppenkennung. Siehe setfsgid(2).

Umgehen von Berechtigungsprüfungen: Superuser und Capabilitys

Auf einem traditionellen UNIX-System ist der Superuser ( root, Benutzerkennung 0) allmächtig und umgeht alle Berechtigungseinschränkungen beim Zugriff auf Dateien.
Unter Linux sind die Superuser-Privilegien in Capabilitys aufgeteilt (siehe capabilities(7)). Zwei Capabilitys sind für Dateiberechtigungsüberprüfungen relevant: CAP_DAC_OVERRIDE und CAP_DAC_READ_SEARCH. (Ein Prozess hat diese Capabilitys, falls seine fsuid 0 ist.)
Die Capability CAP_DAC_OVERRIDE setzt alle Berechtigungsprüfungen außer Kraft, aber gewährt die Ausführberechtigung nur, falls mindestens eines der drei Ausführ-Berechtigungs-Bits der Datei gesetzt ist.
Die Capability CAP_DAC_READ_SEARCH gewährt Lese- und Suchberechtigungen für Verzeichnisse und Leseberechtigungen für gewöhnliche Dateien.

SIEHE AUCH

readlink(2), capabilities(7), credentials(7), symlink(7)

ÜBERSETZUNG

Die deutsche Übersetzung dieser Handbuchseite wurde von Helge Kreutzmann <[email protected]> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer