* [PATCH v2 1/2] drm/bridge: add drm_bridge_clear_and_put()
2026-03-10 12:13 [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put() Luca Ceresoli
@ 2026-03-10 12:13 ` Luca Ceresoli
2026-03-10 12:13 ` [PATCH v2 2/2] drm/bridge: samsung-dsim: use drm_bridge_clear_and_put() to put the next bridge Luca Ceresoli
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Luca Ceresoli @ 2026-03-10 12:13 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Inki Dae,
Jagan Teki, Marek Szyprowski
Cc: Osama Abdelkader, Hui Pu, Ian Ray, Thomas Petazzoni, dri-devel,
linux-kernel, Luca Ceresoli
Drivers having a struct drm_bridge pointer pointing to a bridge in many
cases hold that reference until the owning device is removed. In those
cases the reference to the bridge can be put in the .remove callback
(possibly using devm actions) or in the .destroy func (possibly with the
help of struct drm_bridge::next_bridge). At those moments the driver should
not be operating anymore and won't dereference the bridge pointer after it
is put.
However there are cases when drivers need to stop holding a reference to a
bridge even when their device is not being removed. This is the case for
bridge hot-unplug, when a bridge is removed but the previous entity (bridge
or encoder) is staying. In such case the "previous entity" needs to put it
but cannot do it via devm or .destroy, because it is not being removed.
The easy way to dispose of such pointer is:
drm_bridge_put(my_priv->some_bridge);
my_priv->some_bridge = NULL;
However this is risky because there is a time window between the two lines
where the reference is put, and thus the bridge could be deallocated, but
the pointer is still assigned. If other functions of the same driver were
invoked concurrently they might dereference my_priv->some_bridge during
that window, resulting in use-after-free.
A correct solution is to clear the pointer before putting the reference,
but that needs a temporary variable:
struct drm_bridge *temp = my_priv->some_bridge;
my_priv->some_bridge = NULL;
drm_bridge_put(temp);
This solution is however annoying to write, so the incorrect version might
still sneak in.
Add a simple, easy to use function to put a bridge after setting its
pointer to NULL in the correct way.
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
This is a renamed version of drm_bridge_put_and_clear() which was sent as
part of a larger patch [0] but with largely rewritten documentation and a
detailed commit message.
[0] https://lore.kernel.org/lkml/20250206-hotplug-drm-bridge-v6-14-9d6f2c9c3058@bootlin.com/
---
drivers/gpu/drm/drm_bridge.c | 34 ++++++++++++++++++++++++++++++++++
include/drm/drm_bridge.h | 1 +
2 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index f8b0333a0a3b..0260b16cb47d 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -304,6 +304,9 @@ EXPORT_SYMBOL(drm_bridge_get);
*
* This function decrements the bridge's reference count and frees the
* object if the reference count drops to zero.
+ *
+ * See also drm_bridge_clear_and_put() if you also need to set the pointer
+ * to NULL
*/
void drm_bridge_put(struct drm_bridge *bridge)
{
@@ -312,6 +315,37 @@ void drm_bridge_put(struct drm_bridge *bridge)
}
EXPORT_SYMBOL(drm_bridge_put);
+/**
+ * drm_bridge_clear_and_put - Given a bridge pointer, clear the pointer
+ * then put the bridge
+ * @bridge_pp: pointer to pointer to a struct drm_bridge; ``bridge_pp``
+ * must be non-NULL; if ``*bridge_pp`` is NULL this function
+ * does nothing
+ *
+ * Helper to put a DRM bridge, but only after setting its pointer to
+ * NULL. Useful when a struct drm_bridge reference must be dropped without
+ * leaving a use-after-free window where the pointed bridge might have been
+ * freed while still holding a pointer to it.
+ *
+ * For struct ``drm_bridge *some_bridge``, this code::
+ *
+ * drm_bridge_clear_and_put(&some_bridge);
+ *
+ * is equivalent to the more complex::
+ *
+ * struct drm_bridge *temp = some_bridge;
+ * some_bridge = NULL;
+ * drm_bridge_put(temp);
+ */
+void drm_bridge_clear_and_put(struct drm_bridge **bridge_pp)
+{
+ struct drm_bridge *bridge = *bridge_pp;
+
+ *bridge_pp = NULL;
+ drm_bridge_put(bridge);
+}
+EXPORT_SYMBOL(drm_bridge_clear_and_put);
+
/**
* drm_bridge_put_void - wrapper to drm_bridge_put() taking a void pointer
*
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 4f19f7064ee3..66ab89cf48aa 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -1290,6 +1290,7 @@ void drm_bridge_unplug(struct drm_bridge *bridge);
struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge);
void drm_bridge_put(struct drm_bridge *bridge);
+void drm_bridge_clear_and_put(struct drm_bridge **bridge_pp);
/* Cleanup action for use with __free() */
DEFINE_FREE(drm_bridge_put, struct drm_bridge *, if (_T) drm_bridge_put(_T))
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/2] drm/bridge: samsung-dsim: use drm_bridge_clear_and_put() to put the next bridge
2026-03-10 12:13 [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put() Luca Ceresoli
2026-03-10 12:13 ` [PATCH v2 1/2] " Luca Ceresoli
@ 2026-03-10 12:13 ` Luca Ceresoli
2026-03-11 8:28 ` Marek Szyprowski
2026-03-11 8:19 ` [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put() Maxime Ripard
2026-03-20 10:18 ` Luca Ceresoli
3 siblings, 1 reply; 6+ messages in thread
From: Luca Ceresoli @ 2026-03-10 12:13 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Inki Dae,
Jagan Teki, Marek Szyprowski
Cc: Osama Abdelkader, Hui Pu, Ian Ray, Thomas Petazzoni, dri-devel,
linux-kernel, Luca Ceresoli
drm_bridge_clear_and_put() is simpler to write and it prevents any
potential future use-after-free.
Reviewed-by: Osama Abdelkader <osama.abdelkader@gmail.com>
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
drivers/gpu/drm/bridge/samsung-dsim.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index ec632f268644..c3eb437ef1b0 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -1988,9 +1988,7 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
return 0;
err_release_next_bridge:
- drm_bridge_put(dsi->bridge.next_bridge);
- dsi->bridge.next_bridge = NULL;
-
+ drm_bridge_clear_and_put(&dsi->bridge.next_bridge);
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
samsung_dsim_unregister_te_irq(dsi);
err_remove_bridge:
@@ -2007,8 +2005,7 @@ static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
if (pdata->host_ops && pdata->host_ops->detach)
pdata->host_ops->detach(dsi, device);
- drm_bridge_put(dsi->bridge.next_bridge);
- dsi->bridge.next_bridge = NULL;
+ drm_bridge_clear_and_put(&dsi->bridge.next_bridge);
samsung_dsim_unregister_te_irq(dsi);
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] drm/bridge: samsung-dsim: use drm_bridge_clear_and_put() to put the next bridge
2026-03-10 12:13 ` [PATCH v2 2/2] drm/bridge: samsung-dsim: use drm_bridge_clear_and_put() to put the next bridge Luca Ceresoli
@ 2026-03-11 8:28 ` Marek Szyprowski
0 siblings, 0 replies; 6+ messages in thread
From: Marek Szyprowski @ 2026-03-11 8:28 UTC (permalink / raw)
To: Luca Ceresoli, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Inki Dae, Jagan Teki
Cc: Osama Abdelkader, Hui Pu, Ian Ray, Thomas Petazzoni, dri-devel,
linux-kernel
On 10.03.2026 13:13, Luca Ceresoli wrote:
> drm_bridge_clear_and_put() is simpler to write and it prevents any
> potential future use-after-free.
>
> Reviewed-by: Osama Abdelkader <osama.abdelkader@gmail.com>
> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> drivers/gpu/drm/bridge/samsung-dsim.c | 7 ++-----
> 1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
> index ec632f268644..c3eb437ef1b0 100644
> --- a/drivers/gpu/drm/bridge/samsung-dsim.c
> +++ b/drivers/gpu/drm/bridge/samsung-dsim.c
> @@ -1988,9 +1988,7 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
> return 0;
>
> err_release_next_bridge:
> - drm_bridge_put(dsi->bridge.next_bridge);
> - dsi->bridge.next_bridge = NULL;
> -
> + drm_bridge_clear_and_put(&dsi->bridge.next_bridge);
> if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
> samsung_dsim_unregister_te_irq(dsi);
> err_remove_bridge:
> @@ -2007,8 +2005,7 @@ static int samsung_dsim_host_detach(struct mipi_dsi_host *host,
> if (pdata->host_ops && pdata->host_ops->detach)
> pdata->host_ops->detach(dsi, device);
>
> - drm_bridge_put(dsi->bridge.next_bridge);
> - dsi->bridge.next_bridge = NULL;
> + drm_bridge_clear_and_put(&dsi->bridge.next_bridge);
>
> samsung_dsim_unregister_te_irq(dsi);
>
>
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put()
2026-03-10 12:13 [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put() Luca Ceresoli
2026-03-10 12:13 ` [PATCH v2 1/2] " Luca Ceresoli
2026-03-10 12:13 ` [PATCH v2 2/2] drm/bridge: samsung-dsim: use drm_bridge_clear_and_put() to put the next bridge Luca Ceresoli
@ 2026-03-11 8:19 ` Maxime Ripard
2026-03-20 10:18 ` Luca Ceresoli
3 siblings, 0 replies; 6+ messages in thread
From: Maxime Ripard @ 2026-03-11 8:19 UTC (permalink / raw)
To: Luca Ceresoli
Cc: dri-devel, linux-kernel, Andrzej Hajda, David Airlie, Hui Pu,
Ian Ray, Inki Dae, Jagan Teki, Jernej Skrabec, Jonas Karlman,
Laurent Pinchart, Maarten Lankhorst, Marek Szyprowski,
Maxime Ripard, Neil Armstrong, Osama Abdelkader, Robert Foss,
Simona Vetter, Thomas Petazzoni, Thomas Zimmermann
On Tue, 10 Mar 2026 13:13:22 +0100, Luca Ceresoli wrote:
> This small series introduces drm_bridge_clear_and_put(), to give a easy and
> safe way to put a bridge reference and clear the pointer without leaving a
> possible use-after-free window.
>
> This is part of the work to support hotplug of DRM bridges. The grand plan
>
> [ ... ]
Acked-by: Maxime Ripard <mripard@kernel.org>
Thanks!
Maxime
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put()
2026-03-10 12:13 [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put() Luca Ceresoli
` (2 preceding siblings ...)
2026-03-11 8:19 ` [PATCH v2 0/2] drm/bridge: add drm_bridge_clear_and_put() Maxime Ripard
@ 2026-03-20 10:18 ` Luca Ceresoli
3 siblings, 0 replies; 6+ messages in thread
From: Luca Ceresoli @ 2026-03-20 10:18 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Inki Dae,
Jagan Teki, Marek Szyprowski, Luca Ceresoli
Cc: Osama Abdelkader, Hui Pu, Ian Ray, Thomas Petazzoni, dri-devel,
linux-kernel
On Tue, 10 Mar 2026 13:13:22 +0100, Luca Ceresoli wrote:
> This small series introduces drm_bridge_clear_and_put(), to give a easy and
> safe way to put a bridge reference and clear the pointer without leaving a
> possible use-after-free window.
>
> This is part of the work to support hotplug of DRM bridges. The grand plan
> was discussed in [0].
>
> [...]
Applied, thanks!
[1/2] drm/bridge: add drm_bridge_clear_and_put()
commit: 8f3c83720555ffa96799896f2a0bb985a03a89f4
[2/2] drm/bridge: samsung-dsim: use drm_bridge_clear_and_put() to put the next bridge
commit: fbef867cf6614178bc6afd15ee15f85cddf19eab
Best regards,
--
Luca Ceresoli <luca.ceresoli@bootlin.com>
^ permalink raw reply [flat|nested] 6+ messages in thread