share/mk/: Fix includes
[man-pages.git] / man2 / pivot_root.2
blob9cb5d9b2582bab84c620baba9036c1664614772b
1 .\" Copyright (C) 2019 Michael Kerrisk <mtk.manpages@gmail.com>
2 .\" A very few fragments remain from an earlier page written by
3 .\" Werner Almesberger in 2000
4 .\"
5 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
6 .\"
7 .TH pivot_root 2 (date) "Linux man-pages (unreleased)"
8 .SH NAME
9 pivot_root \- change the root mount
10 .SH LIBRARY
11 Standard C library
12 .RI ( libc ", " \-lc )
13 .SH SYNOPSIS
14 .nf
15 .BR "#include <sys/syscall.h>" "      /* Definition of " SYS_* " constants */"
16 .B #include <unistd.h>
18 .BI "int syscall(SYS_pivot_root, const char *" new_root \
19 ", const char *" put_old );
20 .fi
22 .IR Note :
23 glibc provides no wrapper for
24 .BR pivot_root (),
25 necessitating the use of
26 .BR syscall (2).
27 .SH DESCRIPTION
28 .BR pivot_root ()
29 changes the root mount in the mount namespace of the calling process.
30 More precisely, it moves the root mount to the
31 directory \fIput_old\fP and makes \fInew_root\fP the new root mount.
32 The calling process must have the
33 .B CAP_SYS_ADMIN
34 capability in the user namespace that owns the caller's mount namespace.
36 .BR pivot_root ()
37 changes the root directory and the current working directory
38 of each process or thread in the same mount namespace to
39 .I new_root
40 if they point to the old root directory.
41 (See also NOTES.)
42 On the other hand,
43 .BR pivot_root ()
44 does not change the caller's current working directory
45 (unless it is on the old root directory),
46 and thus it should be followed by a
47 \fBchdir("/")\fP call.
49 The following restrictions apply:
50 .IP \[bu] 3
51 .I new_root
52 and
53 .I put_old
54 must be directories.
55 .IP \[bu]
56 .I new_root
57 and
58 .I put_old
59 must not be on the same mount as the current root.
60 .IP \[bu]
61 \fIput_old\fP must be at or underneath \fInew_root\fP;
62 that is, adding some nonnegative
63 number of "\fI/..\fP" suffixes to the pathname pointed to by
64 .I put_old
65 must yield the same directory as \fInew_root\fP.
66 .IP \[bu]
67 .I new_root
68 must be a path to a mount point, but can't be
69 .IR \[dq]/\[dq] .
70 A path that is not already a mount point can be converted into one by
71 bind mounting the path onto itself.
72 .IP \[bu]
73 The propagation type of the parent mount of
74 .I new_root
75 and the parent mount of the current root directory must not be
76 .BR MS_SHARED ;
77 similarly, if
78 .I put_old
79 is an existing mount point, its propagation type must not be
80 .BR MS_SHARED .
81 These restrictions ensure that
82 .BR pivot_root ()
83 never propagates any changes to another mount namespace.
84 .IP \[bu]
85 The current root directory must be a mount point.
86 .SH RETURN VALUE
87 On success, zero is returned.
88 On error, \-1 is returned, and
89 \fIerrno\fP is set to indicate the error.
90 .SH ERRORS
91 .BR pivot_root ()
92 may fail with any of the same errors as
93 .BR stat (2).
94 Additionally, it may fail with the following errors:
95 .TP
96 .B EBUSY
97 .\" Reconfirmed that the following error occurs on Linux 5.0 by
98 .\" specifying 'new_root' as "/rootfs" and 'put_old' as
99 .\" "/rootfs/oldrootfs", and *not* bind mounting "/rootfs" on top of
100 .\" itself. Of course, this is an odd situation, since a later check
101 .\" in the kernel code will in any case yield EINVAL if 'new_root' is
102 .\" not a mount point. However, when the system call was first added,
103 .\" 'new_root' was not required to be a mount point. So, this
104 .\" error is nowadays probably just the result of crufty accumulation.
105 .\" This error can also occur if we bind mount "/" on top of itself
106 .\" and try to specify "/" as the 'new' (again, an odd situation). So,
107 .\" the EBUSY check in the kernel does still seem necessary to prevent
108 .\" that case.  Furthermore, the "or put_old" piece is probably
109 .\" redundant text (although the check is in the kernel), since,
110 .\" in another check, 'put_old' is required to be under 'new_root'.
111 .I new_root
113 .I put_old
114 is on the current root mount.
115 (This error covers the pathological case where
116 .I new_root
118 .IR \[dq]/\[dq] .)
120 .B EINVAL
121 .I new_root
122 is not a mount point.
124 .B EINVAL
125 \fIput_old\fP is not at or underneath \fInew_root\fP.
127 .B EINVAL
128 The current root directory is not a mount point
129 (because of an earlier
130 .BR chroot (2)).
132 .B EINVAL
133 The current root is on the rootfs (initial ramfs) mount; see NOTES.
135 .B EINVAL
136 Either the mount point at
137 .IR new_root ,
138 or the parent mount of that mount point,
139 has propagation type
140 .BR MS_SHARED .
142 .B EINVAL
143 .I put_old
144 is a mount point and has the propagation type
145 .BR MS_SHARED .
147 .B ENOTDIR
148 \fInew_root\fP or \fIput_old\fP is not a directory.
150 .B EPERM
151 The calling process does not have the
152 .B CAP_SYS_ADMIN
153 capability.
154 .SH STANDARDS
155 Linux.
156 .SH HISTORY
157 Linux 2.3.41.
158 .SH NOTES
159 A command-line interface for this system call is provided by
160 .BR pivot_root (8).
162 .BR pivot_root ()
163 allows the caller to switch to a new root filesystem while at the same time
164 placing the old root mount at a location under
165 .I new_root
166 from where it can subsequently be unmounted.
167 (The fact that it moves all processes that have a root directory
168 or current working directory on the old root directory to the
169 new root frees the old root directory of users,
170 allowing the old root mount to be unmounted more easily.)
172 One use of
173 .BR pivot_root ()
174 is during system startup, when the
175 system mounts a temporary root filesystem (e.g., an
176 .BR initrd (4)),
177 then mounts the real root filesystem, and eventually turns the latter into
178 the root directory of all relevant processes and threads.
179 A modern use is to set up a root filesystem during
180 the creation of a container.
182 The fact that
183 .BR pivot_root ()
184 modifies process root and current working directories in the
185 manner noted in DESCRIPTION
186 is necessary in order to prevent kernel threads from keeping the old
187 root mount busy with their root and current working directories,
188 even if they never access
189 the filesystem in any way.
191 The rootfs (initial ramfs) cannot be
192 .BR pivot_root ()ed.
193 The recommended method of changing the root filesystem in this case is
194 to delete everything in rootfs, overmount rootfs with the new root, attach
195 .IR stdin / stdout / stderr
196 to the new
197 .IR /dev/console ,
198 and exec the new
199 .BR init (1).
200 Helper programs for this process exist; see
201 .BR switch_root (8).
203 .SS pivot_root(\[dq].\[dq], \[dq].\[dq])
204 .I new_root
206 .I put_old
207 may be the same directory.
208 In particular, the following sequence allows a pivot-root operation
209 without needing to create and remove a temporary directory:
211 .in +4n
213 chdir(new_root);
214 pivot_root(".", ".");
215 umount2(".", MNT_DETACH);
219 This sequence succeeds because the
220 .BR pivot_root ()
221 call stacks the old root mount point
222 on top of the new root mount point at
223 .IR / .
224 At that point, the calling process's root directory and current
225 working directory refer to the new root mount point
226 .RI ( new_root ).
227 During the subsequent
228 .BR umount ()
229 call, resolution of
230 .I \[dq].\[dq]
231 starts with
232 .I new_root
233 and then moves up the list of mounts stacked at
234 .IR / ,
235 with the result that old root mount point is unmounted.
237 .SS Historical notes
238 For many years, this manual page carried the following text:
241 .BR pivot_root ()
242 may or may not change the current root and the current
243 working directory of any processes or threads which use the old
244 root directory.
245 The caller of
246 .BR pivot_root ()
247 must ensure that processes with root or current working directory
248 at the old root operate correctly in either case.
249 An easy way to ensure this is to change their
250 root and current working directory to \fInew_root\fP before invoking
251 .BR pivot_root ().
254 This text, written before the system call implementation was
255 even finalized in the kernel, was probably intended to warn users
256 at that time that the implementation might change before final release.
257 However, the behavior stated in DESCRIPTION
258 has remained consistent since this system call
259 was first implemented and will not change now.
260 .SH EXAMPLES
261 .\" FIXME
262 .\" Would it be better, because simpler, to use unshare(2)
263 .\" rather than clone(2) in the example below?
264 The program below demonstrates the use of
265 .BR pivot_root ()
266 inside a mount namespace that is created using
267 .BR clone (2).
268 After pivoting to the root directory named in the program's
269 first command-line argument, the child created by
270 .BR clone (2)
271 then executes the program named in the remaining command-line arguments.
273 We demonstrate the program by creating a directory that will serve as
274 the new root filesystem and placing a copy of the (statically linked)
275 .BR busybox (1)
276 executable in that directory.
278 .in +4n
280 $ \fBmkdir /tmp/rootfs\fP
281 $ \fBls \-id /tmp/rootfs\fP    # Show inode number of new root directory
282 319459 /tmp/rootfs
283 $ \fBcp $(which busybox) /tmp/rootfs\fP
284 $ \fBPS1=\[aq]bbsh$ \[aq] sudo ./pivot_root_demo /tmp/rootfs /busybox sh\fP
285 bbsh$ \fBPATH=/\fP
286 bbsh$ \fBbusybox ln busybox ln\fP
287 bbsh$ \fBln busybox echo\fP
288 bbsh$ \fBln busybox ls\fP
289 bbsh$ \fBls\fP
290 busybox  echo     ln       ls
291 bbsh$ \fBls \-id /\fP          # Compare with inode number above
292 319459 /
293 bbsh$ \fBecho \[aq]hello world\[aq]\fP
294 hello world
297 .SS Program source
300 .\" SRC BEGIN (pivot_root.c)
302 /* pivot_root_demo.c */
304 #define _GNU_SOURCE
305 #include <err.h>
306 #include <limits.h>
307 #include <sched.h>
308 #include <signal.h>
309 #include <stdio.h>
310 #include <stdlib.h>
311 #include <sys/mman.h>
312 #include <sys/mount.h>
313 #include <sys/stat.h>
314 #include <sys/syscall.h>
315 #include <sys/wait.h>
316 #include <unistd.h>
318 static int
319 pivot_root(const char *new_root, const char *put_old)
321     return syscall(SYS_pivot_root, new_root, put_old);
324 #define STACK_SIZE (1024 * 1024)
326 static int              /* Startup function for cloned child */
327 child(void *arg)
329     char        path[PATH_MAX];
330     char        **args = arg;
331     char        *new_root = args[0];
332     const char  *put_old = "/oldrootfs";
334     /* Ensure that \[aq]new_root\[aq] and its parent mount don\[aq]t have
335        shared propagation (which would cause pivot_root() to
336        return an error), and prevent propagation of mount
337        events to the initial mount namespace. */
339     if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) == \-1)
340         err(EXIT_FAILURE, "mount\-MS_PRIVATE");
342     /* Ensure that \[aq]new_root\[aq] is a mount point. */
344     if (mount(new_root, new_root, NULL, MS_BIND, NULL) == \-1)
345         err(EXIT_FAILURE, "mount\-MS_BIND");
347     /* Create directory to which old root will be pivoted. */
349     snprintf(path, sizeof(path), "%s/%s", new_root, put_old);
350     if (mkdir(path, 0777) == \-1)
351         err(EXIT_FAILURE, "mkdir");
353     /* And pivot the root filesystem. */
355     if (pivot_root(new_root, path) == \-1)
356         err(EXIT_FAILURE, "pivot_root");
358     /* Switch the current working directory to "/". */
360     if (chdir("/") == \-1)
361         err(EXIT_FAILURE, "chdir");
363     /* Unmount old root and remove mount point. */
365     if (umount2(put_old, MNT_DETACH) == \-1)
366         perror("umount2");
367     if (rmdir(put_old) == \-1)
368         perror("rmdir");
370     /* Execute the command specified in argv[1]... */
372     execv(args[1], &args[1]);
373     err(EXIT_FAILURE, "execv");
377 main(int argc, char *argv[])
379     char *stack;
381     /* Create a child process in a new mount namespace. */
383     stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
384                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, \-1, 0);
385     if (stack == MAP_FAILED)
386         err(EXIT_FAILURE, "mmap");
388     if (clone(child, stack + STACK_SIZE,
389               CLONE_NEWNS | SIGCHLD, &argv[1]) == \-1)
390         err(EXIT_FAILURE, "clone");
392     /* Parent falls through to here; wait for child. */
394     if (wait(NULL) == \-1)
395         err(EXIT_FAILURE, "wait");
397     exit(EXIT_SUCCESS);
400 .\" SRC END
401 .SH SEE ALSO
402 .BR chdir (2),
403 .BR chroot (2),
404 .BR mount (2),
405 .BR stat (2),
406 .BR initrd (4),
407 .BR mount_namespaces (7),
408 .BR pivot_root (8),
409 .BR switch_root (8)