diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ioctl.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 393a543a519e..6ea15469c63f 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -2172,6 +2172,45 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, | |||
2172 | return ret; | 2172 | return ret; |
2173 | } | 2173 | } |
2174 | 2174 | ||
2175 | static noinline int btrfs_ioctl_tree_search_v2(struct file *file, | ||
2176 | void __user *argp) | ||
2177 | { | ||
2178 | struct btrfs_ioctl_search_args_v2 __user *uarg; | ||
2179 | struct btrfs_ioctl_search_args_v2 args; | ||
2180 | struct inode *inode; | ||
2181 | int ret; | ||
2182 | size_t buf_size; | ||
2183 | const size_t buf_limit = 16 * 1024 * 1024; | ||
2184 | |||
2185 | if (!capable(CAP_SYS_ADMIN)) | ||
2186 | return -EPERM; | ||
2187 | |||
2188 | /* copy search header and buffer size */ | ||
2189 | uarg = (struct btrfs_ioctl_search_args_v2 __user *)argp; | ||
2190 | if (copy_from_user(&args, uarg, sizeof(args))) | ||
2191 | return -EFAULT; | ||
2192 | |||
2193 | buf_size = args.buf_size; | ||
2194 | |||
2195 | if (buf_size < sizeof(struct btrfs_ioctl_search_header)) | ||
2196 | return -EOVERFLOW; | ||
2197 | |||
2198 | /* limit result size to 16MB */ | ||
2199 | if (buf_size > buf_limit) | ||
2200 | buf_size = buf_limit; | ||
2201 | |||
2202 | inode = file_inode(file); | ||
2203 | ret = search_ioctl(inode, &args.key, &buf_size, | ||
2204 | (char *)(&uarg->buf[0])); | ||
2205 | if (ret == 0 && copy_to_user(&uarg->key, &args.key, sizeof(args.key))) | ||
2206 | ret = -EFAULT; | ||
2207 | else if (ret == -EOVERFLOW && | ||
2208 | copy_to_user(&uarg->buf_size, &buf_size, sizeof(buf_size))) | ||
2209 | ret = -EFAULT; | ||
2210 | |||
2211 | return ret; | ||
2212 | } | ||
2213 | |||
2175 | /* | 2214 | /* |
2176 | * Search INODE_REFs to identify path name of 'dirid' directory | 2215 | * Search INODE_REFs to identify path name of 'dirid' directory |
2177 | * in a 'tree_id' tree. and sets path name to 'name'. | 2216 | * in a 'tree_id' tree. and sets path name to 'name'. |
@@ -5252,6 +5291,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
5252 | return btrfs_ioctl_trans_end(file); | 5291 | return btrfs_ioctl_trans_end(file); |
5253 | case BTRFS_IOC_TREE_SEARCH: | 5292 | case BTRFS_IOC_TREE_SEARCH: |
5254 | return btrfs_ioctl_tree_search(file, argp); | 5293 | return btrfs_ioctl_tree_search(file, argp); |
5294 | case BTRFS_IOC_TREE_SEARCH_V2: | ||
5295 | return btrfs_ioctl_tree_search_v2(file, argp); | ||
5255 | case BTRFS_IOC_INO_LOOKUP: | 5296 | case BTRFS_IOC_INO_LOOKUP: |
5256 | return btrfs_ioctl_ino_lookup(file, argp); | 5297 | return btrfs_ioctl_ino_lookup(file, argp); |
5257 | case BTRFS_IOC_INO_PATHS: | 5298 | case BTRFS_IOC_INO_PATHS: |