[PATCH] media: fix media_device_unregister() to destroy media device device resource

From: Shuah Khan
Date: Thu Mar 17 2016 - 18:46:52 EST


When all drivers except usb-core driver is unbound, destroy the media device
resource. Other wise, media device resource will persist in a defunct state.
This leads to use-after-free and bad access errors during a subsequent bind.
Fix it to destroy the media device resource when last reference is released
in media_device_unregister().

Signed-off-by: Shuah Khan <shuahkh@xxxxxxxxxxxxxxx>
---
drivers/media/media-device.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 070421e..7312612 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -822,22 +822,38 @@ printk("%s: mdev=%p\n", __func__, mdev);
dev_dbg(mdev->dev, "Media device unregistered\n");
}

+static void media_device_release_devres(struct device *dev, void *res)
+{
+}
+
+static void media_device_destroy_devres(struct device *dev)
+{
+ int ret;
+
+ ret = devres_destroy(dev, media_device_release_devres, NULL, NULL);
+ pr_debug("%s: devres_destroy() returned %d\n", __func__, ret);
+}
+
void media_device_unregister(struct media_device *mdev)
{
+ int ret;
+ struct device *dev;
printk("%s: mdev=%p\n", __func__, mdev);
if (mdev == NULL)
return;

- mutex_lock(&mdev->graph_mutex);
- kref_put(&mdev->kref, do_media_device_unregister);
- mutex_unlock(&mdev->graph_mutex);
+ ret = kref_put_mutex(&mdev->kref, do_media_device_unregister,
+ &mdev->graph_mutex);
+ if (ret) {
+ /* do_media_device_unregister() has run */
+ dev = mdev->dev;
+ mutex_unlock(&mdev->graph_mutex);
+ media_device_destroy_devres(dev);
+ }

}
EXPORT_SYMBOL_GPL(media_device_unregister);

-static void media_device_release_devres(struct device *dev, void *res)
-{
-}

struct media_device *media_device_get_devres(struct device *dev)
{
--
2.5.0