Commit 08fc1ab6 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

block: fix locking in bdev_del_partition



We need to hold the whole device bd_mutex to protect against
other thread concurrently deleting out partition before we get
to it, and thus causing a use after free.

Fixes: cddae808 ("block: pass a hd_struct to delete_partition")
Reported-by: default avatar <syzbot+6448f3c229bc52b82f69@syzkaller.appspotmail.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent cafe01ef
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -532,19 +532,20 @@ int bdev_add_partition(struct block_device *bdev, int partno,
int bdev_del_partition(struct block_device *bdev, int partno)
{
	struct block_device *bdevp;
	struct hd_struct *part;
	int ret = 0;

	part = disk_get_part(bdev->bd_disk, partno);
	if (!part)
		return -ENXIO;
	struct hd_struct *part = NULL;
	int ret;

	ret = -ENOMEM;
	bdevp = bdget(part_devt(part));
	bdevp = bdget_disk(bdev->bd_disk, partno);
	if (!bdevp)
		goto out_put_part;
		return -ENOMEM;

	mutex_lock(&bdevp->bd_mutex);
	mutex_lock_nested(&bdev->bd_mutex, 1);

	ret = -ENXIO;
	part = disk_get_part(bdev->bd_disk, partno);
	if (!part)
		goto out_unlock;

	ret = -EBUSY;
	if (bdevp->bd_openers)
@@ -553,15 +554,13 @@ int bdev_del_partition(struct block_device *bdev, int partno)
	sync_blockdev(bdevp);
	invalidate_bdev(bdevp);

	mutex_lock_nested(&bdev->bd_mutex, 1);
	delete_partition(bdev->bd_disk, part);
	mutex_unlock(&bdev->bd_mutex);

	ret = 0;
out_unlock:
	mutex_unlock(&bdev->bd_mutex);
	mutex_unlock(&bdevp->bd_mutex);
	bdput(bdevp);
out_put_part:
	if (part)
		disk_put_part(part);
	return ret;
}