[PATCH] drm/vc4: hvs: Fix buffer overflow with the dlist handling

Dave Stevenson dave.stevenson at raspberrypi.com
Tue Feb 2 12:39:17 UTC 2021


Hi Maxime

On Fri, 29 Jan 2021 at 16:07, Maxime Ripard <maxime at cerno.tech> wrote:
>
> Commit 0a038c1c29a7 ("drm/vc4: Move LBM creation out of
> vc4_plane_mode_set()") changed the LBM allocation logic from first
> allocating the LBM memory for the plane to running mode_set,
> adding a gap in the LBM, and then running the dlist allocation filling
> that gap.
>
> The gap was introduced by incrementing the dlist array index, but was
> never checking whether or not we were over the array length, leading
> eventually to memory corruptions if we ever crossed this limit.
>
> vc4_dlist_write had that logic though, and was reallocating a larger
> dlist array when reaching the end of the buffer. Let's share the logic
> between both functions.
>
> Cc: Boris Brezillon <boris.brezillon at collabora.com>
> Cc: Eric Anholt <eric at anholt.net>
> Fixes: 0a038c1c29a7 ("drm/vc4: Move LBM creation out of vc4_plane_mode_set()")
> Signed-off-by: Maxime Ripard <maxime at cerno.tech>

Looks good.

Reviewed-by: Dave Stevenson <dave.stevenson at raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_plane.c | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index b5586c92bfe5..3d33fe3dacea 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -227,7 +227,7 @@ static void vc4_plane_reset(struct drm_plane *plane)
>         __drm_atomic_helper_plane_reset(plane, &vc4_state->base);
>  }
>
> -static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
> +static void vc4_dlist_counter_increment(struct vc4_plane_state *vc4_state)
>  {
>         if (vc4_state->dlist_count == vc4_state->dlist_size) {
>                 u32 new_size = max(4u, vc4_state->dlist_count * 2);
> @@ -242,7 +242,15 @@ static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
>                 vc4_state->dlist_size = new_size;
>         }
>
> -       vc4_state->dlist[vc4_state->dlist_count++] = val;
> +       vc4_state->dlist_count++;
> +}
> +
> +static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
> +{
> +       unsigned int idx = vc4_state->dlist_count;
> +
> +       vc4_dlist_counter_increment(vc4_state);
> +       vc4_state->dlist[idx] = val;
>  }
>
>  /* Returns the scl0/scl1 field based on whether the dimensions need to
> @@ -1057,8 +1065,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>                  * be set when calling vc4_plane_allocate_lbm().
>                  */
>                 if (vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
> -                   vc4_state->y_scaling[1] != VC4_SCALING_NONE)
> -                       vc4_state->lbm_offset = vc4_state->dlist_count++;
> +                   vc4_state->y_scaling[1] != VC4_SCALING_NONE) {
> +                       vc4_state->lbm_offset = vc4_state->dlist_count;
> +                       vc4_dlist_counter_increment(vc4_state);
> +               }
>
>                 if (num_planes > 1) {
>                         /* Emit Cb/Cr as channel 0 and Y as channel
> --
> 2.29.2
>


More information about the dri-devel mailing list