]> git.ipfire.org Git - thirdparty/man-pages.git/commitdiff
pivot_root.2: pivot_root(".", ".") really is a thing
authorMichael Kerrisk <mtk.manpages@gmail.com>
Wed, 31 Jul 2019 21:51:39 +0000 (23:51 +0200)
committerMichael Kerrisk <mtk.manpages@gmail.com>
Mon, 23 Sep 2019 11:11:19 +0000 (13:11 +0200)
LXC uses this [1]. I tested, to double-check, and it works.

The fchdir() dance done by LXC is not needed though:

fchdir(old_root); umount(".", MNT_DETACH); fchdir(new_root);

As far as I can see, just the umount() is sufficient, since,
after pivot_root(), oldi_root is at the top of the stack
of mounts at "/" and thus (so long as CWD is at "/")
the umount will remove the mount at the top of the stack.
Eric Biederman confirmed my understanding by mail, and
Philipp Wendler verified my results by experiment.

[1] See the following commit in LXC:

    commit 2d489f9e87fa0cccd8a1762680a43eeff2fe1b6e
    Author: Serge Hallyn <serge.hallyn@ubuntu.com>
    Date:   Sat Sep 20 03:15:44 2014 +0000

        pivot_root: switch to a new mechanism (v2)

Helped-by: Eric W. Biederman <ebiederm@xmission.com>
Helped-by: Philipp Wendler <ml@philippwendler.de>
Helped-by: Aleksa Sarai <asarai@suse.de>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
man2/pivot_root.2

index a2099144aadd924d4a102b1462dfeed899fc71b3..3cca8a30dd047d6b4ec06a70a801377760a27c68 100644 (file)
@@ -80,7 +80,8 @@ can't be
 .IR """/"""
 (but can be a bind mounted directory on the current root filesystem).
 .IP \-
-\fIput_old\fP must be underneath \fInew_root\fP, that is, adding a nonzero
+\fIput_old\fP must be at or underneath \fInew_root\fP;
+that is, adding a nonnegative
 number of \fI/..\fP to the string pointed to by \fIput_old\fP must yield
 the same directory as \fInew_root\fP.
 .IP \-
@@ -209,6 +210,42 @@ root directory busy with their root and current working directory,
 even if they never access
 the filesystem in any way.
 .PP
+.I new_root
+and
+.I put_old
+may be the same directory.
+In particular, the following sequence allows a pivot-root operation
+without needing to create and remove a temporary directory:
+.PP
+.in +4n
+.EX
+chdir(new_root);
+pivot_root(".", ".");
+umount2(".", MNT_DETACH);
+.EE
+.in
+.PP
+This sequence succeeds because the
+.BR pivot_root ()
+call stacks the old root mount point
+.RI ( old_root )
+on top of the new root mount point at
+.IR / .
+At that point, the calling process's root directory and current
+working directory refer to the new root mount point
+.RI ( new_root ).
+During the subsequent
+.BR umount ()
+call, resolution of
+.IR """."""
+starts with
+.I new_root
+and then moves up the list of mounts stacked at
+.IR / ,
+with the result that
+.IR old_root
+is unmounted.
+.PP
 The rootfs (initial ramfs) cannot be
 .BR pivot_root ()ed.
 The recommended method of changing the root filesystem in this case is