diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2024-09-03 21:48:19 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2024-09-04 16:01:30 +0200 |
commit | 697ba0b6ec4ae04afb67d3911799b5e2043b4455 (patch) | |
tree | 38022d38f2b195c3285c41326b6011ba7431d31b /block | |
parent | block: fix comment to use set_current_state (diff) | |
download | linux-697ba0b6ec4ae04afb67d3911799b5e2043b4455.tar.xz linux-697ba0b6ec4ae04afb67d3911799b5e2043b4455.zip |
block: fix integer overflow in BLKSECDISCARD
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>
Diffstat (limited to 'block')
-rw-r--r-- | block/ioctl.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/block/ioctl.c b/block/ioctl.c index e8e4a4190f18..44257bdfeacb 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -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); |