From 57bab66a921dbbb36839935b4c17c6e01039cc84 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Wed, 31 Jul 2019 23:51:39 +0200 Subject: [PATCH] pivot_root.2: pivot_root(".", ".") really is a thing 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 Date: Sat Sep 20 03:15:44 2014 +0000 pivot_root: switch to a new mechanism (v2) Helped-by: Eric W. Biederman Helped-by: Philipp Wendler Helped-by: Aleksa Sarai Signed-off-by: Michael Kerrisk --- man2/pivot_root.2 | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/man2/pivot_root.2 b/man2/pivot_root.2 index a2099144aa..3cca8a30dd 100644 --- a/man2/pivot_root.2 +++ b/man2/pivot_root.2 @@ -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 -- 2.39.5