[<prev] [next>] [day] [month] [year] [list]
Message-ID: <1546443740-22370-1-git-send-email-liujian56@huawei.com>
Date: Wed, 2 Jan 2019 23:42:20 +0800
From: liujian <liujian56@...wei.com>
To: <gregkh@...uxfoundation.org>, <hamish.martin@...iedtelesis.co.nz>
CC: <liujian56@...wei.com>, <linux-kernel@...r.kernel.org>
Subject: [PATCH] driver: uio: fix possible memory leak and use-after-free in __uio_register_device
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 <liujian56@...wei.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
Powered by blists - more mailing lists