pivot_root(2) System Calls Manual pivot_root(2) NOM pivot_root - Modifier le montage racine BIBLIOTHEQUE Bibliotheque C standard (libc, -lc) SYNOPSIS #include /* Definition des constantes SYS_* */ #include int syscall(SYS_pivot_root, const char *new_root, const char *put_old); Note: la glibc ne fournit pas d'enveloppe pour pivot_root(), necessitant l'utilisation de syscall(2). DESCRIPTION pivot_root() modifie le montage racine dans l'espace de noms de montage du processus appelant. Plus precisement, il deplace le montage racine dans le repertoire put_old et il fait de new_root le nouveau montage racine. Le processus appelant doit avoir la capacite CAP_SYS_ADMIN dans l'espace de noms de l'utilisateur a qui appartient l'espace de noms de montage de l'appelant. pivot_root() change le repertoire racine et le repertoire de travail de chaque processus ou de chaque thread du meme espace de noms de montage en new_root s'ils pointent vers l'ancien repertoire de montage (voir aussi les NOTES). D'un autre cote, pivot_root() ne modifie pas le repertoire de travail de l'appelant (sauf s'il est sur l'ancien repertoire racine), ainsi, il doit etre suivi d'un appel chdir("/"). Les restrictions suivantes s'appliquent : - new_root et put_old doivent etre des repertoires. - new_root et put_old ne doivent pas etre sur le meme montage que la racine actuelle. - put_old doit etre sur new_root ou un descendant de new_root : a savoir qu'ajouter un nombre positif de suffixes << /.. >> au chemin vers lequel pointe put_old doit ramener au meme repertoire que new_root. - new_root doit etre un chemin vers un point de montage ; mais il ne peut pas etre << / >>. Un chemin qui n'est pas un point de montage peut le devenir en montant en miroir le point sur lui-meme. - Le type de propagation du montage parent de new_root et le montage parent du repertoire racine actuel ne doivent pas etre MS_SHARED ; de meme, si put_old est un point de montage existant, son type de propagation ne doit pas etre MS_SHARED. Ces restrictions garantissent que pivot_root() ne propage jamais de changement sur un autre espace de noms de montage. - Le repertoire racine actuel doit etre un point de montage. VALEUR RENVOYEE En cas de succes, zero est renvoye. En cas d'erreur, -1 est renvoye et errno est definie pour preciser l'erreur. ERREURS pivot_root() peut echouer avec une des erreurs de stat(2). Il peut aussi echouer avec les erreurs suivantes : EBUSY new_root ou put_old est sur le montage racine actuel (cette erreur vaut pour le cas pathologique ou new_root est << / >>. EINVAL new_root n'est pas un point de montage. EINVAL put_old n'est pas sur new_root ou un descendant. EINVAL Le repertoire racine actuel n'est pas un point de montage (du fait d'un precedent chroot(2)). EINVAL La racine actuelle est sur le montage rootfs (ramfs initial) ; voir les NOTES. EINVAL Soit le point de montage sur new_root, soit le montage parent de ce point de montage, a un type de propagation MS_SHARED. EINVAL put_old est un point de montage et il a le type de propagation MS_SHARED. ENOTDIR new_root ou put_old n'est pas un repertoire. EPERM Le processus appelant n'a pas la capacite CAP_SYS_ADMIN. STANDARDS Linux. HISTORIQUE Linux 2.3.41. NOTES Une interface en ligne de commande pour cet appel systeme est fournie par pivot_root(8). pivot_root() permet a un appelant de passer a un nouveau systeme de fichiers racine tout en mettant l'ancien montage racine dans new_root, d'ou il peut etre demonte (le fait de deplacer tous les processus ayant un repertoire racine ou actuel dans le repertoire racine vers une nouvelle racine libere l'ancienne racine des utilisateurs, permettant de demonter plus facilement l'ancien montage racine). L'utilisation typique de pivot_root() est durant le demarrage du systeme, lorsque le systeme monte un systeme de fichiers temporaire (par exemple un initrd(4)) puis monte le veritable systeme de fichiers et le transforme eventuellement en racine pour tous les processus et threads concernes. Une utilisation moderne consiste a definir un systeme de fichiers racine pendant la creation d'un conteneur. Le fait que pivot_root() modifie les repertoires racine et de travail du processus comme indique dans la DESCRIPTION est necessaire afin d'empecher les threads du noyau d'occuper l'ancien montage racine avec leurs repertoires racine et de travail, meme s'ils n'accedent jamais au systeme de fichiers en aucune maniere. Le rootfs (initial ramfs) ne peut pas etre pivot_root()e. La methode recommandee pour modifier le systeme de fichiers racine dans ce cas consiste a tout effacer sur le rootfs, monter par-dessus la nouvelle racine, rattacher stdin/stdout/stderr au nouveau /dev/console et executer le nouvel init(1). Il existe des programmes d'aide pour ce processus ; voir switch_root(8). pivot_root(".", ".") new_root et put_old peuvent etre le meme repertoire. En particulier, la sequence suivante permet une operation pivot-root sans devoir creer et supprimer un repertoire temporaire : chdir(new_root); pivot_root(".", "."); umount2(".", MNT_DETACH); Cette sequence reussit parce que l'appel pivot_root() place le point de montage racine au sommet du nouveau point de montage racine sur /. Alors, le repertoire racine et celui de travail du processus appelant se rapportent au nouveau point de montage racine (new_root). Lors de l'appel umount() suivant, la resolution de "." commence par new_root puis monte la liste des points de montage empiles dans /, d'ou il resulte que l'ancien point de montage est demonte. Remarques historiques Pendant de nombreuses annees, cette page de manuel comportait le texte suivant : pivot_root() peut changer ou non les repertoires racine et de travail en cours de tous les processus et threads qui utilisaient l'ancien repertoire racine. L'appelant de pivot_root() doit s'assurer que les processus ayant pour racine ou repertoire de travail l'ancien repertoire se comportent correctement. Le meilleur moyen est de modifier leur repertoire de travail et repertoire racine pour new_root avant d'invoquer pivot_root(). Ce texte, ecrit avant meme la finalisation de l'implementation de l'appel systeme dans le noyau, visait sans doute a avertir les utilisateurs a ce moment la que l'implementation pourrait changer avant la publication definitive. Toutefois, le comportement indique dans DESCRIPTION est reste valable depuis la premiere implementation de cet appel systeme et il ne changera pas maintenant. EXEMPLES Le programme ci-dessous montre l'utilisation de pivot_root() dans un espace de noms de montage cree en utilisant clone(2). Apres avoir change le repertoire racine appele dans le premier parametre de la ligne de commande du programme, l'enfant cree par clone(2) execute alors le programme nomme dans les autres parametres de la ligne de commande. Nous montrons le programme en creant un repertoire qui servira de nouveau systeme de fichiers racine et en mettant une copie de l'executable busybox(1) (liee statiquement) dans ce repertoire. $ mkdir /tmp/rootfs $ ls -id /tmp/rootfs # Numero d'inoeud dans le nouveau repertoire racine 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 / # Comparaison avec le numero d'inoeud au-dessus 319459 / bbsh$ echo 'hello world' hello world Source du programme /* 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 /* Fonction de demarrage pour l'enfant clone */ child(void *arg) { char path[PATH_MAX]; char **args = arg; char *new_root = args[0]; const char *put_old = "/oldrootfs"; /* S'assurer que 'new_root' et son point de montage parent n'aient pas une propagation partagee (ce qui ferait renvoyer une erreur a pivot_root()) et empecher la propagation des evenements de montage dans l'espace de noms de montage initial. */ if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) == -1) err(EXIT_FAILURE, "mount-MS_PRIVATE"); /* S'assurer que 'new_root' soit un point de montage. */ if (mount(new_root, new_root, NULL, MS_BIND, NULL) == -1) err(EXIT_FAILURE, "mount-MS_BIND"); /* Creer le repertoire ou l'ancienne racine sera envoyee. */ snprintf(path, sizeof(path), "%s/%s", new_root, put_old); if (mkdir(path, 0777) == -1) err(EXIT_FAILURE, "mkdir"); /* Et changer de systeme de fichiers racine. */ if (pivot_root(new_root, path) == -1) err(EXIT_FAILURE, "pivot_root"); /* Deplacer le repertoire de travail dans "/". */ if (chdir("/") == -1) err(EXIT_FAILURE, "chdir"); /* Demonter l'ancienne racine et supprimer le point de montage. */ if (umount2(put_old, MNT_DETACH) == -1) perror("umount2"); if (rmdir(put_old) == -1) perror("rmdir"); /* Executer la commande indiquee dans argv[1]... */ execv(args[1], &args[1]); err(EXIT_FAILURE, "execv"); } int main(int argc, char *argv[]) { char *stack; /* Creer un processus enfant dans un nouvel espace de noms de montage. */ 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"); /* Le parent arrive ici ; attendre l'enfant. */ if (wait(NULL) == -1) err(EXIT_FAILURE, "wait"); exit(EXIT_SUCCESS); } VOIR AUSSI chdir(2), chroot(2), mount(2), stat(2), initrd(4), mount_namespaces(7), pivot_root(8), switch_root(8) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot et Jean-Philippe MENGUAL Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 31 octobre 2023 pivot_root(2)