|
@@ -2271,10 +2271,7 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file,
|
|
|
{
|
|
|
struct btrfs_ioctl_ino_lookup_args *args;
|
|
|
struct inode *inode;
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (!capable(CAP_SYS_ADMIN))
|
|
|
- return -EPERM;
|
|
|
+ int ret = 0;
|
|
|
|
|
|
args = memdup_user(argp, sizeof(*args));
|
|
|
if (IS_ERR(args))
|
|
@@ -2282,13 +2279,28 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file,
|
|
|
|
|
|
inode = file_inode(file);
|
|
|
|
|
|
+ /*
|
|
|
+ * Unprivileged query to obtain the containing subvolume root id. The
|
|
|
+ * path is reset so it's consistent with btrfs_search_path_in_tree.
|
|
|
+ */
|
|
|
if (args->treeid == 0)
|
|
|
args->treeid = BTRFS_I(inode)->root->root_key.objectid;
|
|
|
|
|
|
+ if (args->objectid == BTRFS_FIRST_FREE_OBJECTID) {
|
|
|
+ args->name[0] = 0;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!capable(CAP_SYS_ADMIN)) {
|
|
|
+ ret = -EPERM;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
ret = btrfs_search_path_in_tree(BTRFS_I(inode)->root->fs_info,
|
|
|
args->treeid, args->objectid,
|
|
|
args->name);
|
|
|
|
|
|
+out:
|
|
|
if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
|
|
|
ret = -EFAULT;
|
|
|
|