Provided by: manpages-de-dev_4.15.0-9_all bug

BEZEICHNUNG

       pivot_root - die Wurzeleinhängung ändern

Ü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.

VERSIONEN

       pivot_root() wurde in Linux 2.3.41 eingeführt.

KONFORM ZU

       pivot_root() ist Linux-spezifisch und daher nicht portierbar.

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 <sched.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <sys/wait.h>
       #include <sys/syscall.h>
       #include <sys/mount.h>
       #include <sys/stat.h>
       #include <limits.h>
       #include <sys/mman.h>

       #define errExit(Nachricht)    do { perror(Nachricht); exit(EXIT_FAILURE); \
                               } while (0)

       static int
       pivot_root(const char *neue_Wurzel, const char *alte_Wurzel)
       {
           return syscall(SYS_pivot_root, neue_Wurzel, alte_Wurzel);
       }

       #define STACK_SIZE (1024 * 1024)

       static int              /* Startfunktion für geklontes Kind */
       child(void *arg)
       {
           char **args = arg;
           char *neue_Wurzel = args[0];
           const char *alte_Wurzel = "/altes_Wurzeldateisystem";
           char path[PATH_MAX];

           /* 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)
               errExit("mount-MS_PRIVATE");

           /* Sicherstellen, dass 'neue_Wurzel' ein Einhängepunkt ist. */

           if (mount(neue_Wurzel, neue_Wurzel, NULL, MS_BIND, NULL) == -1)
               errExit("mount-MS_BIND");

           /* Ein Verzeichnis anlegen, zu dem die alte Wurzel hin umgeschwenkt wird. */

           snprintf(path, sizeof(path), "%s/%s", neue_Wurzel, alte_Wurzel);
           if (mkdir(path, 0777) == -1)
               errExit("mkdir");

           /* Und das Wurzeldateisystem umschwenken. */

           if (pivot_root(neue_Wurzel, Pfad) == -1)
               errExit("pivot_root");

           /* Das aktuelle Arbeitsverzeichnis auf »/« ändern. */

           if (chdir("/") == -1)
               errExit("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]);
           errExit("execv");
       }

       int
       main(int argc, char *argv[])
       {
           /* Einen Kindprozess in einem neuen Einhängenamensraum erzeugen. */

           char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
                              MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
           if (stack == MAP_FAILED)
               errExit("mmap");

           if (clone(child, stack + STACK_SIZE,
                       CLONE_NEWNS | SIGCHLD, &argv[1]) == -1)
               errExit("clone");

           /* Elternprozess fällt bis hierher durch; wartet auf Kindprozess. */

           if (wait(NULL) == -1)
               errExit("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)

KOLOPHON

       Diese  Seite  ist  Teil  der  Veröffentlichung  5.13  des  Projekts  Linux-man-pages. Eine
       Beschreibung des Projekts, Informationen, wie Fehler  gemeldet  werden  können  sowie  die
       aktuelle Version dieser Seite finden sich unter https://www.kernel.org/doc/man-pages/.

Ü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 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ 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⟩.