summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorShuvam Pandey <shuvampandey1@gmail.com>2026-07-01 11:44:34 -0700
committerAlessio Belle <alessio.belle@imgtec.com>2026-07-02 11:16:18 +0100
commit8dc8f3f4c2382fb7d1b1986ba8f33a2466cd3d7a (patch)
treeb82bcb724d667b75f8122351e7506a3a9f39828a /drivers
parentd431b4012fd22920523dbd2806da663c1048e386 (diff)
downloadlinux-8dc8f3f4c2382fb7d1b1986ba8f33a2466cd3d7a.tar.gz
linux-8dc8f3f4c2382fb7d1b1986ba8f33a2466cd3d7a.zip
drm/imagination: Fix user array stride in pvr_set_uobj_array()
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@vger.kernel.org # v6.8+ Reviewed-by: Alessio Belle <alessio.belle@imgtec.com> Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com> Link: https://patch.msgid.link/6a456012.eb165e5c.113c2a.b71d@mx.google.com Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/imagination/pvr_drv.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 091e9b4873e1..e8487fd22e15 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1257,14 +1257,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;
}
}