]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
vfs: move_mount: reject moving kernel internal mounts
authorEric Biggers <ebiggers@google.com>
Sat, 29 Jun 2019 20:27:44 +0000 (13:27 -0700)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 1 Jul 2019 14:46:36 +0000 (10:46 -0400)
sys_move_mount() crashes by dereferencing the pointer MNT_NS_INTERNAL,
a.k.a. ERR_PTR(-EINVAL), if the old mount is specified by fd for a
kernel object with an internal mount, such as a pipe or memfd.

Fix it by checking for this case and returning -EINVAL.

[AV: what we want is is_mounted(); use that instead of making the
condition even more convoluted]

Reproducer:

    #include <unistd.h>

    #define __NR_move_mount         429
    #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004

    int main()
    {
     int fds[2];

     pipe(fds);
        syscall(__NR_move_mount, fds[0], "", -1, "/", MOVE_MOUNT_F_EMPTY_PATH);
    }

Reported-by: syzbot+6004acbaa1893ad013f0@syzkaller.appspotmail.com
Fixes: 2db154b3ea8e ("vfs: syscall: Add move_mount(2) to move mounts around")
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namespace.c

index 7660c2749c96f075c721b701e0ee4839fe62cb82..6fbc9126367a1cf6db621faa575fd709e114002b 100644 (file)
@@ -2596,11 +2596,12 @@ static int do_move_mount(struct path *old_path, struct path *new_path)
        if (!check_mnt(p))
                goto out;
 
-       /* The thing moved should be either ours or completely unattached. */
-       if (attached && !check_mnt(old))
+       /* The thing moved must be mounted... */
+       if (!is_mounted(&old->mnt))
                goto out;
 
-       if (!attached && !(ns && is_anon_ns(ns)))
+       /* ... and either ours or the root of anon namespace */
+       if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
                goto out;
 
        if (old->mnt.mnt_flags & MNT_LOCKED)