Btrfs: fix up bounds checking in lseek
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / btrfs / file.c
index 0165b86..a9a881e 100644 (file)
@@ -2510,23 +2510,28 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence)
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_map *em = NULL;
        struct extent_state *cached_state = NULL;
-       u64 lockstart = *offset;
-       u64 lockend = i_size_read(inode);
-       u64 start = *offset;
-       u64 len = i_size_read(inode);
+       u64 lockstart;
+       u64 lockend;
+       u64 start;
+       u64 len;
        int ret = 0;
 
-       lockend = max_t(u64, root->sectorsize, lockend);
+       if (inode->i_size == 0)
+               return -ENXIO;
+
+       /*
+        * *offset can be negative, in this case we start finding DATA/HOLE from
+        * the very start of the file.
+        */
+       start = max_t(loff_t, 0, *offset);
+
+       lockstart = round_down(start, root->sectorsize);
+       lockend = round_up(i_size_read(inode), root->sectorsize);
        if (lockend <= lockstart)
                lockend = lockstart + root->sectorsize;
-
        lockend--;
        len = lockend - lockstart + 1;
 
-       len = max_t(u64, len, root->sectorsize);
-       if (inode->i_size == 0)
-               return -ENXIO;
-
        lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0,
                         &cached_state);