Skip to contentSkip to conversation

drm/mediatek: fix device use-after-free on unbind

PATCH Applied Johan Hovold 6 participants 7 messages Oct 6, 2025 – Oct 28, 2025

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drm/mediatek: fix device use-after-free on unbind

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free.

Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in mtk_drm_get_all_drm_priv")
Cc AngeloGioacchino Del Regno <[email protected]>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 10 ----------
 1 file changed, 10 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -10
index 384b0510272c..a94c51a83261 100644
@@ -686,10 +686,6 @@ static int mtk_drm_bind(struct device *dev)
 	for (i = 0; i < private->data->mmsys_dev_num; i++)
 		private->all_drm_private[i]->drm = NULL;
 err_put_dev:
-	for (i = 0; i < private->data->mmsys_dev_num; i++) {
-		/* For device_find_child in mtk_drm_get_all_priv() */
-		put_device(private->all_drm_private[i]->dev);
-	}
 	put_device(private->mutex_dev);
 	return ret;
 }
@@ -697,18 +693,12 @@ static int mtk_drm_bind(struct device *dev)
 static void mtk_drm_unbind(struct device *dev)
 {
 	struct mtk_drm_private *private = dev_get_drvdata(dev);
-	int i;
 
 	/* for multi mmsys dev, unregister drm dev in mmsys master */
 	if (private->drm_master) {
 		drm_dev_unregister(private->drm);
 		mtk_drm_kms_deinit(private->drm);
 		drm_dev_put(private->drm);
-
-		for (i = 0; i < private->data->mmsys_dev_num; i++) {
-			/* For device_find_child in mtk_drm_get_all_priv() */
-			put_device(private->all_drm_private[i]->dev);
-		}
 		put_device(private->mutex_dev);
 	}
 	private->mtk_drm_bound = false;
Signature · 1 line
2.49.1
maintainer Reviewed-by on v1 1/1
#1 lore raw

Il 06/10/25 11:39, Johan Hovold ha scritto:

Quoted 14 lines

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free.

Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Quoted 7 lines
Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in mtk_drm_get_all_drm_priv")
Cc AngeloGioacchino Del Regno <[email protected]>

Heh, nice!

Reviewed-by Tested-by on v1 1/1
#2 lore raw
In reply to Johan Hovold
Quoted 5 lines · Johan Hovold

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

Quoted 8 lines

This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free.

Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Thanks for correcting my "fix". This looks better and i can confirm it fixes the issue :)

Quoted 47 lines
Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in

mtk_drm_get_all_drm_priv")

---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 10 ----------

 1 file changed, 10 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -0
index 384b0510272c..a94c51a83261 100644
@@ -686,10 +686,6 @@ static int mtk_drm_bind(struct device *dev)
  	for (i = 0; i < private->data->mmsys_dev_num; i++)
  		private->all_drm_private[i]->drm = NULL;

 err_put_dev:

drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -4
-	for (i = 0; i < private->data->mmsys_dev_num; i++) {
-		/* For device_find_child in mtk_drm_get_all_priv() */
-		put_device(private->all_drm_private[i]->dev);
-	}

  put_device(private->mutex_dev);
  return ret;
 }

drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -1
@@ -697,18 +693,12 @@ static int mtk_drm_bind(struct device *dev)
  static void mtk_drm_unbind(struct device *dev)
  {
  	struct mtk_drm_private *private = dev_get_drvdata(dev);
-	int i;


  /* for multi mmsys dev, unregister drm dev in mmsys master */ if (private->drm_master) { drm_dev_unregister(private->drm); mtk_drm_kms_deinit(private->drm); drm_dev_put(private->drm);

drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -5
-
-		for (i = 0; i < private->data->mmsys_dev_num; i++) {
-			/* For device_find_child in mtk_drm_get_all_priv() */
-			put_device(private->all_drm_private[i]->dev);
-		}

  put_device(private->mutex_dev);
  }
  private->mtk_drm_bound = false;

Tested-by on v1 1/1
#3 lore raw
In reply to Johan Hovold
Quoted 10 lines · Johan Hovold

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial
fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

This results in a reference imbalance on component bind() failures and
on unbind() which could lead to a user-after-free.

Quoted 7 lines

Make sure to only drop the references after retrieving the driver data
by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

We ran into the same issue in mesaci[1] and have test validated this proposed fix. It was tested with Linux 6.17.3 + this fix.

[1] https://gitlab.freedesktop.org/RickXy/mesa/-/jobs/86389548

Quoted 10 lines
Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count

leaks in mtk_drm_get_all_drm_priv")

Link:
https://lore.kernel.org/r/[email protected]
Cc: [email protected]
Cc: Ma Ke <[email protected]>
Cc: AngeloGioacchino Del Regno
<[email protected]>

Signature · 2 lines
Ritesh Raj Sarraf
Collabora
#4 lore raw
In reply to Johan Hovold

Hi Chun-Kuang,

Quoted 14 lines · Johan Hovold

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free.

Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Quoted 7 lines
Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in mtk_drm_get_all_drm_priv")
Cc AngeloGioacchino Del Regno <[email protected]>

This patch fixes a regression in 6.17-rc4 that apparently breaks boot for some users. To make things worse, the offending commit was also backported to the stable trees.

You need to get this one into mainline as soon as possible, that is, this week and into 6.18-rc4.

Johan

Reviewed-by on v1 1/1
#5 lore raw
In reply to Johan Hovold
Quoted 8 lines · Johan Hovold

External email : Please do not click links or open attachments until you have verified the sender or the content.

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

Quoted 8 lines

This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free.

Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Quoted 49 lines
Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in mtk_drm_get_all_drm_priv")
Cc AngeloGioacchino Del Regno <[email protected]>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 10 ----------
 1 file changed, 10 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -11
index 384b0510272c..a94c51a83261 100644
@@ -686,10 +686,6 @@ static int mtk_drm_bind(struct device *dev)
        for (i = 0; i < private->data->mmsys_dev_num; i++)
                private->all_drm_private[i]->drm = NULL;
 err_put_dev:
-       for (i = 0; i < private->data->mmsys_dev_num; i++) {
-               /* For device_find_child in mtk_drm_get_all_priv() */
-               put_device(private->all_drm_private[i]->dev);
-       }
        put_device(private->mutex_dev);
        return ret;
 }
@@ -697,18 +693,12 @@ static int mtk_drm_bind(struct device *dev)
 static void mtk_drm_unbind(struct device *dev)
 {
        struct mtk_drm_private *private = dev_get_drvdata(dev);
-       int i;
 
        /* for multi mmsys dev, unregister drm dev in mmsys master */
        if (private->drm_master) {
                drm_dev_unregister(private->drm);
                mtk_drm_kms_deinit(private->drm);
                drm_dev_put(private->drm);
-
-               for (i = 0; i < private->data->mmsys_dev_num; i++) {
-                       /* For device_find_child in mtk_drm_get_all_priv() */
-                       put_device(private->all_drm_private[i]->dev);
-               }
                put_device(private->mutex_dev);
        }
        private->mtk_drm_bound = false;
--

2.49.1

maintainer Applied
#6 lore raw
In reply to Johan Hovold

Johan Hovold <[email protected]> 於 2025年10月6日 週一 上午9:48寫道:

Quoted 6 lines

A recent change fixed device reference leaks when looking up drm platform device driver data during bind() but failed to remove a partial fix which had been added by commit 80805b62ea5b ("drm/mediatek: Fix kobject put for component sub-drivers").

Quoted 8 lines

This results in a reference imbalance on component bind() failures and on unbind() which could lead to a user-after-free.

Make sure to only drop the references after retrieving the driver data by effectively reverting the previous partial fix.

Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.

Applied to mediatek-drm-fixes [1], thanks.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-fixes

Regards,
Chun-Kuang.

Quoted 49 lines
Fixes 1f403699c40f ("drm/mediatek: Fix device/node reference count leaks in mtk_drm_get_all_drm_priv")
Cc AngeloGioacchino Del Regno <[email protected]>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 10 ----------
 1 file changed, 10 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_drv.c +0 -11
index 384b0510272c..a94c51a83261 100644
@@ -686,10 +686,6 @@ static int mtk_drm_bind(struct device *dev)
        for (i = 0; i < private->data->mmsys_dev_num; i++)
                private->all_drm_private[i]->drm = NULL;
 err_put_dev:
-       for (i = 0; i < private->data->mmsys_dev_num; i++) {
-               /* For device_find_child in mtk_drm_get_all_priv() */
-               put_device(private->all_drm_private[i]->dev);
-       }
        put_device(private->mutex_dev);
        return ret;
 }
@@ -697,18 +693,12 @@ static int mtk_drm_bind(struct device *dev)
 static void mtk_drm_unbind(struct device *dev)
 {
        struct mtk_drm_private *private = dev_get_drvdata(dev);
-       int i;
 
        /* for multi mmsys dev, unregister drm dev in mmsys master */
        if (private->drm_master) {
                drm_dev_unregister(private->drm);
                mtk_drm_kms_deinit(private->drm);
                drm_dev_put(private->drm);
-
-               for (i = 0; i < private->data->mmsys_dev_num; i++) {
-                       /* For device_find_child in mtk_drm_get_all_priv() */
-                       put_device(private->all_drm_private[i]->dev);
-               }
                put_device(private->mutex_dev);
        }
        private->mtk_drm_bound = false;
--

2.49.1