1PIVOT_ROOT(2)              Linux Programmer's Manual             PIVOT_ROOT(2)
2
3
4

NAME

6       pivot_root - change the root mount
7

SYNOPSIS

9       int pivot_root(const char *new_root, const char *put_old);
10
11       Note: There is no glibc wrapper for this system call; see NOTES.
12

DESCRIPTION

14       pivot_root() changes the root mount in the mount namespace of the call‐
15       ing process.  More precisely, it moves the root mount to the  directory
16       put_old  and  makes  new_root  the new root mount.  The calling process
17       must have the CAP_SYS_ADMIN capability in the user namespace that  owns
18       the caller's mount namespace.
19
20       pivot_root()  changes the root directory and the current working direc‐
21       tory of each process or thread in the same mount namespace to  new_root
22       if  they  point  to  the old root directory.  (See also NOTES.)  On the
23       other hand, pivot_root() does not change the caller's  current  working
24       directory  (unless it is on the old root directory), and thus it should
25       be followed by a chdir("/") call.
26
27       The following restrictions apply:
28
29       -  new_root and put_old must be directories.
30
31       -  new_root and put_old must not be on the same mount  as  the  current
32          root.
33
34       -  put_old must be at or underneath new_root; that is, adding some non‐
35          negative number of "/.." prefixes to  the  pathname  pointed  to  by
36          put_old must yield the same directory as new_root.
37
38       -  new_root  must be a path to a mount point, but can't be "/".  A path
39          that is not already a mount point can be converted into one by  bind
40          mounting the path onto itself.
41
42       -  The  propagation type of the parent mount of new_root and the parent
43          mount of the current root directory must  not  be  MS_SHARED;  simi‐
44          larly,  if  put_old is an existing mount point, its propagation type
45          must not be MS_SHARED.  These restrictions ensure that  pivot_root()
46          never propagates any changes to another mount namespace.
47
48       -  The current root directory must be a mount point.
49

RETURN VALUE

51       On  success,  zero is returned.  On error, -1 is returned, and errno is
52       set appropriately.
53

ERRORS

55       pivot_root() may fail with any of the same errors  as  stat(2).   Addi‐
56       tionally, it may fail with the following errors:
57
58       EBUSY  new_root  or  put_old is on the current root mount.  (This error
59              covers the pathological case where new_root is "/".)
60
61       EINVAL new_root is not a mount point.
62
63       EINVAL put_old is not at or underneath new_root.
64
65       EINVAL The current root directory is not a mount point (because  of  an
66              earlier chroot(2)).
67
68       EINVAL The  current  root  is  on the rootfs (initial ramfs) mount; see
69              NOTES.
70
71       EINVAL Either the mount point at new_root, or the parent mount of  that
72              mount point, has propagation type MS_SHARED.
73
74       EINVAL put_old is a mount point and has the propagation type MS_SHARED.
75
76       ENOTDIR
77              new_root or put_old is not a directory.
78
79       EPERM  The calling process does not have the CAP_SYS_ADMIN capability.
80

VERSIONS

82       pivot_root() was introduced in Linux 2.3.41.
83

CONFORMING TO

85       pivot_root() is Linux-specific and hence is not portable.
86

NOTES

88       Glibc  does  not  provide a wrapper for this system call; call it using
89       syscall(2).
90
91       A  command-line  interface  for  this  system  call  is   provided   by
92       pivot_root(8).
93
94       pivot_root() allows the caller to switch to a new root filesystem while
95       at the same time placing  the  old  root  mount  at  a  location  under
96       new_root  from  where it can subsequently be unmounted.  (The fact that
97       it moves all processes that have a root directory  or  current  working
98       directory  on the old root directory to the new root frees the old root
99       directory of users, allowing the old root mount to  be  unmounted  more
100       easily.)
101
102       One  use  of  pivot_root()  is  during  system startup, when the system
103       mounts a temporary root filesystem (e.g., an  initrd(4)),  then  mounts
104       the real root filesystem, and eventually turns the latter into the root
105       directory of all relevant processes and threads.  A modern  use  is  to
106       set up a root filesystem during the creation of a container.
107
108       The  fact  that  pivot_root() modifies process root and current working
109       directories in the manner noted in DESCRIPTION is necessary in order to
110       prevent  kernel threads from keeping the old root mount busy with their
111       root and current working directories, even if  they  never  access  the
112       filesystem in any way.
113
114       The  rootfs  (initial ramfs) cannot be pivot_root()ed.  The recommended
115       method of changing the root filesystem in this case is to delete every‐
116       thing  in rootfs, overmount rootfs with the new root, attach stdin/std‐
117       out/stderr to the new /dev/console, and exec the new  init(1).   Helper
118       programs for this process exist; see switch_root(8).
119
120   pivot_root(".", ".")
121       new_root  and  put_old  may  be the same directory.  In particular, the
122       following sequence allows a pivot-root  operation  without  needing  to
123       create and remove a temporary directory:
124
125           chdir(new_root);
126           pivot_root(".", ".");
127           umount2(".", MNT_DETACH);
128
129       This  sequence  succeeds  because  the pivot_root() call stacks the old
130       root mount point on top of the new root mount  point  at  /.   At  that
131       point,  the calling process's root directory and current working direc‐
132       tory refer to the new root mount point (new_root).  During  the  subse‐
133       quent  umount()  call, resolution of "."  starts with new_root and then
134       moves up the list of mounts stacked at /, with the result that old root
135       mount point is unmounted.
136
137   Historical notes
138       For many years, this manual page carried the following text:
139
140              pivot_root() may or may not change the current root and the cur‐
141              rent working directory of any processes or threads which use the
142              old root directory.  The caller of pivot_root() must ensure that
143              processes with root or current working directory at the old root
144              operate correctly in either case.  An easy way to ensure this is
145              to change their root and current working directory  to  new_root
146              before invoking pivot_root().
147
148       This  text,  written  before  the  system  call implementation was even
149       finalized in the kernel, was probably intended to warn  users  at  that
150       time  that  the implementation might change before final release.  How‐
151       ever, the behavior stated in DESCRIPTION has remained consistent  since
152       this system call was first implemented and will not change now.
153

EXAMPLES

155       The  program  below demonstrates the use of pivot_root() inside a mount
156       namespace that is created using clone(2).  After pivoting to  the  root
157       directory named in the program's first command-line argument, the child
158       created by clone(2) then executes the program named  in  the  remaining
159       command-line arguments.
160
161       We  demonstrate  the program by creating a directory that will serve as
162       the new root filesystem and placing a copy of the  (statically  linked)
163       busybox(1) executable in that directory.
164
165           $ mkdir /tmp/rootfs
166           $ ls -id /tmp/rootfs    # Show inode number of new root directory
167           319459 /tmp/rootfs
168           $ cp $(which busybox) /tmp/rootfs
169           $ PS1='bbsh$ ' sudo ./pivot_root_demo /tmp/rootfs /busybox sh
170           bbsh$ PATH=/
171           bbsh$ busybox ln busybox ln
172           bbsh$ ln busybox echo
173           bbsh$ ln busybox ls
174           bbsh$ ls
175           busybox  echo     ln       ls
176           bbsh$ ls -id /          # Compare with inode number above
177           319459 /
178           bbsh$ echo 'hello world'
179           hello world
180
181   Program source
182
183
184       /* pivot_root_demo.c */
185
186       #define _GNU_SOURCE
187       #include <sched.h>
188       #include <stdio.h>
189       #include <stdlib.h>
190       #include <unistd.h>
191       #include <sys/wait.h>
192       #include <sys/syscall.h>
193       #include <sys/mount.h>
194       #include <sys/stat.h>
195       #include <limits.h>
196       #include <sys/mman.h>
197
198       #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
199                               } while (0)
200
201       static int
202       pivot_root(const char *new_root, const char *put_old)
203       {
204           return syscall(SYS_pivot_root, new_root, put_old);
205       }
206
207       #define STACK_SIZE (1024 * 1024)
208
209       static int              /* Startup function for cloned child */
210       child(void *arg)
211       {
212           char **args = arg;
213           char *new_root = args[0];
214           const char *put_old = "/oldrootfs";
215           char path[PATH_MAX];
216
217           /* Ensure that 'new_root' and its parent mount don't have
218              shared propagation (which would cause pivot_root() to
219              return an error), and prevent propagation of mount
220              events to the initial mount namespace */
221
222           if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) == 1)
223               errExit("mount-MS_PRIVATE");
224
225           /* Ensure that 'new_root' is a mount point */
226
227           if (mount(new_root, new_root, NULL, MS_BIND, NULL) == -1)
228               errExit("mount-MS_BIND");
229
230           /* Create directory to which old root will be pivoted */
231
232           snprintf(path, sizeof(path), "%s/%s", new_root, put_old);
233           if (mkdir(path, 0777) == -1)
234               errExit("mkdir");
235
236           /* And pivot the root filesystem */
237
238           if (pivot_root(new_root, path) == -1)
239               errExit("pivot_root");
240
241           /* Switch the current working directory to "/" */
242
243           if (chdir("/") == -1)
244               errExit("chdir");
245
246           /* Unmount old root and remove mount point */
247
248           if (umount2(put_old, MNT_DETACH) == -1)
249               perror("umount2");
250           if (rmdir(put_old) == -1)
251               perror("rmdir");
252
253           /* Execute the command specified in argv[1]... */
254
255           execv(args[1], &args[1]);
256           errExit("execv");
257       }
258
259       int
260       main(int argc, char *argv[])
261       {
262           /* Create a child process in a new mount namespace */
263
264           char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
265                              MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
266           if (stack == MAP_FAILED)
267               errExit("mmap");
268
269           if (clone(child, stack + STACK_SIZE,
270                       CLONE_NEWNS | SIGCHLD, &argv[1]) == -1)
271               errExit("clone");
272
273           /* Parent falls through to here; wait for child */
274
275           if (wait(NULL) == -1)
276               errExit("wait");
277
278           exit(EXIT_SUCCESS);
279       }
280

SEE ALSO

282       chdir(2), chroot(2), mount(2), stat(2), initrd(4), mount_namespaces(7),
283       pivot_root(8), switch_root(8)
284

COLOPHON

286       This page is part of release 5.07 of the Linux  man-pages  project.   A
287       description  of  the project, information about reporting bugs, and the
288       latest    version    of    this    page,    can     be     found     at
289       https://www.kernel.org/doc/man-pages/.
290
291
292
293Linux                             2020-06-09                     PIVOT_ROOT(2)
Impressum