Skip to content

Commit 08fc1ab

Browse files
Christoph Hellwigaxboe
authored andcommitted
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: cddae80 ("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>
1 parent cafe01e commit 08fc1ab

File tree

1 file changed

+13
-14
lines changed

1 file changed

+13
-14
lines changed

block/partitions/core.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -532,19 +532,20 @@ int bdev_add_partition(struct block_device *bdev, int partno,
532532
int bdev_del_partition(struct block_device *bdev, int partno)
533533
{
534534
struct block_device *bdevp;
535-
struct hd_struct *part;
536-
int ret = 0;
537-
538-
part = disk_get_part(bdev->bd_disk, partno);
539-
if (!part)
540-
return -ENXIO;
535+
struct hd_struct *part = NULL;
536+
int ret;
541537

542-
ret = -ENOMEM;
543-
bdevp = bdget(part_devt(part));
538+
bdevp = bdget_disk(bdev->bd_disk, partno);
544539
if (!bdevp)
545-
goto out_put_part;
540+
return -ENOMEM;
546541

547542
mutex_lock(&bdevp->bd_mutex);
543+
mutex_lock_nested(&bdev->bd_mutex, 1);
544+
545+
ret = -ENXIO;
546+
part = disk_get_part(bdev->bd_disk, partno);
547+
if (!part)
548+
goto out_unlock;
548549

549550
ret = -EBUSY;
550551
if (bdevp->bd_openers)
@@ -553,16 +554,14 @@ int bdev_del_partition(struct block_device *bdev, int partno)
553554
sync_blockdev(bdevp);
554555
invalidate_bdev(bdevp);
555556

556-
mutex_lock_nested(&bdev->bd_mutex, 1);
557557
delete_partition(bdev->bd_disk, part);
558-
mutex_unlock(&bdev->bd_mutex);
559-
560558
ret = 0;
561559
out_unlock:
560+
mutex_unlock(&bdev->bd_mutex);
562561
mutex_unlock(&bdevp->bd_mutex);
563562
bdput(bdevp);
564-
out_put_part:
565-
disk_put_part(part);
563+
if (part)
564+
disk_put_part(part);
566565
return ret;
567566
}
568567

0 commit comments

Comments
 (0)