Loading fs/btrfs/ioctl.c +33 −15 Original line number Diff line number Diff line Loading @@ -1958,7 +1958,7 @@ static noinline int copy_to_sk(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_ioctl_search_key *sk, size_t *buf_size, char *buf, char __user *ubuf, unsigned long *sk_offset, int *num_found) { Loading Loading @@ -2018,14 +2018,22 @@ static noinline int copy_to_sk(struct btrfs_root *root, sh.transid = found_transid; /* copy search result header */ memcpy(buf + *sk_offset, &sh, sizeof(sh)); if (copy_to_user(ubuf + *sk_offset, &sh, sizeof(sh))) { ret = -EFAULT; goto out; } *sk_offset += sizeof(sh); if (item_len) { char *p = buf + *sk_offset; char __user *up = ubuf + *sk_offset; /* copy the item */ read_extent_buffer(leaf, p, item_off, item_len); if (read_extent_buffer_to_user(leaf, up, item_off, item_len)) { ret = -EFAULT; goto out; } *sk_offset += item_len; } (*num_found)++; Loading @@ -2052,13 +2060,22 @@ static noinline int copy_to_sk(struct btrfs_root *root, } else ret = 1; out: /* * 0: all items from this leaf copied, continue with next * 1: * more items can be copied, but unused buffer is too small * * all items were found * Either way, it will stops the loop which iterates to the next * leaf * -EOVERFLOW: item was to large for buffer * -EFAULT: could not copy extent buffer back to userspace */ return ret; } static noinline int search_ioctl(struct inode *inode, struct btrfs_ioctl_search_key *sk, size_t *buf_size, char *buf) char __user *ubuf) { struct btrfs_root *root; struct btrfs_key key; Loading Loading @@ -2106,7 +2123,7 @@ static noinline int search_ioctl(struct inode *inode, ret = 0; goto err; } ret = copy_to_sk(root, path, &key, sk, buf_size, buf, ret = copy_to_sk(root, path, &key, sk, buf_size, ubuf, &sk_offset, &num_found); btrfs_release_path(path); if (ret) Loading @@ -2124,7 +2141,8 @@ static noinline int search_ioctl(struct inode *inode, static noinline int btrfs_ioctl_tree_search(struct file *file, void __user *argp) { struct btrfs_ioctl_search_args *args; struct btrfs_ioctl_search_args __user *uargs; struct btrfs_ioctl_search_key sk; struct inode *inode; int ret; size_t buf_size; Loading @@ -2132,14 +2150,15 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, if (!capable(CAP_SYS_ADMIN)) return -EPERM; args = memdup_user(argp, sizeof(*args)); if (IS_ERR(args)) return PTR_ERR(args); uargs = (struct btrfs_ioctl_search_args __user *)argp; buf_size = sizeof(args->buf); if (copy_from_user(&sk, &uargs->key, sizeof(sk))) return -EFAULT; buf_size = sizeof(uargs->buf); inode = file_inode(file); ret = search_ioctl(inode, &args->key, &buf_size, args->buf); ret = search_ioctl(inode, &sk, &buf_size, uargs->buf); /* * In the origin implementation an overflow is handled by returning a Loading @@ -2148,9 +2167,8 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, if (ret == -EOVERFLOW) ret = 0; if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) if (ret == 0 && copy_to_user(&uargs->key, &sk, sizeof(sk))) ret = -EFAULT; kfree(args); return ret; } Loading Loading
fs/btrfs/ioctl.c +33 −15 Original line number Diff line number Diff line Loading @@ -1958,7 +1958,7 @@ static noinline int copy_to_sk(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_ioctl_search_key *sk, size_t *buf_size, char *buf, char __user *ubuf, unsigned long *sk_offset, int *num_found) { Loading Loading @@ -2018,14 +2018,22 @@ static noinline int copy_to_sk(struct btrfs_root *root, sh.transid = found_transid; /* copy search result header */ memcpy(buf + *sk_offset, &sh, sizeof(sh)); if (copy_to_user(ubuf + *sk_offset, &sh, sizeof(sh))) { ret = -EFAULT; goto out; } *sk_offset += sizeof(sh); if (item_len) { char *p = buf + *sk_offset; char __user *up = ubuf + *sk_offset; /* copy the item */ read_extent_buffer(leaf, p, item_off, item_len); if (read_extent_buffer_to_user(leaf, up, item_off, item_len)) { ret = -EFAULT; goto out; } *sk_offset += item_len; } (*num_found)++; Loading @@ -2052,13 +2060,22 @@ static noinline int copy_to_sk(struct btrfs_root *root, } else ret = 1; out: /* * 0: all items from this leaf copied, continue with next * 1: * more items can be copied, but unused buffer is too small * * all items were found * Either way, it will stops the loop which iterates to the next * leaf * -EOVERFLOW: item was to large for buffer * -EFAULT: could not copy extent buffer back to userspace */ return ret; } static noinline int search_ioctl(struct inode *inode, struct btrfs_ioctl_search_key *sk, size_t *buf_size, char *buf) char __user *ubuf) { struct btrfs_root *root; struct btrfs_key key; Loading Loading @@ -2106,7 +2123,7 @@ static noinline int search_ioctl(struct inode *inode, ret = 0; goto err; } ret = copy_to_sk(root, path, &key, sk, buf_size, buf, ret = copy_to_sk(root, path, &key, sk, buf_size, ubuf, &sk_offset, &num_found); btrfs_release_path(path); if (ret) Loading @@ -2124,7 +2141,8 @@ static noinline int search_ioctl(struct inode *inode, static noinline int btrfs_ioctl_tree_search(struct file *file, void __user *argp) { struct btrfs_ioctl_search_args *args; struct btrfs_ioctl_search_args __user *uargs; struct btrfs_ioctl_search_key sk; struct inode *inode; int ret; size_t buf_size; Loading @@ -2132,14 +2150,15 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, if (!capable(CAP_SYS_ADMIN)) return -EPERM; args = memdup_user(argp, sizeof(*args)); if (IS_ERR(args)) return PTR_ERR(args); uargs = (struct btrfs_ioctl_search_args __user *)argp; buf_size = sizeof(args->buf); if (copy_from_user(&sk, &uargs->key, sizeof(sk))) return -EFAULT; buf_size = sizeof(uargs->buf); inode = file_inode(file); ret = search_ioctl(inode, &args->key, &buf_size, args->buf); ret = search_ioctl(inode, &sk, &buf_size, uargs->buf); /* * In the origin implementation an overflow is handled by returning a Loading @@ -2148,9 +2167,8 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, if (ret == -EOVERFLOW) ret = 0; if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) if (ret == 0 && copy_to_user(&uargs->key, &sk, sizeof(sk))) ret = -EFAULT; kfree(args); return ret; } Loading