oracular (2) pivot_root.2.gz

Provided by: manpages-de-dev_4.23.1-1_all bug

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
       ⟨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⟩.