Provided by: manpages-de-dev_4.27.0-1_all 

BEZEICHNUNG
pivot_root - die Wurzeleinhängung ändern
BIBLIOTHEK
Standard-C-Bibliothek (libc, -lc)
ÜBERSICHT
#include <sys/syscall.h> /* Definition der SYS_*-Konstanten */
#include <unistd.h>
int syscall(SYS_pivot_root, const char *neue_Wurzel, const char *alte_Wurzel);
Hinweis: Glibc stellt keinen Wrapper für pivot_root() bereit; rufen Sie ihn mittels syscall(2) auf.
BESCHREIBUNG
pivot_root() ändert die Einhängewurzel im Einhängenamensraum des aufrufenden Prozesses. Genauer
ausgedrückt verschiebt es die Einhängewurzel in das Verzeichnis alte_Wurzel und macht neue_Wurzel zur
neuen Einhängewurzel. Der aufrufende Prozess muss in dem Benutzer-Namensraum, zu dem der
Einhängenamensraum des Aufrufenden gehört, über die CAP_SYS_ADMIN-Capability verfügen.
pivot_root() ändert das Wurzelverzeichnis und das aktuelle Arbeitsverzeichnis jedes Prozesses oder
Threads im gleichen Namensraum in neue_Wurzel, falls diese auf das alte Verzeichnis zeigen (siehe auch
ANMERKUNGEN). Andererseits ändert pivot_root() das aktuelle Arbeitsverzeichnis des Aufrufenden nicht (es
sei denn, es ist das alte Wurzelverzeichnis), daher sollte darauf ein Aufruf von chdir("/") folgen.
Die folgenden Einschränkungen gelten:
• Neue_Wurzel und alte_Wurzel müssen Verzeichnisse sein.
• Die neue_Wurzel und die alte_Wurzel dürfen sich nicht in der gleichen Einhängung wie die aktuelle
Wurzel befinden.
• Die alte_Wurzel muss sich unterhalb der neuen_Wurzel befinden, das heißt, Hinzufügen einer
nicht-negativen Anzahl von /.. zum Pfadnamen, der auf die alte_Wurzel zeigt, muss das gleiche
Verzeichnis wie die neue_Wurzel ergeben.
• Neue_Wurzel muss ein Pfad zu einem Einhängepunkt sein, aber darf nicht »/« sein. Ein Pfad, der nicht
bereits ein Einhängepunkt ist, kann umgewandelt werden, indem er auf sich selbst bind-eingehängt wird.
• Der Ausbreitungstyp von neue_Wurzel und seiner Elterneinhängung dürfen nicht MS_SHARED sein;
entsprechend falls alte_Wurzel ein bestehender Einhängepunkt ist, darf sein Ausbreitungstyp nicht
MS_SHARED sein. Diese Einschränkungen stellen sicher, dass pivot_root() niemals Änderungen in einen
anderen Einhänge-Namensraum ausbreitet.
• Das aktuelle Wurzelverzeichnis muss ein Einhängepunkt sein.
RÜCKGABEWERT
Bei Erfolg wird Null zurückgegeben. Bei einem Fehler wird -1 zurückgegeben und errno gesetzt, um den
Fehler anzuzeigen.
FEHLER
pivot_root() kann jeden der von stat(2) zurückgegebenen Fehler zurückgeben. Zusätzlich kann Folgendes
zurückgegeben werden:
EBUSY Die neue_Wurzel oder die alte_Wurzel sind in der aktuellen Wurzeleinhängung. (Dieser Fehler deckt
den pathologischen Fall ab, wenn die neue_Wurzel »/« ist.)
EINVAL neue_Wurzel ist kein Einhängepunkt.
EINVAL Die alte_Wurzel ist nicht in oder unterhalb der neuen_Wurzel.
EINVAL Das aktuelle Wurzelverzeichnis ist kein Einhängepunkt (wegen eines früher ausgeführten chroot(2)).
EINVAL Die aktuelle Wurzel ist auf dem Rootfs (anfänglichen Ramfs-)Dateisystem; siehe ANMERKUNGEN.
EINVAL Entweder der Einhängepunkt unter neue_Wurzel oder die Elterneinhängung dieses Einhängepunktes hat
den Ausbreitungstyp MS_SHARED.
EINVAL alte_Wurzel ist ein Einhängepunkt und der Ausbreitungstyp ist MS_SHARED.
ENOTDIR
neue_Wurzel oder alte_Wurzel ist kein Verzeichnis.
EPERM Der aufrufende Prozess verfügt nicht über die CAP_SYS_ADMIN-Capability.
STANDARDS
Linux.
GESCHICHTE
Linux 2.3.41.
ANMERKUNGEN
Eine Befehlszeilenschnittstelle für diesen Systemaufruf wird durch pivot_root(8) bereitgestellt.
pivot_root() ermöglicht dem Aufrufenden, in eine neue Dateisystemwurzel zu wechseln, während gleichzeitig
die alte Einhängewurzel an einem Ort unterhalb der neuen_Wurzel 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.)
Der typische Anwendungsfall von pivot_root() ist während des Systemstarts, wenn das System ein temporäres
Wurzeldateisystem einhängt, zum Beispiel ein initrd(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.
pivot_root() 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.
Das Rootfs (anfängliche Ramfs) kann nicht mittels pivot_root 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, stdin/stdout/stderr an das neue /dev/console anzuhängen und
das neue init(1) auszuführen. Helferprogramme für diesen Prozess existieren: siehe switch_root(8).
pivot_root(".", ".")
Neue_Wurzel und alte_Wurzel 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:
chdir(neue_Wurzel);
pivot_root(".", ".");
umount2(".", MNT_DETACH);
Diese Sequenz ist erfolgreich, weil der Aufruf von pivot_root() den alten Wurzeleinhängepunkt über den
neuen Wurzeleinhängepunkt in / stapelt. An diesem Punkt beziehen sich das Wurzelverzeichnis und das
aktuelle Arbeitsverzeichnis des aufrufenden Prozesses auf den neuen Wurzeleinhängepunkt (neue_Wurzel).
Während des darauf folgenden Aufrufs von umount() beginnt die Auflösung von ».« mit der neue_Wurzel und
wandert dann die Liste der in / gestapelten Einhängungen hinauf, mit dem Ergebnis, dass der alte
Einhängepunkt ausgehängt wird.
Geschichtliche Anmerkungen
Viele Jahre lang enthielt diese Handbuchseite den folgenden Text:
pivot_root() 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 pivot_root() 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 neue_Wurzel, bevor pivot_root() aufgerufen wird.
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.
BEISPIELE
Das untenstehende Programm beschreibt die Verwendung von pivot_root() innerhalb eines
Einhängenamensraums, der mit clone(2) erstellt wurde. Nach dem Umschwenken zu dem im ersten
Befehlszeilenargument des Programms benannten Wurzelverzeichnis führt der mit clone(2) erzeugte
Kindprozess das in den übrigen Befehlszeilenargumenten benannte Programm aus.
Wir demonstrieren das Programm durch Anlegen eines Verzeichnisses, das als das neue Wurzeldateisystem
dient, und Setzen einer (statisch gelinkten) Kopie der ausführbaren Datei busybox(1) in dieses
Verzeichnis.
$ mkdir /tmp/rootfs
$ ls -id /tmp/rootfs # Inode-Anzahl des neuen Wurzelverzeichnisses zeigen
319459 /tmp/rootfs
$ cp $(which busybox) /tmp/rootfs
$ PS1='bbsh$ ' sudo ./pivot_root_demo /tmp/rootfs /busybox sh
bbsh$ PATH=/
bbsh$ busybox ln busybox ln
bbsh$ ln busybox echo
bbsh$ ln busybox ls
bbsh$ ls
busybox echo ln ls
bbsh$ ls -id / # Mit der Inode-Anzahl oben vergleichen
319459 /
bbsh$ echo 'Hallo Welt'
Hallo Welt
Programmquelltext
/* pivot_root_demo.c */
#define _GNU_SOURCE
#include <err.h>
#include <limits.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>
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);
}
SIEHE AUCH
chdir(2), chroot(2), mount(2), stat(2), initrd(4), mount_namespaces(7), pivot_root(8), switch_root(8)
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Mario Blättermann <mario.blaettermann@gmail.com>
und Helge Kreutzmann <debian@helgefjell.de> 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: debian-l10n-german@lists.debian.org.
Linux man-pages 6.9.1 2. Mai 2024 pivot_root(2)