On 28.05.19 г. 11:21 ч., Qu Wenruo wrote:
> Normally the range->len is set to default value (U64_MAX), but when it's
> not default value, we should check if the range overflows.
>
> And if overflows, return -EINVAL before doing anything.
>
> Signed-off-by: Qu Wenruo <w...@suse.com>
Reviewed-by: Nikolay Borisov <nbori...@suse.com>
> ---
> fs/btrfs/extent-tree.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index f79e477a378e..62bfba6d3c07 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -11245,6 +11245,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info,
> struct fstrim_range *range)
> struct btrfs_device *device;
> struct list_head *devices;
> u64 group_trimmed;
> + u64 range_end = U64_MAX;
> u64 start;
> u64 end;
> u64 trimmed = 0;
> @@ -11254,16 +11255,23 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info,
> struct fstrim_range *range)
> int dev_ret = 0;
> int ret = 0;
>
> + /*
> + * Check range overflow if range->len is set.
> + * The default range->len is U64_MAX.
> + */
> + if (range->len != U64_MAX && check_add_overflow(range->start,
> + range->len, &range_end))
> + return -EINVAL;
> +
> cache = btrfs_lookup_first_block_group(fs_info, range->start);
> for (; cache; cache = next_block_group(cache)) {
> - if (cache->key.objectid >= (range->start + range->len)) {
> + if (cache->key.objectid >= range_end) {
> btrfs_put_block_group(cache);
> break;
> }
>
> start = max(range->start, cache->key.objectid);
> - end = min(range->start + range->len,
> - cache->key.objectid + cache->key.offset);
> + end = min(range_end, cache->key.objectid + cache->key.offset);
>
> if (end - start >= range->minlen) {
> if (!block_group_cache_done(cache)) {
>