[PATCH] drm/vc4: Fix NULL pointer dereference in vc4_plane_create_additional_planes

Henri Zikken posted 1 patch 2 months, 1 week ago
drivers/gpu/drm/vc4/vc4_plane.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
[PATCH] drm/vc4: Fix NULL pointer dereference in vc4_plane_create_additional_planes
Posted by Henri Zikken 2 months, 1 week ago
When a vc4 DRM device has no TXP (Writeback) CRTC, txp_crtc remains
uninitialized after the drm_for_each_crtc loop. Subsequent calls to
drm_crtc_mask(txp_crtc) then dereference a NULL pointer, causing a
kernel panic.

This was observed on Raspberry Pi Zero 2W with a DPI panel connected,
where vc4_dpi_dev_probe triggers vc4_drm_bind which calls
vc4_plane_create_additional_planes without a TXP being present.

Fix by initializing txp_crtc to NULL and guarding all drm_crtc_mask()
calls on txp_crtc with a NULL check.

Fixes: (vc4_plane_create_additional_planes introduction)
Signed-off-by: Henri Zikken<zikken@xs4all.nl>
Signed-off-by: root <root@DESKTOP-40RM2Q1.localdomain>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index fdd6ba310..c43c12c2c 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -2665,7 +2665,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
 	struct drm_plane *cursor_plane;
 	struct drm_crtc *crtc;
 	unsigned int i;
-	struct drm_crtc *txp_crtc;
+	struct drm_crtc *txp_crtc = NULL;
 	uint32_t non_txp_crtc_mask;
 
 	drm_for_each_crtc(crtc, drm) {
@@ -2678,7 +2678,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
 	}
 
 	non_txp_crtc_mask = GENMASK(drm->mode_config.num_crtc - 1, 0) -
-					drm_crtc_mask(txp_crtc);
+					(txp_crtc ? drm_crtc_mask(txp_crtc) : 0);
 
 	/* Set up some arbitrary number of planes.  We're not limited
 	 * by a set number of physical registers, just the space in
@@ -2707,7 +2707,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
 	for (i = 0; i < VC4_NUM_TXP_OVERLAY_PLANES; i++) {
 		struct drm_plane *plane =
 			vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
-				       drm_crtc_mask(txp_crtc));
+				       (txp_crtc ? drm_crtc_mask(txp_crtc) : 0));
 
 		if (IS_ERR(plane))
 			continue;
-- 
2.39.5
Re: [PATCH] drm/vc4: Fix NULL pointer dereference in vc4_plane_create_additional_planes
Posted by Dave Stevenson 1 month, 1 week ago
Hi Henri

Sorry for the delay in replying.

On Fri, 3 Apr 2026 at 09:59, Henri Zikken <zikken@xs4all.nl> wrote:
>
> When a vc4 DRM device has no TXP (Writeback) CRTC, txp_crtc remains
> uninitialized after the drm_for_each_crtc loop. Subsequent calls to
> drm_crtc_mask(txp_crtc) then dereference a NULL pointer, causing a
> kernel panic.
>
> This was observed on Raspberry Pi Zero 2W with a DPI panel connected,
> where vc4_dpi_dev_probe triggers vc4_drm_bind which calls
> vc4_plane_create_additional_planes without a TXP being present.
>
> Fix by initializing txp_crtc to NULL and guarding all drm_crtc_mask()
> calls on txp_crtc with a NULL check.

Which tree have you created this patch against?

Creating a separate set of planes for the writeback connector is a
patch that I haven't upstreamed yet, so it only exists in our vendor
kernel[1].
This issue is already fixed on the rpi-6.18.y branch. It does exist on
earlier branches, but those are frozen for our ongoing development
efforts.

Then again if there is no transposer there is no point in creating the
additional planes at all. Creating them with a mask of 0 is a waste of
time.

  Dave

[1] https://github.com/raspberrypi/linux

> Fixes: (vc4_plane_create_additional_planes introduction)
> Signed-off-by: Henri Zikken<zikken@xs4all.nl>
> Signed-off-by: root <root@DESKTOP-40RM2Q1.localdomain>

Rogue Signed-off-by line.

> ---
>  drivers/gpu/drm/vc4/vc4_plane.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index fdd6ba310..c43c12c2c 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -2665,7 +2665,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
>         struct drm_plane *cursor_plane;
>         struct drm_crtc *crtc;
>         unsigned int i;
> -       struct drm_crtc *txp_crtc;
> +       struct drm_crtc *txp_crtc = NULL;
>         uint32_t non_txp_crtc_mask;
>
>         drm_for_each_crtc(crtc, drm) {
> @@ -2678,7 +2678,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
>         }
>
>         non_txp_crtc_mask = GENMASK(drm->mode_config.num_crtc - 1, 0) -
> -                                       drm_crtc_mask(txp_crtc);
> +                                       (txp_crtc ? drm_crtc_mask(txp_crtc) : 0);
>
>         /* Set up some arbitrary number of planes.  We're not limited
>          * by a set number of physical registers, just the space in
> @@ -2707,7 +2707,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
>         for (i = 0; i < VC4_NUM_TXP_OVERLAY_PLANES; i++) {
>                 struct drm_plane *plane =
>                         vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
> -                                      drm_crtc_mask(txp_crtc));
> +                                      (txp_crtc ? drm_crtc_mask(txp_crtc) : 0));
>
>                 if (IS_ERR(plane))
>                         continue;
> --
> 2.39.5
>