crypto: shash - remove shash_desc::flags
[sfrench/cifs-2.6.git] / fs / namespace.c
index 98a8c182af4f04e0752752751d731802b02172a9..c9cab307fa77de270b1fa2502dc2d7655a9432da 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/task_work.h>
 #include <linux/sched/task.h>
 #include <uapi/linux/mount.h>
+#include <linux/fs_context.h>
 
 #include "pnode.h"
 #include "internal.h"
@@ -940,38 +941,81 @@ static struct mount *skip_mnt_tree(struct mount *p)
        return p;
 }
 
-struct vfsmount *
-vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
+/**
+ * vfs_create_mount - Create a mount for a configured superblock
+ * @fc: The configuration context with the superblock attached
+ *
+ * Create a mount to an already configured superblock.  If necessary, the
+ * caller should invoke vfs_get_tree() before calling this.
+ *
+ * Note that this does not attach the mount to anything.
+ */
+struct vfsmount *vfs_create_mount(struct fs_context *fc)
 {
        struct mount *mnt;
-       struct dentry *root;
 
-       if (!type)
-               return ERR_PTR(-ENODEV);
+       if (!fc->root)
+               return ERR_PTR(-EINVAL);
 
-       mnt = alloc_vfsmnt(name);
+       mnt = alloc_vfsmnt(fc->source ?: "none");
        if (!mnt)
                return ERR_PTR(-ENOMEM);
 
-       if (flags & SB_KERNMOUNT)
+       if (fc->sb_flags & SB_KERNMOUNT)
                mnt->mnt.mnt_flags = MNT_INTERNAL;
 
-       root = mount_fs(type, flags, name, data);
-       if (IS_ERR(root)) {
-               mnt_free_id(mnt);
-               free_vfsmnt(mnt);
-               return ERR_CAST(root);
-       }
+       atomic_inc(&fc->root->d_sb->s_active);
+       mnt->mnt.mnt_sb         = fc->root->d_sb;
+       mnt->mnt.mnt_root       = dget(fc->root);
+       mnt->mnt_mountpoint     = mnt->mnt.mnt_root;
+       mnt->mnt_parent         = mnt;
 
-       mnt->mnt.mnt_root = root;
-       mnt->mnt.mnt_sb = root->d_sb;
-       mnt->mnt_mountpoint = mnt->mnt.mnt_root;
-       mnt->mnt_parent = mnt;
        lock_mount_hash();
-       list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
+       list_add_tail(&mnt->mnt_instance, &mnt->mnt.mnt_sb->s_mounts);
        unlock_mount_hash();
        return &mnt->mnt;
 }
+EXPORT_SYMBOL(vfs_create_mount);
+
+struct vfsmount *fc_mount(struct fs_context *fc)
+{
+       int err = vfs_get_tree(fc);
+       if (!err) {
+               up_write(&fc->root->d_sb->s_umount);
+               return vfs_create_mount(fc);
+       }
+       return ERR_PTR(err);
+}
+EXPORT_SYMBOL(fc_mount);
+
+struct vfsmount *vfs_kern_mount(struct file_system_type *type,
+                               int flags, const char *name,
+                               void *data)
+{
+       struct fs_context *fc;
+       struct vfsmount *mnt;
+       int ret = 0;
+
+       if (!type)
+               return ERR_PTR(-EINVAL);
+
+       fc = fs_context_for_mount(type, flags);
+       if (IS_ERR(fc))
+               return ERR_CAST(fc);
+
+       if (name)
+               ret = vfs_parse_fs_string(fc, "source",
+                                         name, strlen(name));
+       if (!ret)
+               ret = parse_monolithic_mount_data(fc, data);
+       if (!ret)
+               mnt = fc_mount(fc);
+       else
+               mnt = ERR_PTR(ret);
+
+       put_fs_context(fc);
+       return mnt;
+}
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
 
 struct vfsmount *
@@ -1013,27 +1057,6 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 
        mnt->mnt.mnt_flags = old->mnt.mnt_flags;
        mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);
-       /* Don't allow unprivileged users to change mount flags */
-       if (flag & CL_UNPRIVILEGED) {
-               mnt->mnt.mnt_flags |= MNT_LOCK_ATIME;
-
-               if (mnt->mnt.mnt_flags & MNT_READONLY)
-                       mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
-
-               if (mnt->mnt.mnt_flags & MNT_NODEV)
-                       mnt->mnt.mnt_flags |= MNT_LOCK_NODEV;
-
-               if (mnt->mnt.mnt_flags & MNT_NOSUID)
-                       mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID;
-
-               if (mnt->mnt.mnt_flags & MNT_NOEXEC)
-                       mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC;
-       }
-
-       /* Don't allow unprivileged users to reveal what is under a mount */
-       if ((flag & CL_UNPRIVILEGED) &&
-           (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire)))
-               mnt->mnt.mnt_flags |= MNT_LOCKED;
 
        atomic_inc(&sb->s_active);
        mnt->mnt.mnt_sb = sb;
@@ -1464,6 +1487,29 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
 
 static void shrink_submounts(struct mount *mnt);
 
+static int do_umount_root(struct super_block *sb)
+{
+       int ret = 0;
+
+       down_write(&sb->s_umount);
+       if (!sb_rdonly(sb)) {
+               struct fs_context *fc;
+
+               fc = fs_context_for_reconfigure(sb->s_root, SB_RDONLY,
+                                               SB_RDONLY);
+               if (IS_ERR(fc)) {
+                       ret = PTR_ERR(fc);
+               } else {
+                       ret = parse_monolithic_mount_data(fc, NULL);
+                       if (!ret)
+                               ret = reconfigure_super(fc);
+                       put_fs_context(fc);
+               }
+       }
+       up_write(&sb->s_umount);
+       return ret;
+}
+
 static int do_umount(struct mount *mnt, int flags)
 {
        struct super_block *sb = mnt->mnt.mnt_sb;
@@ -1529,11 +1575,7 @@ static int do_umount(struct mount *mnt, int flags)
                 */
                if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
                        return -EPERM;
-               down_write(&sb->s_umount);
-               if (!sb_rdonly(sb))
-                       retval = do_remount_sb(sb, SB_RDONLY, NULL, 0);
-               up_write(&sb->s_umount);
-               return retval;
+               return do_umount_root(sb);
        }
 
        namespace_lock();
@@ -1839,6 +1881,33 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
        return 0;
 }
 
+static void lock_mnt_tree(struct mount *mnt)
+{
+       struct mount *p;
+
+       for (p = mnt; p; p = next_mnt(p, mnt)) {
+               int flags = p->mnt.mnt_flags;
+               /* Don't allow unprivileged users to change mount flags */
+               flags |= MNT_LOCK_ATIME;
+
+               if (flags & MNT_READONLY)
+                       flags |= MNT_LOCK_READONLY;
+
+               if (flags & MNT_NODEV)
+                       flags |= MNT_LOCK_NODEV;
+
+               if (flags & MNT_NOSUID)
+                       flags |= MNT_LOCK_NOSUID;
+
+               if (flags & MNT_NOEXEC)
+                       flags |= MNT_LOCK_NOEXEC;
+               /* Don't allow unprivileged users to reveal what is under a mount */
+               if (list_empty(&p->mnt_expire))
+                       flags |= MNT_LOCKED;
+               p->mnt.mnt_flags = flags;
+       }
+}
+
 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
 {
        struct mount *p;
@@ -1956,6 +2025,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
                        struct mountpoint *dest_mp,
                        struct path *parent_path)
 {
+       struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
        HLIST_HEAD(tree_list);
        struct mnt_namespace *ns = dest_mnt->mnt_ns;
        struct mountpoint *smp;
@@ -2006,6 +2076,9 @@ static int attach_recursive_mnt(struct mount *source_mnt,
                                 child->mnt_mountpoint);
                if (q)
                        mnt_change_mountpoint(child, smp, q);
+               /* Notice when we are propagating across user namespaces */
+               if (child->mnt_parent->mnt_ns->user_ns != user_ns)
+                       lock_mnt_tree(child);
                commit_tree(child);
        }
        put_mountpoint(smp);
@@ -2313,7 +2386,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
        int err;
        struct super_block *sb = path->mnt->mnt_sb;
        struct mount *mnt = real_mount(path->mnt);
-       void *sec_opts = NULL;
+       struct fs_context *fc;
 
        if (!check_mnt(mnt))
                return -EINVAL;
@@ -2324,24 +2397,22 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
        if (!can_change_locked_flags(mnt, mnt_flags))
                return -EPERM;
 
-       if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) {
-               err = security_sb_eat_lsm_opts(data, &sec_opts);
-               if (err)
-                       return err;
-       }
-       err = security_sb_remount(sb, sec_opts);
-       security_free_mnt_opts(&sec_opts);
-       if (err)
-               return err;
+       fc = fs_context_for_reconfigure(path->dentry, sb_flags, MS_RMT_MASK);
+       if (IS_ERR(fc))
+               return PTR_ERR(fc);
 
-       down_write(&sb->s_umount);
-       err = -EPERM;
-       if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
-               err = do_remount_sb(sb, sb_flags, data, 0);
-               if (!err)
-                       set_mount_attributes(mnt, mnt_flags);
+       err = parse_monolithic_mount_data(fc, data);
+       if (!err) {
+               down_write(&sb->s_umount);
+               err = -EPERM;
+               if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
+                       err = reconfigure_super(fc);
+                       if (!err)
+                               set_mount_attributes(mnt, mnt_flags);
+               }
+               up_write(&sb->s_umount);
        }
-       up_write(&sb->s_umount);
+       put_fs_context(fc);
        return err;
 }
 
@@ -2425,29 +2496,6 @@ out:
        return err;
 }
 
-static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
-{
-       int err;
-       const char *subtype = strchr(fstype, '.');
-       if (subtype) {
-               subtype++;
-               err = -EINVAL;
-               if (!subtype[0])
-                       goto err;
-       } else
-               subtype = "";
-
-       mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
-       err = -ENOMEM;
-       if (!mnt->mnt_sb->s_subtype)
-               goto err;
-       return mnt;
-
- err:
-       mntput(mnt);
-       return ERR_PTR(err);
-}
-
 /*
  * add a mount into a namespace's mount tree
  */
@@ -2492,7 +2540,39 @@ unlock:
        return err;
 }
 
-static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags);
+static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags);
+
+/*
+ * Create a new mount using a superblock configuration and request it
+ * be added to the namespace tree.
+ */
+static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
+                          unsigned int mnt_flags)
+{
+       struct vfsmount *mnt;
+       struct super_block *sb = fc->root->d_sb;
+       int error;
+
+       error = security_sb_kern_mount(sb);
+       if (!error && mount_too_revealing(sb, &mnt_flags))
+               error = -EPERM;
+
+       if (unlikely(error)) {
+               fc_drop_locked(fc);
+               return error;
+       }
+
+       up_write(&sb->s_umount);
+
+       mnt = vfs_create_mount(fc);
+       if (IS_ERR(mnt))
+               return PTR_ERR(mnt);
+
+       error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags);
+       if (error < 0)
+               mntput(mnt);
+       return error;
+}
 
 /*
  * create a new mount for userspace and request it to be added into the
@@ -2502,8 +2582,9 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
                        int mnt_flags, const char *name, void *data)
 {
        struct file_system_type *type;
-       struct vfsmount *mnt;
-       int err;
+       struct fs_context *fc;
+       const char *subtype = NULL;
+       int err = 0;
 
        if (!fstype)
                return -EINVAL;
@@ -2512,23 +2593,37 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
        if (!type)
                return -ENODEV;
 
-       mnt = vfs_kern_mount(type, sb_flags, name, data);
-       if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
-           !mnt->mnt_sb->s_subtype)
-               mnt = fs_set_subtype(mnt, fstype);
+       if (type->fs_flags & FS_HAS_SUBTYPE) {
+               subtype = strchr(fstype, '.');
+               if (subtype) {
+                       subtype++;
+                       if (!*subtype) {
+                               put_filesystem(type);
+                               return -EINVAL;
+                       }
+               } else {
+                       subtype = "";
+               }
+       }
 
+       fc = fs_context_for_mount(type, sb_flags);
        put_filesystem(type);
-       if (IS_ERR(mnt))
-               return PTR_ERR(mnt);
-
-       if (mount_too_revealing(mnt, &mnt_flags)) {
-               mntput(mnt);
-               return -EPERM;
-       }
+       if (IS_ERR(fc))
+               return PTR_ERR(fc);
+
+       if (subtype)
+               err = vfs_parse_fs_string(fc, "subtype",
+                                         subtype, strlen(subtype));
+       if (!err && name)
+               err = vfs_parse_fs_string(fc, "source", name, strlen(name));
+       if (!err)
+               err = parse_monolithic_mount_data(fc, data);
+       if (!err)
+               err = vfs_get_tree(fc);
+       if (!err)
+               err = do_new_mount_fc(fc, path, mnt_flags);
 
-       err = do_add_mount(real_mount(mnt), path, mnt_flags);
-       if (err)
-               mntput(mnt);
+       put_fs_context(fc);
        return err;
 }
 
@@ -2863,7 +2958,8 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
 
 static void free_mnt_ns(struct mnt_namespace *ns)
 {
-       ns_free_inum(&ns->ns);
+       if (!is_anon_ns(ns))
+               ns_free_inum(&ns->ns);
        dec_mnt_namespaces(ns->ucounts);
        put_user_ns(ns->user_ns);
        kfree(ns);
@@ -2878,7 +2974,7 @@ static void free_mnt_ns(struct mnt_namespace *ns)
  */
 static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
 
-static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
+static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool anon)
 {
        struct mnt_namespace *new_ns;
        struct ucounts *ucounts;
@@ -2888,28 +2984,27 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
        if (!ucounts)
                return ERR_PTR(-ENOSPC);
 
-       new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
+       new_ns = kzalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
        if (!new_ns) {
                dec_mnt_namespaces(ucounts);
                return ERR_PTR(-ENOMEM);
        }
-       ret = ns_alloc_inum(&new_ns->ns);
-       if (ret) {
-               kfree(new_ns);
-               dec_mnt_namespaces(ucounts);
-               return ERR_PTR(ret);
+       if (!anon) {
+               ret = ns_alloc_inum(&new_ns->ns);
+               if (ret) {
+                       kfree(new_ns);
+                       dec_mnt_namespaces(ucounts);
+                       return ERR_PTR(ret);
+               }
        }
        new_ns->ns.ops = &mntns_operations;
-       new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
+       if (!anon)
+               new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
        atomic_set(&new_ns->count, 1);
-       new_ns->root = NULL;
        INIT_LIST_HEAD(&new_ns->list);
        init_waitqueue_head(&new_ns->poll);
-       new_ns->event = 0;
        new_ns->user_ns = get_user_ns(user_ns);
        new_ns->ucounts = ucounts;
-       new_ns->mounts = 0;
-       new_ns->pending_mounts = 0;
        return new_ns;
 }
 
@@ -2933,7 +3028,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
 
        old = ns->root;
 
-       new_ns = alloc_mnt_ns(user_ns);
+       new_ns = alloc_mnt_ns(user_ns, false);
        if (IS_ERR(new_ns))
                return new_ns;
 
@@ -2941,13 +3036,18 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
        /* First pass: copy the tree topology */
        copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
        if (user_ns != ns->user_ns)
-               copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
+               copy_flags |= CL_SHARED_TO_SLAVE;
        new = copy_tree(old, old->mnt.mnt_root, copy_flags);
        if (IS_ERR(new)) {
                namespace_unlock();
                free_mnt_ns(new_ns);
                return ERR_CAST(new);
        }
+       if (user_ns != ns->user_ns) {
+               lock_mount_hash();
+               lock_mnt_tree(new);
+               unlock_mount_hash();
+       }
        new_ns->root = new;
        list_add_tail(&new_ns->list, &new->mnt_list);
 
@@ -2988,37 +3088,25 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
        return new_ns;
 }
 
-/**
- * create_mnt_ns - creates a private namespace and adds a root filesystem
- * @mnt: pointer to the new root filesystem mountpoint
- */
-static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
-{
-       struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
-       if (!IS_ERR(new_ns)) {
-               struct mount *mnt = real_mount(m);
-               mnt->mnt_ns = new_ns;
-               new_ns->root = mnt;
-               new_ns->mounts++;
-               list_add(&mnt->mnt_list, &new_ns->list);
-       } else {
-               mntput(m);
-       }
-       return new_ns;
-}
-
-struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
+struct dentry *mount_subtree(struct vfsmount *m, const char *name)
 {
+       struct mount *mnt = real_mount(m);
        struct mnt_namespace *ns;
        struct super_block *s;
        struct path path;
        int err;
 
-       ns = create_mnt_ns(mnt);
-       if (IS_ERR(ns))
+       ns = alloc_mnt_ns(&init_user_ns, true);
+       if (IS_ERR(ns)) {
+               mntput(m);
                return ERR_CAST(ns);
+       }
+       mnt->mnt_ns = ns;
+       ns->root = mnt;
+       ns->mounts++;
+       list_add(&mnt->mnt_list, &ns->list);
 
-       err = vfs_path_lookup(mnt->mnt_root, mnt,
+       err = vfs_path_lookup(m->mnt_root, m,
                        name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
 
        put_mnt_ns(ns);
@@ -3228,6 +3316,7 @@ out0:
 static void __init init_mount_tree(void)
 {
        struct vfsmount *mnt;
+       struct mount *m;
        struct mnt_namespace *ns;
        struct path root;
        struct file_system_type *type;
@@ -3240,10 +3329,14 @@ static void __init init_mount_tree(void)
        if (IS_ERR(mnt))
                panic("Can't create rootfs");
 
-       ns = create_mnt_ns(mnt);
+       ns = alloc_mnt_ns(&init_user_ns, false);
        if (IS_ERR(ns))
                panic("Can't allocate initial namespace");
-
+       m = real_mount(mnt);
+       m->mnt_ns = ns;
+       ns->root = m;
+       ns->mounts = 1;
+       list_add(&m->mnt_list, &ns->list);
        init_task.nsproxy->mnt_ns = ns;
        get_mnt_ns(ns);
 
@@ -3297,10 +3390,10 @@ void put_mnt_ns(struct mnt_namespace *ns)
        free_mnt_ns(ns);
 }
 
-struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
+struct vfsmount *kern_mount(struct file_system_type *type)
 {
        struct vfsmount *mnt;
-       mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, data);
+       mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, NULL);
        if (!IS_ERR(mnt)) {
                /*
                 * it is a longterm mount, don't release mnt until
@@ -3310,7 +3403,7 @@ struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
        }
        return mnt;
 }
-EXPORT_SYMBOL_GPL(kern_mount_data);
+EXPORT_SYMBOL_GPL(kern_mount);
 
 void kern_unmount(struct vfsmount *mnt)
 {
@@ -3352,7 +3445,8 @@ bool current_chrooted(void)
        return chrooted;
 }
 
-static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
+static bool mnt_already_visible(struct mnt_namespace *ns,
+                               const struct super_block *sb,
                                int *new_mnt_flags)
 {
        int new_flags = *new_mnt_flags;
@@ -3364,7 +3458,7 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
                struct mount *child;
                int mnt_flags;
 
-               if (mnt->mnt.mnt_sb->s_type != new->mnt_sb->s_type)
+               if (mnt->mnt.mnt_sb->s_type != sb->s_type)
                        continue;
 
                /* This mount is not fully visible if it's root directory
@@ -3415,7 +3509,7 @@ found:
        return visible;
 }
 
-static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
+static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags)
 {
        const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
        struct mnt_namespace *ns = current->nsproxy->mnt_ns;
@@ -3425,7 +3519,7 @@ static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
                return false;
 
        /* Can this filesystem be too revealing? */
-       s_iflags = mnt->mnt_sb->s_iflags;
+       s_iflags = sb->s_iflags;
        if (!(s_iflags & SB_I_USERNS_VISIBLE))
                return false;
 
@@ -3435,7 +3529,7 @@ static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
                return true;
        }
 
-       return !mnt_already_visible(ns, mnt, new_mnt_flags);
+       return !mnt_already_visible(ns, sb, new_mnt_flags);
 }
 
 bool mnt_may_suid(struct vfsmount *mnt)
@@ -3484,6 +3578,9 @@ static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
            !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (is_anon_ns(mnt_ns))
+               return -EINVAL;
+
        if (fs->users != 1)
                return -EINVAL;