block: fix integer overflow in BLKSECDISCARD
I independently rediscovered
commit 22d24a544b
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>
This commit is contained in:
parent
2be6190cd7
commit
697ba0b6ec
@ -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 @@ fail:
|
|||||||
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,
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user