From: Christoph Hellwig hch@lst.de
mainline inclusion from mainline-v5.17-rc1 commit 99d8690aae4b2f0d1d90075de355ac087f820a66 category: bugfix bugzilla: 188733, https://gitee.com/openeuler/kernel/issues/I81XCK
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
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: 83cbce9574462c6b ("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 conflict: block/genhd.c Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com --- block/genhd.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/block/genhd.c b/block/genhd.c index 96db5ae191d6..878d521523a2 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -800,10 +800,6 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, disk->major = MAJOR(devt); disk->first_minor = MINOR(devt);
- retval = disk_alloc_events(disk); - if (retval) - goto out_free_ext_minor; - if (disk->flags & GENHD_FL_HIDDEN) { /* * Don't let hidden disks show up in /proc/partitions, @@ -818,7 +814,7 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, ddev->devt = devt; retval = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); if (retval) - goto out_disk_release_events; + goto out_free_ext_minor; bdi_set_owner(bdi, ddev); retval = blk_register_region(disk_devt(disk), disk->minors, NULL, exact_match, exact_lock, disk); @@ -838,6 +834,9 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, retval = device_add(ddev); if (retval) goto out_unregister_region; + retval = disk_alloc_events(disk); + if (retval) + goto out_device_del; if (!sysfs_deprecated) { retval = sysfs_create_link(block_depr, &ddev->kobj, kobject_name(&ddev->kobj)); @@ -921,8 +920,6 @@ static int __device_add_disk(struct device *parent, struct gendisk *disk, out_unregister_bdi: if (!(disk->flags & GENHD_FL_HIDDEN)) bdi_unregister(disk->queue->backing_dev_info); -out_disk_release_events: - disk_release_events(disk); out_free_ext_minor: blk_free_devt(devt); return WARN_ON_ONCE(retval); /* keep until all callers handle errors */