If an item in tree_search is too large to be stored in the given buffer, return
the needed size (including the header).

Signed-off-by: Gerhard Heift <gerh...@heift.name>
---
 fs/btrfs/ioctl.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 04e1a98..10b9931 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1854,7 +1854,7 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                               struct btrfs_path *path,
                               struct btrfs_key *key,
                               struct btrfs_ioctl_search_key *sk,
-                              size_t buf_size,
+                              size_t *buf_size,
                               char *buf,
                               unsigned long *sk_offset,
                               int *num_found)
@@ -1887,7 +1887,7 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                if (!key_in_sk(key, sk))
                        continue;
 
-               if (sizeof(sh) + item_len > buf_size) {
+               if (sizeof(sh) + item_len > *buf_size) {
                        if (*num_found) {
                                ret = 1;
                                goto overflow;
@@ -1898,11 +1898,12 @@ static noinline int copy_to_sk(struct btrfs_root *root,
                         * handle -EOVERFLOW
                         */
 
+                       *buf_size = sizeof(sh) + item_len;
                        item_len = 0;
                        ret = -EOVERFLOW;
                }
 
-               if (sizeof(sh) + item_len + *sk_offset > buf_size) {
+               if (sizeof(sh) + item_len + *sk_offset > *buf_size) {
                        ret = 1;
                        goto overflow;
                }
@@ -1951,7 +1952,7 @@ overflow:
 
 static noinline int search_ioctl(struct inode *inode,
                                 struct btrfs_ioctl_search_key *sk,
-                                size_t buf_size,
+                                size_t *buf_size,
                                 char *buf)
 {
        struct btrfs_root *root;
@@ -1962,8 +1963,10 @@ static noinline int search_ioctl(struct inode *inode,
        int num_found = 0;
        unsigned long sk_offset = 0;
 
-       if (buf_size < sizeof(struct btrfs_ioctl_search_header))
+       if (*buf_size < sizeof(struct btrfs_ioctl_search_header)) {
+               *buf_size = sizeof(struct btrfs_ioctl_search_header);
                return -EOVERFLOW;
+       }
 
        path = btrfs_alloc_path();
        if (!path)
@@ -2016,9 +2019,10 @@ err:
 static noinline int btrfs_ioctl_tree_search(struct file *file,
                                           void __user *argp)
 {
-        struct btrfs_ioctl_search_args *args;
-        struct inode *inode;
-        int ret;
+       struct btrfs_ioctl_search_args *args;
+       struct inode *inode;
+       int ret;
+       size_t buf_size;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -2027,8 +2031,10 @@ static noinline int btrfs_ioctl_tree_search(struct file 
*file,
        if (IS_ERR(args))
                return PTR_ERR(args);
 
+       buf_size = sizeof(args->buf);
+
        inode = file_inode(file);
-       ret = search_ioctl(inode, &args->key, sizeof(args->buf), args->buf);
+       ret = search_ioctl(inode, &args->key, &buf_size, args->buf);
 
        /*
         * In the origin implementation an overflow is handled by returning a
-- 
1.8.5.3

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to