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

Reply via email to