diff options
author | Gerhard Heift <gerhard@heift.name> | 2014-01-30 10:23:58 -0500 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-06-12 21:21:26 -0400 |
commit | 12544442882e13aee98126928bb3a1a141484fe8 (patch) | |
tree | d8927e8ee3498c2362f38b328b73c3a37bcd77e1 | |
parent | 25c9bc2e2bc9d67de7fc49ff2784cae5de755192 (diff) |
btrfs: tree_search, search_ioctl: accept varying buffer
rewrite search_ioctl to accept a buffer with varying size
Signed-off-by: Gerhard Heift <Gerhard@Heift.Name>
Signed-off-by: Chris Mason <clm@fb.com>
Acked-by: David Sterba <dsterba@suse.cz>
-rw-r--r-- | fs/btrfs/ioctl.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 65148cd102cd..775640475e35 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1957,6 +1957,7 @@ static noinline int copy_to_sk(struct btrfs_root *root, | |||
1957 | struct btrfs_path *path, | 1957 | struct btrfs_path *path, |
1958 | struct btrfs_key *key, | 1958 | struct btrfs_key *key, |
1959 | struct btrfs_ioctl_search_key *sk, | 1959 | struct btrfs_ioctl_search_key *sk, |
1960 | size_t buf_size, | ||
1960 | char *buf, | 1961 | char *buf, |
1961 | unsigned long *sk_offset, | 1962 | unsigned long *sk_offset, |
1962 | int *num_found) | 1963 | int *num_found) |
@@ -1989,11 +1990,10 @@ static noinline int copy_to_sk(struct btrfs_root *root, | |||
1989 | if (!key_in_sk(key, sk)) | 1990 | if (!key_in_sk(key, sk)) |
1990 | continue; | 1991 | continue; |
1991 | 1992 | ||
1992 | if (sizeof(sh) + item_len > BTRFS_SEARCH_ARGS_BUFSIZE) | 1993 | if (sizeof(sh) + item_len > buf_size) |
1993 | item_len = 0; | 1994 | item_len = 0; |
1994 | 1995 | ||
1995 | if (sizeof(sh) + item_len + *sk_offset > | 1996 | if (sizeof(sh) + item_len + *sk_offset > buf_size) { |
1996 | BTRFS_SEARCH_ARGS_BUFSIZE) { | ||
1997 | ret = 1; | 1997 | ret = 1; |
1998 | goto out; | 1998 | goto out; |
1999 | } | 1999 | } |
@@ -2040,17 +2040,21 @@ out: | |||
2040 | } | 2040 | } |
2041 | 2041 | ||
2042 | static noinline int search_ioctl(struct inode *inode, | 2042 | static noinline int search_ioctl(struct inode *inode, |
2043 | struct btrfs_ioctl_search_args *args) | 2043 | struct btrfs_ioctl_search_key *sk, |
2044 | size_t buf_size, | ||
2045 | char *buf) | ||
2044 | { | 2046 | { |
2045 | struct btrfs_root *root; | 2047 | struct btrfs_root *root; |
2046 | struct btrfs_key key; | 2048 | struct btrfs_key key; |
2047 | struct btrfs_path *path; | 2049 | struct btrfs_path *path; |
2048 | struct btrfs_ioctl_search_key *sk = &args->key; | ||
2049 | struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info; | 2050 | struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info; |
2050 | int ret; | 2051 | int ret; |
2051 | int num_found = 0; | 2052 | int num_found = 0; |
2052 | unsigned long sk_offset = 0; | 2053 | unsigned long sk_offset = 0; |
2053 | 2054 | ||
2055 | if (buf_size < sizeof(struct btrfs_ioctl_search_header)) | ||
2056 | return -EOVERFLOW; | ||
2057 | |||
2054 | path = btrfs_alloc_path(); | 2058 | path = btrfs_alloc_path(); |
2055 | if (!path) | 2059 | if (!path) |
2056 | return -ENOMEM; | 2060 | return -ENOMEM; |
@@ -2084,7 +2088,7 @@ static noinline int search_ioctl(struct inode *inode, | |||
2084 | ret = 0; | 2088 | ret = 0; |
2085 | goto err; | 2089 | goto err; |
2086 | } | 2090 | } |
2087 | ret = copy_to_sk(root, path, &key, sk, args->buf, | 2091 | ret = copy_to_sk(root, path, &key, sk, buf_size, buf, |
2088 | &sk_offset, &num_found); | 2092 | &sk_offset, &num_found); |
2089 | btrfs_release_path(path); | 2093 | btrfs_release_path(path); |
2090 | if (ret) | 2094 | if (ret) |
@@ -2113,7 +2117,7 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, | |||
2113 | return PTR_ERR(args); | 2117 | return PTR_ERR(args); |
2114 | 2118 | ||
2115 | inode = file_inode(file); | 2119 | inode = file_inode(file); |
2116 | ret = search_ioctl(inode, args); | 2120 | ret = search_ioctl(inode, &args->key, sizeof(args->buf), args->buf); |
2117 | if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) | 2121 | if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) |
2118 | ret = -EFAULT; | 2122 | ret = -EFAULT; |
2119 | kfree(args); | 2123 | kfree(args); |