]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
block: fix integer overflow in BLKSECDISCARD
authorAlexey Dobriyan <adobriyan@gmail.com>
Tue, 3 Sep 2024 19:48:19 +0000 (22:48 +0300)
committerJens Axboe <axboe@kernel.dk>
Wed, 4 Sep 2024 14:01:30 +0000 (08:01 -0600)
I independently rediscovered

commit 22d24a544b0d49bbcbd61c8c0eaf77d3c9297155
block: fix overflow in blk_ioctl_discard()

but for secure erase.

Same problem:

uint64_t r[2] = {512, 18446744073709551104ULL};
ioctl(fd, BLKSECDISCARD, r);

will enter near infinite loop inside blkdev_issue_secure_erase():

a.out: attempt to access beyond end of device
loop0: rw=5, sector=3399043073, nr_sectors = 1024 limit=2048
bio_check_eod: 3286214 callbacks suppressed

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Link: https://lore.kernel.org/r/9e64057f-650a-46d1-b9f7-34af391536ef@p183
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/ioctl.c

index e8e4a4190f183a467567c7d554b8215982a01407..44257bdfeacbf4b4474b3e8a257fd7ab4442b897 100644 (file)
@@ -126,7 +126,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
                return -EINVAL;
 
        filemap_invalidate_lock(bdev->bd_mapping);
-       err = truncate_bdev_range(bdev, mode, start, start + len - 1);
+       err = truncate_bdev_range(bdev, mode, start, end - 1);
        if (err)
                goto fail;
 
@@ -163,7 +163,7 @@ fail:
 static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
                void __user *argp)
 {
-       uint64_t start, len;
+       uint64_t start, len, end;
        uint64_t range[2];
        int err;
 
@@ -178,11 +178,12 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
        len = range[1];
        if ((start & 511) || (len & 511))
                return -EINVAL;
-       if (start + len > bdev_nr_bytes(bdev))
+       if (check_add_overflow(start, len, &end) ||
+           end > bdev_nr_bytes(bdev))
                return -EINVAL;
 
        filemap_invalidate_lock(bdev->bd_mapping);
-       err = truncate_bdev_range(bdev, mode, start, start + len - 1);
+       err = truncate_bdev_range(bdev, mode, start, end - 1);
        if (!err)
                err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
                                                GFP_KERNEL);