Re: [PATCH] drm/imagination: Fix user array stride in pvr_set_uobj_array()

From: Alessio Belle

Date: Wed Jul 01 2026 - 14:17:49 EST


Hi Shuvam,

On Tue, 2026-06-16 at 03:31 +0545, shuvampandey1@xxxxxxxxx wrote:
> pvr_set_uobj_array() copies an array of kernel objects to a userspace
> array whose element size is described by out->stride. When out->stride
> is different from the kernel object size, the slow path advances the
> userspace pointer by the kernel object size and the kernel pointer by the
> userspace stride.
>
> This reverses the intended layout. For larger userspace strides, later
> copies read from the wrong kernel addresses. For smaller userspace
> strides, later copies are written at the wrong userspace offsets. The
> padding clear is also done only for the first element instead of the
> padding area for each element.
>
> Advance the userspace pointer by out->stride and the kernel pointer by
> obj_size, and clear per-element padding while the current userspace
> pointer is still available.
>
> Fixes: f99f5f3ea7ef ("drm/imagination: Add GPU ID parsing and firmware loading")
> Cc: stable@xxxxxxxxxxxxxxx # v6.8+
> Signed-off-by: Shuvam Pandey <shuvampandey1@xxxxxxxxx>

Could you resend the patch with the "From:" header fixed up with name + email,
to match the signed off line? Somehow the name got lost.

Everything else looks good, so with that sorted,

Reviewed-by: Alessio Belle <alessio.belle@xxxxxxxxxx>

Thanks,
Alessio

> ---
> drivers/gpu/drm/imagination/pvr_drv.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
> index 268900464ab6..0a68a9c32361 100644
> --- a/drivers/gpu/drm/imagination/pvr_drv.c
> +++ b/drivers/gpu/drm/imagination/pvr_drv.c
> @@ -1252,14 +1252,13 @@ pvr_set_uobj_array(const struct drm_pvr_obj_array *out, u32 min_stride, u32 obj_
> if (copy_to_user(out_ptr, in_ptr, cpy_elem_size))
> return -EFAULT;
>
> - out_ptr += obj_size;
> - in_ptr += out->stride;
> - }
> + if (out->stride > obj_size &&
> + clear_user(out_ptr + cpy_elem_size, out->stride - obj_size)) {
> + return -EFAULT;
> + }
>
> - if (out->stride > obj_size &&
> - clear_user(u64_to_user_ptr(out->array + obj_size),
> - out->stride - obj_size)) {
> - return -EFAULT;
> + out_ptr += out->stride;
> + in_ptr += obj_size;
> }
> }
>