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: cddae808ae
("block: pass a hd_struct to delete_partition")
Reported-by: syzbot+6448f3c229bc52b82f69@syzkaller.appspotmail.com
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
cafe01ef8f
commit
08fc1ab6d7
@ -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);
|
bdevp = bdget_disk(bdev->bd_disk, partno);
|
||||||
if (!part)
|
|
||||||
return -ENXIO;
|
|
||||||
|
|
||||||
ret = -ENOMEM;
|
|
||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user