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

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: 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
...@@ -532,19 +532,20 @@ int bdev_add_partition(struct block_device *bdev, int partno, ...@@ -532,19 +532,20 @@ int bdev_add_partition(struct block_device *bdev, int partno,
int bdev_del_partition(struct block_device *bdev, int partno) int bdev_del_partition(struct block_device *bdev, int partno)
{ {
struct block_device *bdevp; struct block_device *bdevp;
struct hd_struct *part; struct hd_struct *part = NULL;
int ret = 0; int ret;
part = disk_get_part(bdev->bd_disk, partno);
if (!part)
return -ENXIO;
ret = -ENOMEM; bdevp = bdget_disk(bdev->bd_disk, partno);
bdevp = bdget(part_devt(part));
if (!bdevp) if (!bdevp)
goto out_put_part; return -ENOMEM;
mutex_lock(&bdevp->bd_mutex); 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; ret = -EBUSY;
if (bdevp->bd_openers) if (bdevp->bd_openers)
...@@ -553,16 +554,14 @@ int bdev_del_partition(struct block_device *bdev, int partno) ...@@ -553,16 +554,14 @@ int bdev_del_partition(struct block_device *bdev, int partno)
sync_blockdev(bdevp); sync_blockdev(bdevp);
invalidate_bdev(bdevp); invalidate_bdev(bdevp);
mutex_lock_nested(&bdev->bd_mutex, 1);
delete_partition(bdev->bd_disk, part); delete_partition(bdev->bd_disk, part);
mutex_unlock(&bdev->bd_mutex);
ret = 0; ret = 0;
out_unlock: out_unlock:
mutex_unlock(&bdev->bd_mutex);
mutex_unlock(&bdevp->bd_mutex); mutex_unlock(&bdevp->bd_mutex);
bdput(bdevp); bdput(bdevp);
out_put_part: if (part)
disk_put_part(part); disk_put_part(part);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment