1PIVOT_ROOT(2) Linux Programmer's Manual PIVOT_ROOT(2)
2
3
4
6 pivot_root - change the root mount
7
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
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
55 On success, zero is returned. On error, -1 is returned, and errno is
56 set to indicate the error.
57
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
86 pivot_root() was introduced in Linux 2.3.41.
87
89 pivot_root() is Linux-specific and hence is not portable.
90
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
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
283 chdir(2), chroot(2), mount(2), stat(2), initrd(4), mount_namespaces(7),
284 pivot_root(8), switch_root(8)
285
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)