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

NAME

6       pivot_root - change the root mount
7

SYNOPSIS

9       #include <sys/syscall.h>      /* Definition of SYS_* constants */
10       #include <unistd.h>
11
12       int syscall(SYS_pivot_root, const char *new_root, const char *put_old);
13
14       Note: glibc provides no wrapper for pivot_root(), necessitating the use
15       of syscall(2).
16

DESCRIPTION

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

RETURN VALUE

55       On success, zero is returned.  On error, -1 is returned, and  errno  is
56       set to indicate the error.
57

ERRORS

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

VERSIONS

86       pivot_root() was introduced in Linux 2.3.41.
87

CONFORMING TO

89       pivot_root() is Linux-specific and hence is not portable.
90

NOTES

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

EXAMPLES

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

SEE ALSO

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

COLOPHON

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