Commit 7637aaaf authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Zheng Qixing
Browse files

block: fix integer overflow in BLKSECDISCARD

mainline inclusion
from mainline-v6.12-rc1
commit 697ba0b6ec4ae04afb67d3911799b5e2043b4455
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAYRAS
CVE: CVE-2024-49994

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=697ba0b6ec4ae04afb67d3911799b5e2043b4455



--------------------------------

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: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Link: https://lore.kernel.org/r/9e64057f-650a-46d1-b9f7-34af391536ef@p183


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>

Conflicts:
	block/ioctl.c
[The conflict occurs because commit 881494ed031f ("blk_ioctl_{
discard,zeroout}(): we only want ->bd_inode->i_mapping here...")
is not introduced.]
Signed-off-by: default avatarZheng Qixing <zhengqixing@huawei.com>
parent a42fc9da
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
		return -EINVAL;

	filemap_invalidate_lock(inode->i_mapping);
	err = truncate_bdev_range(bdev, mode, start, start + len - 1);
	err = truncate_bdev_range(bdev, mode, start, end - 1);
	if (err)
		goto fail;
	err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL);
@@ -127,7 +127,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,
		void __user *argp)
{
	uint64_t start, len;
	uint64_t start, len, end;
	uint64_t range[2];
	int err;

@@ -142,11 +142,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_inode->i_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);