fs: port ->permission() to pass mnt_idmap
[linux-block.git] / fs / btrfs / ioctl.c
index f23d0d399b9fc6220c0d49798ed04a45fd324121..80c7feb30770f2749511b218bfc2649322c025d2 100644 (file)
@@ -898,10 +898,11 @@ free_pending:
  *     nfs_async_unlink().
  */
 
-static int btrfs_may_delete(struct user_namespace *mnt_userns,
+static int btrfs_may_delete(struct mnt_idmap *idmap,
                            struct inode *dir, struct dentry *victim, int isdir)
 {
        int error;
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
 
        if (d_really_is_negative(victim))
                return -ENOENT;
@@ -909,7 +910,7 @@ static int btrfs_may_delete(struct user_namespace *mnt_userns,
        BUG_ON(d_inode(victim->d_parent) != dir);
        audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
-       error = inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC);
+       error = inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
        if (error)
                return error;
        if (IS_APPEND(dir))
@@ -933,16 +934,16 @@ static int btrfs_may_delete(struct user_namespace *mnt_userns,
 }
 
 /* copy of may_create in fs/namei.c() */
-static inline int btrfs_may_create(struct user_namespace *mnt_userns,
+static inline int btrfs_may_create(struct mnt_idmap *idmap,
                                   struct inode *dir, struct dentry *child)
 {
        if (d_really_is_positive(child))
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
-       if (!fsuidgid_has_mapping(dir->i_sb, mnt_userns))
+       if (!fsuidgid_has_mapping(dir->i_sb, idmap))
                return -EOVERFLOW;
-       return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC);
+       return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
 }
 
 /*
@@ -951,7 +952,7 @@ static inline int btrfs_may_create(struct user_namespace *mnt_userns,
  * inside this filesystem so it's quite a bit simpler.
  */
 static noinline int btrfs_mksubvol(const struct path *parent,
-                                  struct user_namespace *mnt_userns,
+                                  struct mnt_idmap *idmap,
                                   const char *name, int namelen,
                                   struct btrfs_root *snap_src,
                                   bool readonly,
@@ -961,18 +962,19 @@ static noinline int btrfs_mksubvol(const struct path *parent,
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct dentry *dentry;
        struct fscrypt_str name_str = FSTR_INIT((char *)name, namelen);
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
        int error;
 
        error = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
        if (error == -EINTR)
                return error;
 
-       dentry = lookup_one(mnt_userns, name, parent->dentry, namelen);
+       dentry = lookup_one(idmap, name, parent->dentry, namelen);
        error = PTR_ERR(dentry);
        if (IS_ERR(dentry))
                goto out_unlock;
 
-       error = btrfs_may_create(mnt_userns, dir, dentry);
+       error = btrfs_may_create(idmap, dir, dentry);
        if (error)
                goto out_dput;
 
@@ -1007,7 +1009,7 @@ out_unlock:
 }
 
 static noinline int btrfs_mksnapshot(const struct path *parent,
-                                  struct user_namespace *mnt_userns,
+                                  struct mnt_idmap *idmap,
                                   const char *name, int namelen,
                                   struct btrfs_root *root,
                                   bool readonly,
@@ -1037,7 +1039,7 @@ static noinline int btrfs_mksnapshot(const struct path *parent,
 
        btrfs_wait_ordered_extents(root, U64_MAX, 0, (u64)-1);
 
-       ret = btrfs_mksubvol(parent, mnt_userns, name, namelen,
+       ret = btrfs_mksubvol(parent, idmap, name, namelen,
                             root, readonly, inherit);
 out:
        if (snapshot_force_cow)
@@ -1240,13 +1242,14 @@ out_drop:
 }
 
 static noinline int __btrfs_ioctl_snap_create(struct file *file,
-                               struct user_namespace *mnt_userns,
+                               struct mnt_idmap *idmap,
                                const char *name, unsigned long fd, int subvol,
                                bool readonly,
                                struct btrfs_qgroup_inherit *inherit)
 {
        int namelen;
        int ret = 0;
+       struct user_namespace *mnt_userns = mnt_idmap_owner(idmap);
 
        if (!S_ISDIR(file_inode(file)->i_mode))
                return -ENOTDIR;
@@ -1268,7 +1271,7 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
        }
 
        if (subvol) {
-               ret = btrfs_mksubvol(&file->f_path, mnt_userns, name,
+               ret = btrfs_mksubvol(&file->f_path, idmap, name,
                                     namelen, NULL, readonly, inherit);
        } else {
                struct fd src = fdget(fd);
@@ -1290,7 +1293,7 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
                         */
                        ret = -EPERM;
                } else {
-                       ret = btrfs_mksnapshot(&file->f_path, mnt_userns,
+                       ret = btrfs_mksnapshot(&file->f_path, idmap,
                                               name, namelen,
                                               BTRFS_I(src_inode)->root,
                                               readonly, inherit);
@@ -1317,7 +1320,7 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
                return PTR_ERR(vol_args);
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
 
-       ret = __btrfs_ioctl_snap_create(file, file_mnt_user_ns(file),
+       ret = __btrfs_ioctl_snap_create(file, file_mnt_idmap(file),
                                        vol_args->name, vol_args->fd, subvol,
                                        false, NULL);
 
@@ -1377,7 +1380,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
                }
        }
 
-       ret = __btrfs_ioctl_snap_create(file, file_mnt_user_ns(file),
+       ret = __btrfs_ioctl_snap_create(file, file_mnt_idmap(file),
                                        vol_args->name, vol_args->fd, subvol,
                                        readonly, inherit);
        if (ret)
@@ -1870,7 +1873,7 @@ out:
        return ret;
 }
 
-static int btrfs_search_path_in_tree_user(struct user_namespace *mnt_userns,
+static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap,
                                struct inode *inode,
                                struct btrfs_ioctl_ino_lookup_user_args *args)
 {
@@ -1962,7 +1965,7 @@ static int btrfs_search_path_in_tree_user(struct user_namespace *mnt_userns,
                                ret = PTR_ERR(temp_inode);
                                goto out_put;
                        }
-                       ret = inode_permission(mnt_userns, temp_inode,
+                       ret = inode_permission(idmap, temp_inode,
                                               MAY_READ | MAY_EXEC);
                        iput(temp_inode);
                        if (ret) {
@@ -2101,7 +2104,7 @@ static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp)
                return -EACCES;
        }
 
-       ret = btrfs_search_path_in_tree_user(file_mnt_user_ns(file), inode, args);
+       ret = btrfs_search_path_in_tree_user(file_mnt_idmap(file), inode, args);
 
        if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
                ret = -EFAULT;
@@ -2335,7 +2338,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
        struct btrfs_root *dest = NULL;
        struct btrfs_ioctl_vol_args *vol_args = NULL;
        struct btrfs_ioctl_vol_args_v2 *vol_args2 = NULL;
-       struct user_namespace *mnt_userns = file_mnt_user_ns(file);
+       struct mnt_idmap *idmap = file_mnt_idmap(file);
        char *subvol_name, *subvol_name_ptr = NULL;
        int subvol_namelen;
        int err = 0;
@@ -2428,7 +2431,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                         * anywhere in the filesystem the user wouldn't be able
                         * to delete without an idmapped mount.
                         */
-                       if (old_dir != dir && mnt_userns != &init_user_ns) {
+                       if (old_dir != dir && idmap != &nop_mnt_idmap) {
                                err = -EOPNOTSUPP;
                                goto free_parent;
                        }
@@ -2471,7 +2474,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
        err = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
        if (err == -EINTR)
                goto free_subvol_name;
-       dentry = lookup_one(mnt_userns, subvol_name, parent, subvol_namelen);
+       dentry = lookup_one(idmap, subvol_name, parent, subvol_namelen);
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
                goto out_unlock_dir;
@@ -2513,13 +2516,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                if (root == dest)
                        goto out_dput;
 
-               err = inode_permission(mnt_userns, inode, MAY_WRITE | MAY_EXEC);
+               err = inode_permission(idmap, inode, MAY_WRITE | MAY_EXEC);
                if (err)
                        goto out_dput;
        }
 
        /* check if subvolume may be deleted by a user */
-       err = btrfs_may_delete(mnt_userns, dir, dentry, 1);
+       err = btrfs_may_delete(idmap, dir, dentry, 1);
        if (err)
                goto out_dput;
 
@@ -2582,7 +2585,7 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
                 * running and allows defrag on files open in read-only mode.
                 */
                if (!capable(CAP_SYS_ADMIN) &&
-                   inode_permission(&init_user_ns, inode, MAY_WRITE)) {
+                   inode_permission(&nop_mnt_idmap, inode, MAY_WRITE)) {
                        ret = -EPERM;
                        goto out;
                }