[v2,3/11] drm: pl111: Use devm_of_reserved_mem_device_init()

Message ID 20260902201640.2024648-4-mukesh.ojha@oss.qualcomm.com (mailing list archive)
State New
Headers
Series drm: Use devm_of_reserved_mem_device_init() |

Commit Message

Mukesh Ojha Sept. 2, 2026, 8:16 p.m. UTC
Switch to devm_of_reserved_mem_device_init() so the reserved memory
region is released automatically on probe failure or device removal.
Remove the explicit of_reserved_mem_device_release() calls in the
dev_put error path and pl111_amba_remove().

Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
 drivers/gpu/drm/pl111/pl111_drv.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
  

Comments

sashiko-bot@kernel.org Sept. 2, 2026, 8:33 p.m. UTC | #1
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] Pre-existing use-after-free and memory corruption risks due to tying resource lifetimes (`priv` structure and reserved memory) to `devres` (driver unbind) while the `drm_device` can outlive the unbind.
- [High] The `drm_panel_bridge` allocated via `drm_panel_bridge_add_typed()` in `pl111_modeset_init()` is leaked if `drm_dev_register()` fails.
- [High] When `INTEGRATOR_CLCD_CM` is matched, `pl111_versatile_init()` overwrites `np` without dropping the original reference. If the second match fails, probe incorrectly fails.
--

commit 76a1e18802677a9e3db4c051729d253910d2a13c
Author: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>

drm: pl111: Use devm_of_reserved_mem_device_init()

This patch converts the driver to use devm_of_reserved_mem_device_init,
allowing the reserved memory region to be released automatically on
probe failure or device removal. It removes the explicit cleanup calls.

> diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
> index 8ec659b3c08eb..a07b17261961c 100644
> --- a/drivers/gpu/drm/pl111/pl111_drv.c
> +++ b/drivers/gpu/drm/pl111/pl111_drv.c
> @@ -255,7 +255,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
>  	drm->dev_private = priv;
>  	priv->variant = variant;
>  
> -	ret = of_reserved_mem_device_init(dev);
> +	ret = devm_of_reserved_mem_device_init(dev);

[Severity: High]
This is a pre-existing issue, but does tying resource lifetimes to devres
here expose a use-after-free risk?

The priv structure is allocated via devm_kzalloc() and the reserved
memory is now managed via devres, tying their lifetimes to the driver
unbind lifecycle. However, the drm_device is allocated without devres via
drm_dev_alloc() and tied to a refcount.

If a local user holds an open DRM file descriptor (like /dev/dri/card0)
and the driver is unbound via sysfs, devres will free priv and the reserved
memory while the DRM device persists. Because pl111_amba_remove() calls
drm_dev_unregister() instead of drm_dev_unplug(), the device is not
marked as unplugged and subsequent ioctls are not blocked.

An ioctl like DRM_IOCTL_PRIME_FD_TO_HANDLE will call
pl111_gem_import_sg_table(), which accesses dev->dev_private (priv),
potentially causing a use-after-free. Should the driver be migrated to
drm_dev_unplug() and devm_drm_dev_alloc() to prevent this?

[ ... ]

> @@ -314,7 +314,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
>  
>  dev_put:
>  	drm_dev_put(drm);
> -	of_reserved_mem_device_release(dev);
>  
>  	return ret;
>  }

[Severity: High]
This is a pre-existing issue, but does this error path leak the panel
bridge?

During probe, a bridge is created by calling drm_panel_bridge_add_typed()
inside pl111_modeset_init(), which adds the bridge to the global DRM bridge
list with a reference count of 2.

If drm_dev_register() subsequently fails, the probe function jumps to
the dev_put label. The error path calls drm_dev_put(drm) but fails to
call drm_panel_bridge_remove(priv->bridge). When the panel device is
eventually unbound, its devres cleanup drops one reference on the bridge,
but the bridge is never removed from the global list, leaving a dangling
pointer. Does this need an explicit drm_panel_bridge_remove() call here?

Also, while reviewing the probe path, I noticed a potential node reference
issue in pl111_versatile_init() called earlier in this function:

drivers/gpu/drm/pl111/pl111_versatile.c:pl111_versatile_init() {
    ...
    np = of_find_matching_node_and_match(NULL, versatile_clcd_of_match,
                                         &clcd_id);
    ...
    if (clcd_id == INTEGRATOR_CLCD_CM) {
        np = of_find_matching_node_and_match(NULL, impd1_clcd_of_match,
                                             &clcd_id);
}

[Severity: High]
This is a pre-existing issue, but does overwriting np without dropping the
original reference cause a memory leak?

For the INTEGRATOR_CLCD_CM type, a second call to
of_find_matching_node_and_match() is made, and its result overwrites np
without calling of_node_put() on the original node. If the IM-PD1 syscon
is not found, the second call returns NULL. The probe then calls
syscon_node_to_regmap(NULL), which fails and returns an error, preventing
the driver from probing successfully on valid standard Integrator AP
hardware. Should of_node_put() be called before reassigning np?
  

Patch

diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index 8ec659b3c08e..a07b17261961 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -255,7 +255,7 @@  static int pl111_amba_probe(struct amba_device *amba_dev,
 	drm->dev_private = priv;
 	priv->variant = variant;
 
-	ret = of_reserved_mem_device_init(dev);
+	ret = devm_of_reserved_mem_device_init(dev);
 	if (!ret) {
 		drm_info(drm, "using device-specific reserved memory\n");
 		priv->use_device_memory = true;
@@ -314,7 +314,6 @@  static int pl111_amba_probe(struct amba_device *amba_dev,
 
 dev_put:
 	drm_dev_put(drm);
-	of_reserved_mem_device_release(dev);
 
 	return ret;
 }
@@ -330,7 +329,6 @@  static void pl111_amba_remove(struct amba_device *amba_dev)
 	if (priv->panel)
 		drm_panel_bridge_remove(priv->bridge);
 	drm_dev_put(drm);
-	of_reserved_mem_device_release(dev);
 }
 
 static void pl111_amba_shutdown(struct amba_device *amba_dev)