From cebb1c2331c2af1b7f1c822ac672a7f77b54bd90 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 28 Oct 2026 10:41:07 -0600 Subject: [PATCH] block: fix use-after-free of the disk in sync_bdevs() sync_bdevs() holds a reference to the bdev inode while it takes bd_disk->open_mutex. For a partition the inode doesn't keep the gendisk alive, the device reference does: part_release() drops the disk as soon as the last reference to the partition device is gone. A sync(2) racing with the last close of a partition of an already deleted disk locks a freed open_mutex. Take a device reference before touching the disk, like blkdev_get_no_open() does, and skip the bdev if it's on its way out. Fixes: a8698707a183 ("block: move bd_mutex to struct gendisk") Signed-off-by: Josef Bacik Reviewed-by: Christoph Hellwig Link: https://patch.msgid.link/20261028164415.1262013-5-axboe@kernel.dk Signed-off-by: Jens Axboe --- block/bdev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/block/bdev.c b/block/bdev.c index fac74319e9fb..cc35126e483d 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -1366,6 +1366,15 @@ void sync_bdevs(bool wait) old_inode = inode; bdev = I_BDEV(inode); + /* + * The inode does not keep the gendisk of a partition alive, the + * device does. + */ + if (!kobject_get_unless_zero(&bdev->bd_device.kobj)) { + spin_lock(&blockdev_superblock->s_inode_list_lock); + continue; + } + mutex_lock(&bdev->bd_disk->open_mutex); if (!atomic_read(&bdev->bd_openers)) { ; /* skip */ @@ -1381,6 +1390,7 @@ void sync_bdevs(bool wait) filemap_fdatawrite(inode->i_mapping); } mutex_unlock(&bdev->bd_disk->open_mutex); + put_device(&bdev->bd_device); spin_lock(&blockdev_superblock->s_inode_list_lock); }