Before device_register, if something goes wrong, we need to manually free idev.
In the error handling path, after device_unregister, idev maybe have been released, we should not use it anymore. Signed-off-by: liujian <liujia...@huawei.com> --- drivers/uio/uio.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 1313422..5c10fc7 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -413,13 +413,18 @@ static int uio_get_minor(struct uio_device *idev) return retval; } -static void uio_free_minor(struct uio_device *idev) +static void __uio_free_minor(int id) { mutex_lock(&minor_lock); - idr_remove(&uio_idr, idev->minor); + idr_remove(&uio_idr, id); mutex_unlock(&minor_lock); } +static void uio_free_minor(struct uio_device *idev) +{ + __uio_free_minor(idev->minor); +} + /** * uio_event_notify - trigger an interrupt event * @info: UIO device capabilities @@ -919,6 +924,7 @@ int __uio_register_device(struct module *owner, { struct uio_device *idev; int ret = 0; + int uio_minor; if (!uio_class_registered) return -EPROBE_DEFER; @@ -940,8 +946,12 @@ int __uio_register_device(struct module *owner, atomic_set(&idev->event, 0); ret = uio_get_minor(idev); - if (ret) + if (ret) { + kfree(idev); return ret; + } + + uio_minor = idev->minor; idev->dev.devt = MKDEV(uio_major, idev->minor); idev->dev.class = &uio_class; @@ -950,8 +960,11 @@ int __uio_register_device(struct module *owner, dev_set_drvdata(&idev->dev, idev); ret = dev_set_name(&idev->dev, "uio%d", idev->minor); - if (ret) - goto err_device_create; + if (ret) { + __uio_free_minor(uio_minor); + kfree(idev); + return ret; + } ret = device_register(&idev->dev); if (ret) @@ -987,7 +1000,7 @@ int __uio_register_device(struct module *owner, err_uio_dev_add_attributes: device_unregister(&idev->dev); err_device_create: - uio_free_minor(idev); + __uio_free_minor(uio_minor); return ret; } EXPORT_SYMBOL_GPL(__uio_register_device); -- 2.7.4