Commit 697ba0b6 authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Jens Axboe

block: fix integer overflow in BLKSECDISCARD

I independently rediscovered

	commit 22d24a54
	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: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Link: https://lore.kernel.org/r/9e64057f-650a-46d1-b9f7-34af391536ef@p183Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 2be6190c
...@@ -126,7 +126,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, ...@@ -126,7 +126,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
return -EINVAL; return -EINVAL;
filemap_invalidate_lock(bdev->bd_mapping); 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) if (err)
goto fail; goto fail;
...@@ -163,7 +163,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, ...@@ -163,7 +163,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
void __user *argp) void __user *argp)
{ {
uint64_t start, len; uint64_t start, len, end;
uint64_t range[2]; uint64_t range[2];
int err; int err;
...@@ -178,11 +178,12 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, ...@@ -178,11 +178,12 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode,
len = range[1]; len = range[1];
if ((start & 511) || (len & 511)) if ((start & 511) || (len & 511))
return -EINVAL; return -EINVAL;
if (start + len > bdev_nr_bytes(bdev)) if (check_add_overflow(start, len, &end) ||
end > bdev_nr_bytes(bdev))
return -EINVAL; return -EINVAL;
filemap_invalidate_lock(bdev->bd_mapping); 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) if (!err)
err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9, err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
GFP_KERNEL); GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment