move mount_capable() further out
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 13 May 2019 16:57:22 +0000 (12:57 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 25 May 2019 22:00:02 +0000 (18:00 -0400)
Call graph of vfs_get_tree():
vfs_fsconfig_locked() # neither kernmount, nor submount
do_new_mount() # neither kernmount, nor submount
fc_mount()
afs_mntpt_do_automount() # submount
mount_one_hugetlbfs() # kernmount
pid_ns_prepare_proc() # kernmount
mq_create_mount() # kernmount
vfs_kern_mount()
simple_pin_fs() # kernmount
vfs_submount() # submount
kern_mount() # kernmount
init_mount_tree()
btrfs_mount()
nfs_do_root_mount()

The first two need the check (unconditionally).
init_mount_tree() is setting rootfs up; any capability
checks make zero sense for that one.  And btrfs_mount()/
nfs_do_root_mount() have the checks already done in their
callers.

IOW, we can shift mount_capable() handling into
the two callers - one in the normal case of mount(2),
another - in fsconfig(2) handling of FSCONFIG_CMD_CREATE.
I.e. the syscalls that set a new filesystem up.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/fsopen.c
fs/namespace.c
fs/super.c

index c2891e933ef17e2fe326bc3eef2a11cb4c982cd3..390172772f55b78256a64bd9ed3a0fb0e459d76e 100644 (file)
@@ -230,6 +230,8 @@ static int vfs_fsconfig_locked(struct fs_context *fc, int cmd,
        case FSCONFIG_CMD_CREATE:
                if (fc->phase != FS_CONTEXT_CREATE_PARAMS)
                        return -EBUSY;
+               if (!mount_capable(fc))
+                       return -EPERM;
                fc->phase = FS_CONTEXT_CREATING;
                ret = vfs_get_tree(fc);
                if (ret)
index ffb13f0562b0702df6c22724b0557c6fb789d732..1141641dff9605b6f729080a31e1f1d82f337fea 100644 (file)
@@ -2786,6 +2786,8 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
                err = vfs_parse_fs_string(fc, "source", name, strlen(name));
        if (!err)
                err = parse_monolithic_mount_data(fc, data);
+       if (!err && !mount_capable(fc))
+               err = -EPERM;
        if (!err)
                err = vfs_get_tree(fc);
        if (!err)
index 2c38541cd89f2f569df5b1bc34033a1e5dfbf7e9..72b4a5afcfd6da3cbd7ba9cdca70f11d3df92fd9 100644 (file)
@@ -1415,12 +1415,6 @@ int vfs_get_tree(struct fs_context *fc)
        if (fc->root)
                return -EBUSY;
 
-       if (!(fc->sb_flags & SB_KERNMOUNT) &&
-           fc->purpose != FS_CONTEXT_FOR_SUBMOUNT) {
-               if (!mount_capable(fc))
-                       return -EPERM;
-       }
-
        /* Get the mountable root in fc->root, with a ref on the root and a ref
         * on the superblock.
         */