.\" -*- coding: UTF-8 -*- .\" Copyright (C) 2019 Michael Kerrisk .\" A very few fragments remain from an earlier page written by .\" Werner Almesberger in 2000 .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH pivot_root 2 "3. Mai 2023" "Linux man\-pages 6.05.01" .SH BEZEICHNUNG pivot_root \- die Wurzeleinhängung ändern .SH BIBLIOTHEK Standard\-C\-Bibliothek (\fIlibc\fP, \fI\-lc\fP) .SH ÜBERSICHT .nf \fB#include \fP /* Definition der \fBSYS_*\fP\-Konstanten */ \fB#include \fP .PP \fBint syscall(SYS_pivot_root, const char *\fP\fIneue_Wurzel\fP\fB, const char *\fP\fIalte_Wurzel\fP\fB);\fP .fi .PP \fIHinweis\fP: Glibc stellt keinen Wrapper für \fBpivot_root\fP() bereit; rufen Sie ihn mittels \fBsyscall\fP(2) auf. .SH BESCHREIBUNG \fBpivot_root\fP() ändert die Einhängewurzel im Einhängenamensraum des aufrufenden Prozesses. Genauer ausgedrückt verschiebt es die Einhängewurzel in das Verzeichnis \fIalte_Wurzel\fP und macht \fIneue_Wurzel\fP zur neuen Einhängewurzel. Der aufrufende Prozess muss in dem Benutzer\-Namensraum, zu dem der Einhängenamensraum des Aufrufenden gehört, über die \fBCAP_SYS_ADMIN\fP\-Capability verfügen. .PP \fBpivot_root\fP() ändert das Wurzelverzeichnis und das aktuelle Arbeitsverzeichnis jedes Prozesses oder Threads im gleichen Namensraum in \fIneue_Wurzel\fP, falls diese auf das alte Verzeichnis zeigen (siehe auch ANMERKUNGEN). Andererseits ändert \fBpivot_root\fP() das aktuelle Arbeitsverzeichnis des Aufrufenden nicht (es sei denn, es ist das alte Wurzelverzeichnis), daher sollte darauf ein Aufruf von \fBchdir("/")\fP folgen. .PP Die folgenden Einschränkungen gelten: .IP \[bu] 3 \fINeue_Wurzel\fP und \fIalte_Wurzel\fP müssen Verzeichnisse sein. .IP \[bu] Die \fIneue_Wurzel\fP und die \fIalte_Wurzel\fP dürfen sich nicht in der gleichen Einhängung wie die aktuelle Wurzel befinden. .IP \[bu] Die \fIalte_Wurzel\fP muss sich unterhalb der \fIneuen_Wurzel\fP befinden, das heißt, Hinzufügen einer nicht\-negativen Anzahl von \fI/..\fP zum Pfadnamen, der auf die \fIalte_Wurzel\fP zeigt, muss das gleiche Verzeichnis wie die \fIneue_Wurzel\fP ergeben. .IP \[bu] \fINeue_Wurzel\fP muss ein Pfad zu einem Einhängepunkt sein, aber darf nicht \fI"/"\fP sein. Ein Pfad, der nicht bereits ein Einhängepunkt ist, kann umgewandelt werden, indem er auf sich selbst bind\-eingehängt wird. .IP \[bu] Der Ausbreitungstyp von \fIneue_Wurzel\fP und seiner Elterneinhängung dürfen nicht \fBMS_SHARED\fP sein; entsprechend falls \fIalte_Wurzel\fP ein bestehender Einhängepunkt ist, darf sein Ausbreitungstyp nicht \fBMS_SHARED\fP sein. Diese Einschränkungen stellen sicher, dass \fBpivot_root\fP() niemals Änderungen in einen anderen Einhänge\-Namensraum ausbreitet. .IP \[bu] Das aktuelle Wurzelverzeichnis muss ein Einhängepunkt sein. .SH RÜCKGABEWERT Bei Erfolg wird Null zurückgegeben. Bei einem Fehler wird \-1 zurückgegeben und \fIerrno\fP gesetzt, um den Fehler anzuzeigen. .SH FEHLER \fBpivot_root\fP() kann jeden der von \fBstat\fP(2) zurückgegebenen Fehler zurückgeben. Zusätzlich kann Folgendes zurückgegeben werden: .TP \fBEBUSY\fP .\" Reconfirmed that the following error occurs on Linux 5.0 by .\" specifying 'new_root' as "/rootfs" and 'put_old' as .\" "/rootfs/oldrootfs", and *not* bind mounting "/rootfs" on top of .\" itself. Of course, this is an odd situation, since a later check .\" in the kernel code will in any case yield EINVAL if 'new_root' is .\" not a mount point. However, when the system call was first added, .\" 'new_root' was not required to be a mount point. So, this .\" error is nowadays probably just the result of crufty accumulation. .\" This error can also occur if we bind mount "/" on top of itself .\" and try to specify "/" as the 'new' (again, an odd situation). So, .\" the EBUSY check in the kernel does still seem necessary to prevent .\" that case. Furthermore, the "or put_old" piece is probably .\" redundant text (although the check is in the kernel), since, .\" in another check, 'put_old' is required to be under 'new_root'. Die \fIneue_Wurzel\fP oder die \fIalte_Wurzel\fP sind in der aktuellen Wurzeleinhängung. (Dieser Fehler deckt den pathologischen Fall ab, wenn die \fIneue_Wurzel\fP \fI"/"\fP ist.) .TP \fBEINVAL\fP \fIneue_Wurzel\fP ist kein Einhängepunkt. .TP \fBEINVAL\fP Die \fIalte_Wurzel\fP ist nicht in oder unterhalb der \fIneuen_Wurzel\fP. .TP \fBEINVAL\fP Das aktuelle Wurzelverzeichnis ist kein Einhängepunkt (wegen eines früher ausgeführten \fBchroot\fP(2)). .TP \fBEINVAL\fP Die aktuelle Wurzel ist auf dem Rootfs (anfänglichen Ramfs\-)Dateisystem; siehe ANMERKUNGEN. .TP \fBEINVAL\fP Entweder der Einhängepunkt unter \fIneue_Wurzel\fP oder die Elterneinhängung dieses Einhängepunktes hat den Ausbreitungstyp \fBMS_SHARED\fP. .TP \fBEINVAL\fP \fIalte_Wurzel\fP ist ein Einhängepunkt und der Ausbreitungstyp ist \fBMS_SHARED\fP. .TP \fBENOTDIR\fP \fIneue_Wurzel\fP oder \fIalte_Wurzel\fP ist kein Verzeichnis. .TP \fBEPERM\fP Der aufrufende Prozess verfügt nicht über die \fBCAP_SYS_ADMIN\fP\-Capability. .SH STANDARDS Linux. .SH GESCHICHTE Linux 2.3.41. .SH ANMERKUNGEN Eine Befehlszeilenschnittstelle für diesen Systemaufruf wird durch \fBpivot_root\fP(8) bereitgestellt. .PP \fBpivot_root\fP() ermöglicht dem Aufrufenden, in eine neue Dateisystemwurzel zu wechseln, während gleichzeitig die alte Einhängewurzel an einem Ort unterhalb der \fIneuen_Wurzel\fP platziert wird, wo sie anschließend ausgehängt werden kann. (Die Tatsache, dass alle Prozesse, die ein Wurzelverzeichnis oder ein aktuelles Arbeitsverzeichnis unterhalb des alten Wurzelverzeichnisses haben, zu der neuen Wurzel verschoben werden, befreit das alte Wurzelverzeichnis von Benutzern, wodurch das alte Wurzelverzeichnis leichter ausgehängt werden kann.) .PP Der typische Anwendungsfall von \fBpivot_root\fP() ist während des Systemstarts, wenn das System ein temporäres Wurzeldateisystem einhängt, zum Beispiel ein \fBinitrd\fP(4). Danach wird das reale Wurzeldateisystem eingehängt und eventuell in die aktuelle Wurzel aller relevanten Prozesse und Threads verwandelt. Ein moderner Anwendungsfall ist die Einrichtung eines Wurzeldateisystems während der Erzeugung eines Containers. .PP \fBpivot_root\fP() verändert die Wurzel und das aktuelle Arbeitsverzeichnis in der im Abschnitt BESCHREIBUNG angegebenen Weise. Dies ist nötig, um Kernel\-Threads daran zu hindern, die alte Einhängewurzel mit ihren Wurzeln und aktuellen Arbeitsverzeichnissen belegt zu halten, selbst dann, wenn sie auf das Dateisystem niemals zugreifen. .PP .\" Das Rootfs (anfängliche Ramfs) kann nicht mittels \fBpivot_root\fP erreicht werden. Die in diesem Fall empfohlene Methode zur Änderung des Wurzeldateisystems ist das Löschen sämtlicher Inhalte im Rootfs, das Rootfs mit der neuen Wurzel übereinzuhängen, \fIstdin\fP/\fIstdout\fP/\fIstderr\fP an das neue \fI/dev/console\fP anzuhängen und das neue \fBinit\fP(1) auszuführen. Helferprogramme für diesen Prozess existieren: siehe \fBswitch_root\fP(8). .SS "pivot_root(\[dq].\[dq], \[dq].\[dq])" \fINeue_Wurzel\fP und \fIalte_Wurzel\fP können das gleiche Verzeichnis sein. Die folgende Sequenz erlaubt eine Pivot\-Root\-Aktion, ohne dass ein temporäres Verzeichnis angelegt und wieder entfernt werden muss: .PP .in +4n .EX chdir(neue_Wurzel); pivot_root(".", "."); umount2(".", MNT_DETACH); .EE .in .PP .\" Diese Sequenz ist erfolgreich, weil der Aufruf von \fBpivot_root\fP() den alten Wurzeleinhängepunkt über den neuen Wurzeleinhängepunkt in \fI/\fP stapelt. An diesem Punkt beziehen sich das Wurzelverzeichnis und das aktuelle Arbeitsverzeichnis des aufrufenden Prozesses auf den neuen Wurzeleinhängepunkt (\fIneue_Wurzel\fP). Während des darauf folgenden Aufrufs von \fBumount\fP() beginnt die Auflösung von \fI"."\fP mit der \fIneue_Wurzel\fP und wandert dann die Liste der in \fI/\fP gestapelten Einhängungen hinauf, mit dem Ergebnis, dass der alte Einhängepunkt ausgehängt wird. .SS "Geschichtliche Anmerkungen" Viele Jahre lang enthielt diese Handbuchseite den folgenden Text: .RS .PP \fBpivot_root\fP() kann die aktuelle Wurzel und das aktuelle Arbeitsverzeichnis von Prozessen und Threads ändern, welche das alte Wurzelverzeichnis nutzen, muss dies aber nicht. Der Prozess, welcher \fBpivot_root\fP() aufruft, muss sicherstellen, dass Prozesse mit Wurzel\- oder aktuellem Arbeitsverzeichnis in jedem Fall korrekt arbeiten. Ein einfacher Weg hierzu ist die Änderung von Wurzel\- und aktuellem Arbeitsverzeichnis auf die \fIneue_Wurzel\fP, bevor \fBpivot_root\fP() aufgerufen wird. .RE .PP Dieser Text, der geschrieben wurde, bevor, die Implementierung des Systemaufrufs im Kernel überhaupt abgeschlossen war, beabsichtigte seinerzeit möglicherweise, die Benutzer zu warnen, dass sich die Implementation bis zur finalen Veröffentlichung ändern könnte. Jedoch ist das im Abschnitt BESCHREIBUNG angegebene Verhalten seit der Erstveröffentlichung dieses Systemaufrufs konsistent geblieben und wird sich nun nicht ändern. .SH BEISPIELE .\" FIXME .\" Would it be better, because simpler, to use unshare(2) .\" rather than clone(2) in the example below? Das untenstehende Programm beschreibt die Verwendung von \fBpivot_root\fP() innerhalb eines Einhängenamensraums, der mit \fBclone\fP(2) erstellt wurde. Nach dem Umschwenken zu dem im ersten Befehlszeilenargument des Programms benannten Wurzelverzeichnis führt der mit \fBclone\fP(2) erzeugte Kindprozess das in den übrigen Befehlszeilenargumenten benannte Programm aus. .PP Wir demonstrieren das Programm durch Anlegen eines Verzeichnisses, das als das neue Wurzeldateisystem dient, und Setzen einer (statisch gelinkten) Kopie der ausführbaren Datei \fBbusybox\fP(1) in dieses Verzeichnis. .PP .in +4n .EX $ \fBmkdir /tmp/rootfs\fP $ \fBls \-id /tmp/rootfs\fP # Inode\-Anzahl des neuen Wurzelverzeichnisses zeigen 319459 /tmp/rootfs $ \fBcp $(which busybox) /tmp/rootfs\fP $ \fBPS1=\[aq]bbsh$ \[aq] sudo ./pivot_root_demo /tmp/rootfs /busybox sh\fP bbsh$ \fBPATH=/\fP bbsh$ \fBbusybox ln busybox ln\fP bbsh$ \fBln busybox echo\fP bbsh$ \fBln busybox ls\fP bbsh$ \fBls\fP busybox echo ln ls bbsh$ \fBls \-id /\fP # Mit der Inode\-Anzahl oben vergleichen 319459 / bbsh$ \fBecho \[aq]Hallo Welt\[aq]\fP Hallo Welt .EE .in .SS Programmquelltext \& .PP .\" SRC BEGIN (pivot_root.c) .EX /* pivot_root_demo.c */ \& #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include \& static int pivot_root(const char *new_root, const char *put_old) { return syscall(SYS_pivot_root, new_root, put_old); } \& #define STACK_SIZE (1024 * 1024) \& static int /* Startfunktion für das geklonte Kind */ child(void *arg) { char path[PATH_MAX]; char **args = arg; char *new_root = args[0]; const char *put_old = "/oldrootfs"; \& /* Sicherstellen, dass »neue_Wurzel« und dessen Elterneinhängung keine gemeinsame Ausbreitung haben (was pivot_root() dazu bringen würde, einen Fehler auszugeben) und die Ausbreitung von Einhängeereignissen in den anfänglichen Namensraum zu verhindern. */ \& if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) == \-1) err(EXIT_FAILURE, "mount\-MS_PRIVATE"); \& /* Sicherstellen, dass »neue_Wurzel« ein Einhängepunkt ist. */ \& if (mount(new_root, new_root, NULL, MS_BIND, NULL) == \-1) err(EXIT_FAILURE, "mount\-MS_BIND"); \& /* Ein Verzeichnis anlegen, zu dem die alte Wurzel hin umgeschwenkt wird. */ \& snprintf(path, sizeof(path), "%s/%s", new_root, put_old); if (mkdir(path, 0777) == \-1) err(EXIT_FAILURE, "mkdir"); \& /* Und das Wurzeldateisystem umschwenken. */ \& if (pivot_root(new_root, path) == \-1) err(EXIT_FAILURE, "pivot_root"); \& /* Das aktuelle Arbeitsverzeichnis auf »/« ändern. */ \& if (chdir("/") == \-1) err(EXIT_FAILURE, "chdir"); \& /* Die alte Wurzel aushängen und den Einhängepunkt entfernen.*/ \& if (umount2(put_old, MNT_DETACH) == \-1) perror("umount2"); if (rmdir(put_old) == \-1) perror("rmdir"); \& /* Den in argv[1] … angegebenen Befehl ausführen */ \& execv(args[1], &args[1]); err(EXIT_FAILURE, "execv"); } \& int main(int argc, char *argv[]) { char *stack; \& /* Einen Kindprozess in einem neuen Einhängenamensraum erzeugen. */ \& stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, \-1, 0); if (stack == MAP_FAILED) err(EXIT_FAILURE, "mmap"); \& if (clone(child, stack + STACK_SIZE, CLONE_NEWNS | SIGCHLD, &argv[1]) == \-1) err(EXIT_FAILURE, "clone"); \& /* Elternprozess fällt bis hierher durch; wartet auf Kindprozess. */ \& if (wait(NULL) == \-1) err(EXIT_FAILURE, "wait"); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "SIEHE AUCH" \fBchdir\fP(2), \fBchroot\fP(2), \fBmount\fP(2), \fBstat\fP(2), \fBinitrd\fP(4), \fBmount_namespaces\fP(7), \fBpivot_root\fP(8), \fBswitch_root\fP(8) .PP .SH ÜBERSETZUNG Die deutsche Übersetzung dieser Handbuchseite wurde von Mario Blättermann und Helge Kreutzmann erstellt. .PP Diese Übersetzung ist Freie Dokumentation; lesen Sie die .UR https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3 .UE oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen. .PP Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die .MT debian-l10n-german@lists.debian.org Mailingliste der Übersetzer .ME .