mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
block: fix error unwinding in device_add_disk
One device_add is called disk->ev will be freed by disk_release, so we
should free it twice. Fix this by allocating disk->ev after device_add
so that the extra local unwinding can be removed entirely.
Based on an earlier patch from Tetsuo Handa.
Reported-by: syzbot <syzbot+28a66a9fbc621c939000@syzkaller.appspotmail.com>
Tested-by: syzbot <syzbot+28a66a9fbc621c939000@syzkaller.appspotmail.com>
Fixes: 83cbce9574
("block: add error handling for device_add_disk / add_disk")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20211221161851.788424-1-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
37e11c3616
commit
99d8690aae
@ -442,10 +442,6 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
|
|||||||
disk->first_minor = ret;
|
disk->first_minor = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = disk_alloc_events(disk);
|
|
||||||
if (ret)
|
|
||||||
goto out_free_ext_minor;
|
|
||||||
|
|
||||||
/* delay uevents, until we scanned partition table */
|
/* delay uevents, until we scanned partition table */
|
||||||
dev_set_uevent_suppress(ddev, 1);
|
dev_set_uevent_suppress(ddev, 1);
|
||||||
|
|
||||||
@ -456,7 +452,12 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
|
|||||||
ddev->devt = MKDEV(disk->major, disk->first_minor);
|
ddev->devt = MKDEV(disk->major, disk->first_minor);
|
||||||
ret = device_add(ddev);
|
ret = device_add(ddev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_disk_release_events;
|
goto out_free_ext_minor;
|
||||||
|
|
||||||
|
ret = disk_alloc_events(disk);
|
||||||
|
if (ret)
|
||||||
|
goto out_device_del;
|
||||||
|
|
||||||
if (!sysfs_deprecated) {
|
if (!sysfs_deprecated) {
|
||||||
ret = sysfs_create_link(block_depr, &ddev->kobj,
|
ret = sysfs_create_link(block_depr, &ddev->kobj,
|
||||||
kobject_name(&ddev->kobj));
|
kobject_name(&ddev->kobj));
|
||||||
@ -538,8 +539,6 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
|
|||||||
sysfs_remove_link(block_depr, dev_name(ddev));
|
sysfs_remove_link(block_depr, dev_name(ddev));
|
||||||
out_device_del:
|
out_device_del:
|
||||||
device_del(ddev);
|
device_del(ddev);
|
||||||
out_disk_release_events:
|
|
||||||
disk_release_events(disk);
|
|
||||||
out_free_ext_minor:
|
out_free_ext_minor:
|
||||||
if (disk->major == BLOCK_EXT_MAJOR)
|
if (disk->major == BLOCK_EXT_MAJOR)
|
||||||
blk_free_ext_minor(disk->first_minor);
|
blk_free_ext_minor(disk->first_minor);
|
||||||
|
Loading…
Reference in New Issue
Block a user