Man page - pivot_root(2)

Packages contains this manual

Available languages:

en fr ja de

Manual

pivot_root

BEZEICHNUNG
BIBLIOTHEK
ÜBERSICHT
BESCHREIBUNG
RÜCKGABEWERT
FEHLER
STANDARDS
GESCHICHTE
ANMERKUNGEN
pivot_root(".", ".")
Geschichtliche Anmerkungen
BEISPIELE
Programmquelltext
SIEHE AUCH
ÜBERSETZUNG

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 .