[PATCH openEuler-1.0-LTS v3 0/2] fix CVE-2025-38709

fix CVE-2025-38709 Christoph Hellwig (1): block: use bd_prepare_to_claim directly in the loop driver Jan Kara (1): loop: Avoid updating block size under exclusive owner block/blk.h | 4 ---- drivers/block/loop.c | 46 ++++++++++++++++++++++++++++++++++---------- fs/block_dev.c | 1 + include/linux/fs.h | 4 ++++ 4 files changed, 41 insertions(+), 14 deletions(-) -- 2.39.2

From: Christoph Hellwig <hch@lst.de> mainline inclusion from mainline-v5.9-rc1 commit ecbe6bc0003bfd5bf8581cb679cae0eb944432cb category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICWGGN CVE: CVE-2025-38709 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------ The arcane magic in bd_start_claiming is only needed to be able to claim a block_device that hasn't been fully set up. Switch the loop driver that claims from the ioctl path with a fully set up struct block_device to just use the much simpler bd_prepare_to_claim directly. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <axboe@kernel.dk> Conflicts: drivers/block/loop.c fs/block_dev.c include/linux/fs.h include/linux/blkdev.h block/blk.h [Export bd_prepare_to_claim.] Signed-off-by: Zheng Qixing <zhengqixing@huawei.com> --- block/blk.h | 4 ---- fs/block_dev.c | 1 + include/linux/fs.h | 4 ++++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/block/blk.h b/block/blk.h index 30146e2099e3..2730b239f158 100644 --- a/block/blk.h +++ b/block/blk.h @@ -273,10 +273,6 @@ unsigned int blk_plug_queued_count(struct request_queue *q); void blk_account_io_start(struct request *req, bool new_io); void blk_account_io_completion(struct request *req, unsigned int bytes); void blk_account_io_done(struct request *req, u64 now); -int bd_prepare_to_claim(struct block_device *bdev, - struct block_device *whole, void *holder); -void bd_abort_claiming(struct block_device *bdev, struct block_device *whole, - void *holder); /* * EH timer and IO completion will both attempt to 'grab' the request, make diff --git a/fs/block_dev.c b/fs/block_dev.c index e072d1ef16ef..6d3e4356392a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1100,6 +1100,7 @@ int bd_prepare_to_claim(struct block_device *bdev, spin_unlock(&bdev_lock); return 0; } +EXPORT_SYMBOL_GPL(bd_prepare_to_claim); /* only for the loop driver */ static void bd_clear_claiming(struct block_device *whole, void *holder) { diff --git a/include/linux/fs.h b/include/linux/fs.h index 1c9aac073db1..584957a75822 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2645,6 +2645,10 @@ extern struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, void *holder); extern struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder); +extern int bd_prepare_to_claim(struct block_device *bdev, + struct block_device *whole, void *holder); +extern void bd_abort_claiming(struct block_device *bdev, + struct block_device *whole, void *holder); extern void blkdev_put(struct block_device *bdev, fmode_t mode); extern int __blkdev_reread_part(struct block_device *bdev); extern int blkdev_reread_part(struct block_device *bdev); -- 2.39.2

From: Jan Kara <jack@suse.cz> mainline inclusion from mainline-v6.17-rc1 commit 7e49538288e523427beedd26993d446afef1a6fb category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICWGGN CVE: CVE-2025-38709 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------ Syzbot came up with a reproducer where a loop device block size is changed underneath a mounted filesystem. This causes a mismatch between the block device block size and the block size stored in the superblock causing confusion in various places such as fs/buffer.c. The particular issue triggered by syzbot was a warning in __getblk_slow() due to requested buffer size not matching block device block size. Fix the problem by getting exclusive hold of the loop device to change its block size. This fails if somebody (such as filesystem) has already an exclusive ownership of the block device and thus prevents modifying the loop device under some exclusive owner which doesn't expect it. Reported-by: syzbot+01ef7a8da81a975e1ccd@syzkaller.appspotmail.com Signed-off-by: Jan Kara <jack@suse.cz> Tested-by: syzbot+01ef7a8da81a975e1ccd@syzkaller.appspotmail.com Link: https://lore.kernel.org/r/20250711163202.19623-2-jack@suse.cz Signed-off-by: Jens Axboe <axboe@kernel.dk> Conflicts: drivers/block/loop.c [Context conflicts due to not merging commit 98ded54a3383, 473516b36193, ae0d40ff4964, 9423c653fe61, b38c8be255e8, b03732a9c0db and 1e1a9cecfab3.] Signed-off-by: Zheng Qixing <zhengqixing@huawei.com> --- drivers/block/loop.c | 46 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 026cde240c4a..5be6bdc9f201 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1513,15 +1513,37 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg) return error; } -static int loop_set_block_size(struct loop_device *lo, unsigned long arg) +static int loop_set_block_size(struct loop_device *lo, fmode_t mode, + struct block_device *bdev, unsigned long arg) { + struct block_device *claimed_bdev = NULL; int err = 0; - if (lo->lo_state != Lo_bound) - return -ENXIO; + /* + * If we don't hold exclusive handle for the device, upgrade to it + * here to avoid changing device under exclusive owner. + */ + if (!(mode & FMODE_EXCL)) { + claimed_bdev = bdev->bd_contains; + err = bd_prepare_to_claim(bdev, claimed_bdev, + loop_set_block_size); + if (err) + return err; + } - if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg)) - return -EINVAL; + err = mutex_lock_killable(&loop_ctl_mutex); + if (err) + goto abort_claim; + + if (lo->lo_state != Lo_bound) { + err = -ENXIO; + goto unlock; + } + + if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg)) { + err = -EINVAL; + goto unlock; + } if (lo->lo_queue->limits.logical_block_size != arg) { sync_blockdev(lo->lo_device); @@ -1546,7 +1568,11 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) loop_update_dio(lo); out_unfreeze: blk_mq_unfreeze_queue(lo->lo_queue); - +unlock: + mutex_unlock(&loop_ctl_mutex); +abort_claim: + if (claimed_bdev) + bd_abort_claiming(bdev, claimed_bdev, loop_set_block_size); return err; } @@ -1565,9 +1591,6 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd, case LOOP_SET_DIRECT_IO: err = loop_set_dio(lo, arg); break; - case LOOP_SET_BLOCK_SIZE: - err = loop_set_block_size(lo, arg); - break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } @@ -1606,9 +1629,12 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, break; case LOOP_GET_STATUS64: return loop_get_status64(lo, (struct loop_info64 __user *) arg); + case LOOP_SET_BLOCK_SIZE: + if (!(mode & FMODE_WRITE) && !capable(CAP_SYS_ADMIN)) + return -EPERM; + return loop_set_block_size(lo, mode, bdev, arg); case LOOP_SET_CAPACITY: case LOOP_SET_DIRECT_IO: - case LOOP_SET_BLOCK_SIZE: if (!(mode & FMODE_WRITE) && !capable(CAP_SYS_ADMIN)) return -EPERM; /* Fall through */ -- 2.39.2

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/18193 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/SM5... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/18193 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/SM5...
participants (2)
-
patchwork bot
-
Zheng Qixing