pivot_root.2: 'new_root' must be a mount point

It appears that 'new_root' may not have needed to be a mount
point on ancient kernels, but already in Linux 2.4.5, there
was the diff shown below. Verified also by testing.

@@ -1631,8 +1605,9 @@
  *  - we don't move root/cwd if they are not at the root (reason: if something
  *    cared enough to change them, it's probably wrong to force them elsewhere)
  *  - it's okay to pick a root that isn't the root of a file system, e.g.
- *    /nfs/my_root where /nfs is the mount point. Better avoid creating
- *    unreachable mount points this way, though.
+ *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
+ *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
+ *    first.
  */

 asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
@@ -1640,7 +1615,7 @@
        struct dentry *root;
        struct vfsmount *root_mnt;
        struct vfsmount *tmp;
-       struct nameidata new_nd, old_nd;
+       struct nameidata new_nd, old_nd, parent_nd, root_parent;
        char *name;
        int error;

@@ -1688,6 +1663,10 @@
        if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
                goto out2; /* loop */
        error = -EINVAL;
+       if (root_mnt->mnt_root != root)
+               goto out2;
+       if (new_nd.mnt->mnt_root != new_nd.dentry)
+               goto out2; /* not a mountpoint */
        tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
        spin_lock(&dcache_lock);
        if (tmp != new_nd.mnt) {

Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
Michael Kerrisk 2019-07-26 16:54:16 +02:00
parent dc95a3a39f
commit 37704bfc8f
1 changed files with 9 additions and 4 deletions

View File

@ -91,10 +91,11 @@ or
see also below), not the old root directory, but the
mount point of that filesystem is mounted on \fIput_old\fP.
.PP
\fInew_root\fP does not have to be a mount point.
In this case,
\fI/proc/mounts\fP will show the mount point of the filesystem containing
\fInew_root\fP as root (\fI/\fP).
.I new_root
must be a mount point.
(If it is not otherwise a mount point, it suffices to bind mount
.I new_root
on top of itself.)
.SH RETURN VALUE
On success, zero is returned.
On error, \-1 is returned, and
@ -110,6 +111,10 @@ Additionally, it may return:
or a filesystem is already mounted on \fIput_old\fP.
.TP
.B EINVAL
.I new_root
is not a mount point.
.TP
.B EINVAL
\fIput_old\fP is not underneath \fInew_root\fP.
.TP
.B EINVAL