| From 6a47f9fd2d970674ed9dedc52fc7ab76fd015785 Mon Sep 17 00:00:00 2001 |
| From: Osama Abdelkader <osama.abdelkader@gmail.com> |
| Date: Mon, 20 Jul 2026 15:44:35 +0200 |
| Subject: drm/panthor: fix firmware control interface bounds checks |
| |
| From: Osama Abdelkader <osama.abdelkader@gmail.com> |
| |
| commit 6a47f9fd2d970674ed9dedc52fc7ab76fd015785 upstream. |
| |
| panthor_init_cs_iface() and panthor_init_csg_iface() validate firmware |
| control interface offsets with 32-bit arithmetic and the size of the host |
| wrapper structures. The offsets are derived from firmware-provided strides, |
| so the arithmetic can wrap before the bounds check, and the host wrapper |
| size is not the size of the firmware control interface being mapped. |
| |
| Use 64-bit arithmetic for the computed offsets and validate against the |
| actual firmware control interface structure sizes with subtraction-based |
| bounds checks. Also validate that the shared section is large enough for |
| the global control interface before using it. |
| |
| Fixes: 2718d91816ee ("drm/panthor: Add the FW logical block") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com> |
| Reviewed-by: Steven Price <steven.price@arm.com> |
| Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> |
| Link: https://patch.msgid.link/20260720134435.13377-1-osama.abdelkader@gmail.com |
| Signed-off-by: Steven Price <steven.price@arm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/gpu/drm/panthor/panthor_fw.c | 19 +++++++++++++------ |
| 1 file changed, 13 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/gpu/drm/panthor/panthor_fw.c |
| +++ b/drivers/gpu/drm/panthor/panthor_fw.c |
| @@ -895,14 +895,15 @@ static int panthor_init_cs_iface(struct |
| struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_idx); |
| struct panthor_fw_cs_iface *cs_iface = &ptdev->fw->iface.streams[csg_idx][cs_idx]; |
| u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); |
| - u32 iface_offset = CSF_GROUP_CONTROL_OFFSET + |
| - (csg_idx * glb_iface->control->group_stride) + |
| + u64 iface_offset = CSF_GROUP_CONTROL_OFFSET + |
| + ((u64)csg_idx * glb_iface->control->group_stride) + |
| CSF_STREAM_CONTROL_OFFSET + |
| - (cs_idx * csg_iface->control->stream_stride); |
| + ((u64)cs_idx * csg_iface->control->stream_stride); |
| struct panthor_fw_cs_iface *first_cs_iface = |
| panthor_fw_get_cs_iface(ptdev, 0, 0); |
| |
| - if (iface_offset + sizeof(*cs_iface) >= shared_section_sz) |
| + if (iface_offset > shared_section_sz || |
| + sizeof(*cs_iface->control) > shared_section_sz - iface_offset) |
| return -EINVAL; |
| |
| spin_lock_init(&cs_iface->lock); |
| @@ -952,10 +953,12 @@ static int panthor_init_csg_iface(struct |
| struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); |
| struct panthor_fw_csg_iface *csg_iface = &ptdev->fw->iface.groups[csg_idx]; |
| u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); |
| - u32 iface_offset = CSF_GROUP_CONTROL_OFFSET + (csg_idx * glb_iface->control->group_stride); |
| + u64 iface_offset = CSF_GROUP_CONTROL_OFFSET + |
| + ((u64)csg_idx * glb_iface->control->group_stride); |
| unsigned int i; |
| |
| - if (iface_offset + sizeof(*csg_iface) >= shared_section_sz) |
| + if (iface_offset > shared_section_sz || |
| + sizeof(*csg_iface->control) > shared_section_sz - iface_offset) |
| return -EINVAL; |
| |
| spin_lock_init(&csg_iface->lock); |
| @@ -1007,11 +1010,15 @@ static u32 panthor_get_instr_features(st |
| static int panthor_fw_init_ifaces(struct panthor_device *ptdev) |
| { |
| struct panthor_fw_global_iface *glb_iface = &ptdev->fw->iface.global; |
| + u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); |
| unsigned int i; |
| |
| if (!ptdev->fw->shared_section->mem->kmap) |
| return -EINVAL; |
| |
| + if (sizeof(*glb_iface->control) > shared_section_sz) |
| + return -EINVAL; |
| + |
| spin_lock_init(&glb_iface->lock); |
| glb_iface->control = ptdev->fw->shared_section->mem->kmap; |
| |