diff options
| -rw-r--r-- | fs/btrfs/ioctl.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 6e09fc1c1c18..3d89fd888399 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -1957,7 +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 | size_t *buf_size, |
| 1961 | char *buf, | 1961 | char *buf, |
| 1962 | unsigned long *sk_offset, | 1962 | unsigned long *sk_offset, |
| 1963 | int *num_found) | 1963 | int *num_found) |
| @@ -1990,7 +1990,7 @@ static noinline int copy_to_sk(struct btrfs_root *root, | |||
| 1990 | if (!key_in_sk(key, sk)) | 1990 | if (!key_in_sk(key, sk)) |
| 1991 | continue; | 1991 | continue; |
| 1992 | 1992 | ||
| 1993 | if (sizeof(sh) + item_len > buf_size) { | 1993 | if (sizeof(sh) + item_len > *buf_size) { |
| 1994 | if (*num_found) { | 1994 | if (*num_found) { |
| 1995 | ret = 1; | 1995 | ret = 1; |
| 1996 | goto out; | 1996 | goto out; |
| @@ -2001,11 +2001,12 @@ static noinline int copy_to_sk(struct btrfs_root *root, | |||
| 2001 | * handle -EOVERFLOW | 2001 | * handle -EOVERFLOW |
| 2002 | */ | 2002 | */ |
| 2003 | 2003 | ||
| 2004 | *buf_size = sizeof(sh) + item_len; | ||
| 2004 | item_len = 0; | 2005 | item_len = 0; |
| 2005 | ret = -EOVERFLOW; | 2006 | ret = -EOVERFLOW; |
| 2006 | } | 2007 | } |
| 2007 | 2008 | ||
| 2008 | if (sizeof(sh) + item_len + *sk_offset > buf_size) { | 2009 | if (sizeof(sh) + item_len + *sk_offset > *buf_size) { |
| 2009 | ret = 1; | 2010 | ret = 1; |
| 2010 | goto out; | 2011 | goto out; |
| 2011 | } | 2012 | } |
| @@ -2056,7 +2057,7 @@ out: | |||
| 2056 | 2057 | ||
| 2057 | static noinline int search_ioctl(struct inode *inode, | 2058 | static noinline int search_ioctl(struct inode *inode, |
| 2058 | struct btrfs_ioctl_search_key *sk, | 2059 | struct btrfs_ioctl_search_key *sk, |
| 2059 | size_t buf_size, | 2060 | size_t *buf_size, |
| 2060 | char *buf) | 2061 | char *buf) |
| 2061 | { | 2062 | { |
| 2062 | struct btrfs_root *root; | 2063 | struct btrfs_root *root; |
| @@ -2067,8 +2068,10 @@ static noinline int search_ioctl(struct inode *inode, | |||
| 2067 | int num_found = 0; | 2068 | int num_found = 0; |
| 2068 | unsigned long sk_offset = 0; | 2069 | unsigned long sk_offset = 0; |
| 2069 | 2070 | ||
| 2070 | if (buf_size < sizeof(struct btrfs_ioctl_search_header)) | 2071 | if (*buf_size < sizeof(struct btrfs_ioctl_search_header)) { |
| 2072 | *buf_size = sizeof(struct btrfs_ioctl_search_header); | ||
| 2071 | return -EOVERFLOW; | 2073 | return -EOVERFLOW; |
| 2074 | } | ||
| 2072 | 2075 | ||
| 2073 | path = btrfs_alloc_path(); | 2076 | path = btrfs_alloc_path(); |
| 2074 | if (!path) | 2077 | if (!path) |
| @@ -2121,9 +2124,10 @@ err: | |||
| 2121 | static noinline int btrfs_ioctl_tree_search(struct file *file, | 2124 | static noinline int btrfs_ioctl_tree_search(struct file *file, |
| 2122 | void __user *argp) | 2125 | void __user *argp) |
| 2123 | { | 2126 | { |
| 2124 | struct btrfs_ioctl_search_args *args; | 2127 | struct btrfs_ioctl_search_args *args; |
| 2125 | struct inode *inode; | 2128 | struct inode *inode; |
| 2126 | int ret; | 2129 | int ret; |
| 2130 | size_t buf_size; | ||
| 2127 | 2131 | ||
| 2128 | if (!capable(CAP_SYS_ADMIN)) | 2132 | if (!capable(CAP_SYS_ADMIN)) |
| 2129 | return -EPERM; | 2133 | return -EPERM; |
| @@ -2132,8 +2136,10 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, | |||
| 2132 | if (IS_ERR(args)) | 2136 | if (IS_ERR(args)) |
| 2133 | return PTR_ERR(args); | 2137 | return PTR_ERR(args); |
| 2134 | 2138 | ||
| 2139 | buf_size = sizeof(args->buf); | ||
| 2140 | |||
| 2135 | inode = file_inode(file); | 2141 | inode = file_inode(file); |
| 2136 | ret = search_ioctl(inode, &args->key, sizeof(args->buf), args->buf); | 2142 | ret = search_ioctl(inode, &args->key, &buf_size, args->buf); |
| 2137 | 2143 | ||
| 2138 | /* | 2144 | /* |
| 2139 | * In the origin implementation an overflow is handled by returning a | 2145 | * In the origin implementation an overflow is handled by returning a |
