From abf888b03a9805a3bc37948a0df443553b1c0910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Sat, 30 May 2026 15:37:42 -0300 Subject: [PATCH 01/15] drm/v3d: Wait for pending L2T flush before cleaning caches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v3d_clean_caches() starts the cache-clean sequence by writing V3D_L2TCACTL_TMUWCF to V3D_CTL_L2TCACTL and then polling for that bit to clear. It does not, however, check for an L2T flush (L2TFLS) that may still be in flight from a previous operation. On pre-V3D 7.1 hardware, kicking off the TMU write-combiner flush while an L2T flush is still pending can clobber bits in L2TCACTL and cause cache inconsistencies. Poll for L2TFLS to clear before writing L2TCACTL on V3D < 7.1, ensuring any pending flush has completed before a new clean is issued. Cc: stable@vger.kernel.org Fixes: d223f98f0209 ("drm/v3d: Add support for compute shader dispatch.") Link: https://patch.msgid.link/20260530-v3d-fix-rpi4-freezes-v1-1-c2c8307da6ce@igalia.com Signed-off-by: Maíra Canal Reviewed-by: Iago Toral Quiroga --- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 75d9eccd7966..dd7da419702f 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -213,6 +213,14 @@ v3d_clean_caches(struct v3d_dev *v3d) trace_v3d_cache_clean_begin(dev); + /* GFXH-1897: Ensure pending flushes complete before writing L2TCACTL */ + if (v3d->ver < V3D_GEN_71) { + if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & + V3D_L2TCACTL_L2TFLS), 100)) { + drm_err(dev, "Timeout waiting for L2T clean\n"); + } + } + V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF); if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & V3D_L2TCACTL_TMUWCF), 100)) { From 1d0b597facdd3c0239c88e8797c1014e1ea0ef15 Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Fri, 29 May 2026 14:08:53 +0200 Subject: [PATCH 02/15] accel/ivpu: Add bounds check for firmware runtime memory Validate that the firmware runtime memory specified in the image header is properly aligned and sized to hold the firmware image. This prevents errors during memory allocation and image transfer. Fixes: 2007e210b6a1 ("accel/ivpu: Split FW runtime and global memory buffers") Cc: stable@vger.kernel.org # v7.0+ Signed-off-by: Andrzej Kacprowski Reviewed-by: Karol Wachowski Signed-off-by: Karol Wachowski Link: https://patch.msgid.link/20260529120853.135876-1-andrzej.kacprowski@linux.intel.com --- drivers/accel/ivpu/ivpu_fw.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 107f8ad31050..33c50779c06b 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -259,6 +259,22 @@ static int ivpu_fw_parse(struct ivpu_device *vdev) return -EINVAL; } + if (!PAGE_ALIGNED(runtime_addr)) { + ivpu_err(vdev, "Runtime address 0x%llx not page aligned\n", runtime_addr); + return -EINVAL; + } + + if (!PAGE_ALIGNED(runtime_size)) { + ivpu_err(vdev, "Runtime size %llu not page aligned\n", runtime_size); + return -EINVAL; + } + + if (runtime_size < image_size) { + ivpu_err(vdev, "Runtime size too small: %llu, image size: %llu\n", + runtime_size, image_size); + return -EINVAL; + } + if (!ivpu_is_within_range(image_load_addr, image_size, &vdev->hw->ranges.runtime)) { ivpu_err(vdev, "Invalid firmware load address: 0x%llx and size %llu\n", image_load_addr, image_size); From dd1311bcf0e62f0c515115f46a3813370f4a4bb1 Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Fri, 29 May 2026 13:58:42 +0200 Subject: [PATCH 03/15] accel/ivpu: Add bounds checks for firmware log indices Add validation that read and write indices in the firmware log buffer are within valid bounds (< data_size) before using them. If out-of-bounds indices are encountered (from firmware), clamp them to safe values instead of proceeding with invalid offsets. This prevents potential out-of-bounds buffer access when firmware supplies invalid log indices. Fixes: 1fc1251149a7 ("accel/ivpu: Refactor functions in ivpu_fw_log.c") Cc: stable@vger.kernel.org # v6.18+ Signed-off-by: Andrzej Kacprowski Reviewed-by: Karol Wachowski Signed-off-by: Karol Wachowski Link: https://patch.msgid.link/20260529115842.135378-1-andrzej.kacprowski@linux.intel.com --- drivers/accel/ivpu/ivpu_fw_log.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c index 337c906b0210..275baf844b56 100644 --- a/drivers/accel/ivpu/ivpu_fw_log.c +++ b/drivers/accel/ivpu/ivpu_fw_log.c @@ -98,6 +98,11 @@ static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const cha u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0; u32 log_end = READ_ONCE(log->write_index); + if (log_start >= data_size) + log_start = 0; + if (log_end > data_size) + log_end = data_size; + if (log->wrap_count == log->read_wrap_count) { if (log_end <= log_start) { drm_printf(p, "==== %s \"%s\" log empty ====\n", prefix, log->name); From fb176425837693f50c5c9fc8db6fbb04af22bd0a Mon Sep 17 00:00:00 2001 From: Andrzej Kacprowski Date: Fri, 29 May 2026 14:08:41 +0200 Subject: [PATCH 04/15] accel/ivpu: Add buffer overflow check in MS get_info_ioctl Add validation that the info size returned from the metric stream info query is not exceeded when checked against the allocated buffer size. If the firmware returns a size larger than the buffer, reject the operation with -EOVERFLOW instead of proceeding with an incorrect buffer copy. Fixes: cdfad4db7756 ("accel/ivpu: Add NPU profiling support") Cc: stable@vger.kernel.org # v6.18+ Signed-off-by: Andrzej Kacprowski Reviewed-by: Karol Wachowski Signed-off-by: Karol Wachowski Link: https://patch.msgid.link/20260529120841.135852-1-andrzej.kacprowski@linux.intel.com --- drivers/accel/ivpu/ivpu_ms.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c index be43851f5f32..cd176e77b9a0 100644 --- a/drivers/accel/ivpu/ivpu_ms.c +++ b/drivers/accel/ivpu/ivpu_ms.c @@ -291,6 +291,13 @@ int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file * if (ret) goto unlock; + if (info_size > ivpu_bo_size(bo)) { + ivpu_warn_ratelimited(vdev, "MS info overflow: %#llx > %#zx\n", + info_size, ivpu_bo_size(bo)); + ret = -EOVERFLOW; + goto unlock; + } + if (args->buffer_size < info_size) { ret = -ENOSPC; goto unlock; From ae0383e5a9a4b12d68c76c4769857def4665deff Mon Sep 17 00:00:00 2001 From: Yicong Hui Date: Mon, 6 Apr 2026 19:00:13 +0100 Subject: [PATCH 05/15] drm/imx: Fix three kernel-doc warnings in dcss-scaler.c Fix the following W=1 kerneldoc warnings by adding the missing parameter descriptions for @phase0_identity and @nn_interpolation in dcss_scaler_filter_design() and @phase0_identity in dcss_scaler_gaussian_filter() Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:173 function parameter 'phase0_identity' not described in 'dcss_scaler_gaussian_filter' Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'phase0_identity' not described in 'dcss_scaler_filter_design' Warning: drivers/gpu/drm/imx/dcss/dcss-scaler.c:270 function parameter 'nn_interpolation' not described in 'dcss_scaler_filter_design' Fixes: 9021c317b770 ("drm/imx: Add initial support for DCSS on iMX8MQ") Signed-off-by: Yicong Hui Reviewed-by: Laurentiu Palcu Link: https://patch.msgid.link/20260406180013.2442096-1-yiconghui@gmail.com Signed-off-by: Liu Ying --- drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c index 32c3f46b21da..5c7f8d952ec1 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-scaler.c +++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c @@ -166,6 +166,7 @@ static int exp_approx_q(int x) * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter. * @fc_q: fixed-point cutoff frequency normalized to range [0, 1] * @use_5_taps: indicates whether to use 5 taps or 7 taps + * @phase0_identity: whether to override phase 0 coefficients with identity filter * @coef: output filter coefficients */ static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps, @@ -262,7 +263,9 @@ static void dcss_scaler_nearest_neighbor_filter(bool use_5_taps, * @src_length: length of input * @dst_length: length of output * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps + * @phase0_identity: whether to override phase 0 coefficients with identity filter * @coef: output coefficients + * @nn_interpolation: whether to use nearest neighbor instead of gaussian filter */ static void dcss_scaler_filter_design(int src_length, int dst_length, bool use_5_taps, bool phase0_identity, From ae7676952790f421c40918e2586a2c9f12a682b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Tue, 2 Jun 2026 14:50:14 -0300 Subject: [PATCH 06/15] drm/v3d: Fix vaddr leak when indirect CSD has zeroed workgroups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v3d_rewrite_csd_job_wg_counts_from_indirect() maps both the indirect buffer and the workgroup buffer and is expected to release them before returning. When any of the workgroup counts read from the buffer is zero, the function bailed out early and skipped the cleanup, leaking the vaddr mappings of both BOs. Jump to the cleanup path instead of returning directly, so the mappings are always dropped. Cc: stable@vger.kernel.org Fixes: 18b8413b25b7 ("drm/v3d: Create a CPU job extension for a indirect CSD job") Suggested-by: Jose Maria Casanova Crespo Reviewed-by: Iago Toral Quiroga Link: https://patch.msgid.link/20260602-v3d-fix-indirect-csd-v4-1-654309e32bc0@igalia.com Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/v3d_sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 94bf628dc91c..47f83936cd73 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -403,7 +403,7 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job) wg_counts = (uint32_t *)(bo->vaddr + indirect_csd->offset); if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0) - return; + goto unmap_bo; args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT; @@ -428,6 +428,7 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job) } } +unmap_bo: v3d_put_bo_vaddr(indirect); v3d_put_bo_vaddr(bo); } From 7f93fad5ea0affc9e1505dd0f7596c0fdb496213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Tue, 2 Jun 2026 14:50:15 -0300 Subject: [PATCH 07/15] drm/v3d: Skip CSD when it has zeroed workgroups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A compute shader dispatch encodes its workgroup counts in the CFG0..CFG2 registers. Kicking off a dispatch with a zero count in any of the three dimensions is invalid. First, the hardware will process 0 as 65536, while the user-space driver exposes a maximum of 65535. Over that, a submission with a zeroed workgroup dimension should be a no-op. These zeroed counts can reach the dispatch path through an indirect CSD job, whose workgroup counts are only known once the indirect buffer is read and may legitimately be zero, but such scenario should only result in a no-op. Overwrite the indirect CSD job workgroup counts with the indirect BO ones, even if they are zeroed, and don't submit the job to the hardware when any of the workgroup counts is zero, so the job completes immediately instead of running the shader. Cc: stable@vger.kernel.org Fixes: d223f98f0209 ("drm/v3d: Add support for compute shader dispatch.") Suggested-by: Jose Maria Casanova Crespo Reviewed-by: Iago Toral Quiroga Link: https://patch.msgid.link/20260602-v3d-fix-indirect-csd-v4-2-654309e32bc0@igalia.com Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/v3d_sched.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 47f83936cd73..8a635a9ec046 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -352,6 +352,16 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) return NULL; } + /* The HW interprets a workgroup size of 0 as 65536; however, the + * user-space driver exposes a maximum of 65535. Therefore, a 0 in + * any dimension means that we have no workgroups and the compute + * shader should not be dispatched. + */ + if (!V3D_GET_FIELD(job->args.cfg[0], V3D_CSD_QUEUED_CFG0_NUM_WGS_X) || + !V3D_GET_FIELD(job->args.cfg[1], V3D_CSD_QUEUED_CFG1_NUM_WGS_Y) || + !V3D_GET_FIELD(job->args.cfg[2], V3D_CSD_QUEUED_CFG2_NUM_WGS_Z)) + return NULL; + v3d->queue[V3D_CSD].active_job = &job->base; v3d_invalidate_caches(v3d); @@ -402,13 +412,13 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job) wg_counts = (uint32_t *)(bo->vaddr + indirect_csd->offset); - if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0) - goto unmap_bo; - args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT; + if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0) + goto unmap_bo; + num_batches = DIV_ROUND_UP(indirect_csd->wg_size, 16) * (wg_counts[0] * wg_counts[1] * wg_counts[2]); From 30252e6f71ba974ecf9cd8ce395b73b9900bc378 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 2 Jun 2026 13:24:01 +0200 Subject: [PATCH 08/15] drm/dumb-buffer: Drop buffer-size limits for now The size limits break some of the CI tests. So drop them for now. Keep the other overflow tests from commit 5ab62dd3687b ("drm: prevent integer overflows in dumb buffer creation helpers") in place. There is still a pre-existing overflow check for 32-bit type limits in drm_mode_create_dumb() that will catch the really absurd size requests. Drivers that still do not use drm_mode_size_dumb() should be updated. The helper calculates dumb-buffer geometry with overflow checks. Signed-off-by: Thomas Zimmermann Fixes: 5ab62dd3687b ("drm: prevent integer overflows in dumb buffer creation helpers") Reported-by: Jani Nikula Closes: https://lore.kernel.org/dri-devel/ddf0233e50044059c85279f928661563ef6a55bf@intel.com/ Cc: Rajat Gupta Cc: Thomas Zimmermann Cc: Maarten Lankhorst Cc: Maxime Ripard Acked-by: Jani Nikula Link: https://patch.msgid.link/20260602112842.252279-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_dumb_buffers.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/drm_dumb_buffers.c b/drivers/gpu/drm/drm_dumb_buffers.c index cc99681a9ed0..2156dbe601c9 100644 --- a/drivers/gpu/drm/drm_dumb_buffers.c +++ b/drivers/gpu/drm/drm_dumb_buffers.c @@ -202,13 +202,6 @@ int drm_mode_create_dumb(struct drm_device *dev, if (!args->width || !args->height || !args->bpp) return -EINVAL; - /* Reject unreasonable inputs early. Dumb buffers are for software - * rendering; nothing legitimate needs more than 8192x8192 at 32bpp. - * This prevents overflows in downstream alignment helpers. - */ - if (args->width >= 8192 || args->height >= 8192 || args->bpp > 32) - return -EINVAL; - /* overflow checks for 32bit size calculations */ if (args->bpp > U32_MAX - 8) return -EINVAL; From 6bf7e2affc6e62da7add393d7f352d4040f5bc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Sun, 31 May 2026 17:18:55 -0300 Subject: [PATCH 09/15] drm/v3d: Fix global performance monitor reference counting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the SET_GLOBAL ioctl, v3d_perfmon_find() bumps the reference count on the perfmon it returns, but v3d_perfmon_set_global_ioctl() and v3d_perfmon_delete() fail to release that reference on several paths: 1. v3d_perfmon_set_global_ioctl() leaks the reference on its error paths. 2. CLEAR_GLOBAL leaks both the find reference and the reference previously stashed in v3d->global_perfmon by the SET_GLOBAL ioctl that configured it. 3. Destroying a perfmon that is the current global perfmon leaks the reference stashed by the SET_GLOBAL ioctl. Release each of these references explicitly. Cc: stable@vger.kernel.org Fixes: c6eabbab359c ("drm/v3d: Add DRM_IOCTL_V3D_PERFMON_SET_GLOBAL") Reviewed-by: Iago Toral Quiroga Link: https://patch.msgid.link/20260531-v3d-perfmon-lifetime-v2-1-60ed4485a203@igalia.com Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/v3d_perfmon.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c index 8e0249580bba..ecfd446ff75f 100644 --- a/drivers/gpu/drm/v3d/v3d_perfmon.c +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c @@ -309,8 +309,11 @@ static void v3d_perfmon_delete(struct v3d_file_priv *v3d_priv, if (perfmon == v3d->active_perfmon) v3d_perfmon_stop(v3d, perfmon, false); - /* If the global perfmon is being destroyed, set it to NULL */ - cmpxchg(&v3d->global_perfmon, perfmon, NULL); + /* If the global perfmon is being destroyed, clean it and release + * the reference stashed in v3d_perfmon_set_global_ioctl(). + */ + if (cmpxchg(&v3d->global_perfmon, perfmon, NULL) == perfmon) + v3d_perfmon_put(perfmon); v3d_perfmon_put(perfmon); } @@ -461,16 +464,27 @@ int v3d_perfmon_set_global_ioctl(struct drm_device *dev, void *data, /* If the request is to clear the global performance monitor */ if (req->flags & DRM_V3D_PERFMON_CLEAR_GLOBAL) { - if (!v3d->global_perfmon) + struct v3d_perfmon *old; + + /* DRM_V3D_PERFMON_CLEAR_GLOBAL doesn't check if + * v3d->global_perfmon == perfmon. Therefore, there + * is no need to keep perfmon's reference. + */ + v3d_perfmon_put(perfmon); + + old = xchg(&v3d->global_perfmon, NULL); + if (!old) return -EINVAL; - xchg(&v3d->global_perfmon, NULL); + v3d_perfmon_put(old); return 0; } - if (cmpxchg(&v3d->global_perfmon, NULL, perfmon)) + if (cmpxchg(&v3d->global_perfmon, NULL, perfmon)) { + v3d_perfmon_put(perfmon); return -EBUSY; + } return 0; } From 00f547e0dfecf83014fb32bcba587c6b684c1362 Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sat, 23 May 2026 19:51:59 +0000 Subject: [PATCH 10/15] accel/ethosu: fix IFM region index out-of-bounds in command stream parser NPU_SET_IFM_REGION extracts the region index with param & 0x7f, giving a maximum value of 127. However region_size[] and output_region[] in struct ethosu_validated_cmdstream_info are both sized to NPU_BASEP_REGION_MAX (8), giving valid indices [0..7]. Every other region assignment in the same switch uses param & 0x7: NPU_SET_OFM_REGION: st.ofm.region = param & 0x7; NPU_SET_IFM2_REGION: st.ifm2.region = param & 0x7; NPU_SET_WEIGHT_REGION: st.weight[0].region = param & 0x7; NPU_SET_SCALE_REGION: st.scale[0].region = param & 0x7; The 0x7f mask on IFM is inconsistent and appears to be a typo. feat_matrix_length() and calc_sizes() use the region index directly as an array subscript into the kzalloc'd info struct: info->region_size[fm->region] = max(...); A userspace caller supplying NPU_SET_IFM_REGION with param > 7 causes a write up to 127*8 = 1016 bytes past the start of region_size[], corrupting adjacent kernel heap data. Fix by applying the same & 0x7 mask used by all other region assignments. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal Link: https://patch.msgid.link/20260523195159.55801-1-meatuni001@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/accel/ethosu/ethosu_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index 7994e7073903..ced99cf9cdfc 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -464,7 +464,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, st.ifm.broadcast = param; break; case NPU_SET_IFM_REGION: - st.ifm.region = param & 0x7f; + st.ifm.region = param & 0x7; break; case NPU_SET_IFM_WIDTH0_M1: st.ifm.width0 = param; From ef911805d86a05363d3ec2fa9835a41def83bb7e Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sat, 23 May 2026 21:07:52 +0000 Subject: [PATCH 11/15] accel/ethosu: reject NPU_OP_RESIZE commands from userspace NPU_OP_RESIZE is a U85-only command that the driver does not yet implement. The existing WARN_ON(1) placeholder fires unconditionally whenever userspace submits this command via DRM_IOCTL_ETHOSU_GEM_CREATE, causing unbounded kernel log spam. If panic_on_warn is set the kernel panics, giving any unprivileged user with access to the DRM device a trivial denial-of-service primitive. Replace the WARN_ON(1) with an explicit -EINVAL return so the ioctl rejects the command before it reaches hardware. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal Link: https://patch.msgid.link/20260523210840.92039-2-meatuni001@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/accel/ethosu/ethosu_gem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index ced99cf9cdfc..863cdadb137a 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -431,8 +431,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, return ret; break; case NPU_OP_RESIZE: // U85 only - WARN_ON(1); // TODO - break; + return -EINVAL; case NPU_SET_KERNEL_WIDTH_M1: st.ifm.width = param; break; From e703843f242b28e35ac79408de571ae110c740b5 Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sat, 23 May 2026 21:07:53 +0000 Subject: [PATCH 12/15] accel/ethosu: fix wrong weight index in NPU_SET_SCALE1_LENGTH on U85 On non-U65 hardware (e.g. U85), opcode 0x4093 is NPU_SET_WEIGHT2_LENGTH. The BASE handler for the same opcode correctly assigns to st.weight[2].base, but the LENGTH handler mistakenly assigns cmds[1] to st.weight[1].length instead of st.weight[2].length. This leaves weight[2].length at its initialised sentinel value of 0xffffffff and corrupts weight[1].length with the user-supplied value, breaking the software bounds-check state for both weight buffers on U85. Fix the index to match the BASE handler. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal Link: https://patch.msgid.link/20260523210840.92039-3-meatuni001@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/accel/ethosu/ethosu_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index 863cdadb137a..52b6a8752c75 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -598,7 +598,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, if (ethosu_is_u65(edev)) st.scale[1].length = cmds[1]; else - st.weight[1].length = cmds[1]; + st.weight[2].length = cmds[1]; break; case NPU_SET_WEIGHT3_BASE: st.weight[3].base = addr; From ee6d9b6e51626f259c6f0e38d94f91be4fd14754 Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sun, 24 May 2026 10:37:10 +0000 Subject: [PATCH 13/15] accel/ethosu: fix arithmetic issues in dma_length() dma_length() derives DMA region usage from command stream values and updates region_size[]: len = ((len + stride[0]) * size0 + stride[1]) * size1 region_size[region] = max(..., len + dma->offset) Several arithmetic issues can corrupt the derived region size: - signed stride values may underflow when added to len - intermediate multiplications may overflow - len + dma->offset may overflow during region_size updates - dma_length() error returns were not validated by the caller region_size[] is later used by ethosu_job.c to validate command stream accesses against GEM buffer sizes. Arithmetic wraparound can therefore under-report region usage and bypass the bounds validation. Fix by validating signed additions, using overflow helpers for multiplications and offset updates, and propagating dma_length() failures to the caller. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal Link: https://patch.msgid.link/20260524103710.47397-1-meatuni001@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/accel/ethosu/ethosu_gem.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index 52b6a8752c75..27c5fdbe9a5d 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -2,6 +2,7 @@ /* Copyright 2025 Arm, Ltd. */ #include +#include #include #include @@ -164,16 +165,26 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info, u64 len = dma->len; if (mode >= 1) { + if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len) + return U64_MAX; len += dma->stride[0]; - len *= dma_st->size0; + if (check_mul_overflow(len, (u64)dma_st->size0, &len)) + return U64_MAX; } if (mode == 2) { + if (dma->stride[1] < 0 && (u64)(-dma->stride[1]) > len) + return U64_MAX; len += dma->stride[1]; - len *= dma_st->size1; + if (check_mul_overflow(len, (u64)dma_st->size1, &len)) + return U64_MAX; + } + if (dma->region >= 0) { + u64 end; + + if (check_add_overflow(len, dma->offset, &end)) + return U64_MAX; + info->region_size[dma->region] = max(info->region_size[dma->region], end); } - if (dma->region >= 0) - info->region_size[dma->region] = max(info->region_size[dma->region], - len + dma->offset); return len; } @@ -395,6 +406,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, case NPU_OP_DMA_START: srclen = dma_length(info, &st.dma, &st.dma.src); dstlen = dma_length(info, &st.dma, &st.dma.dst); + if (srclen == U64_MAX || dstlen == U64_MAX) + return -EINVAL; if (st.dma.dst.region >= 0) info->output_region[st.dma.dst.region] = true; From d9d021218162b6c4fe0bdf42b2b340f1aae23a12 Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sun, 24 May 2026 13:03:19 +0000 Subject: [PATCH 14/15] accel/ethosu: reject DMA commands with uninitialized length cmd_state_init() initializes the command state with memset(0xff), leaving dma->len at U64_MAX to signal missing setup. The only setter is NPU_SET_DMA0_LEN; if userspace omits this command and issues NPU_OP_DMA_START, dma->len remains U64_MAX. In dma_length(), a positive stride added to U64_MAX wraps to a small value. With size0 == 1, check_mul_overflow() does not trigger and dma_length() returns 0 instead of U64_MAX. The caller's U64_MAX check then passes, region_size[] stays 0, and the bounds check in ethosu_job.c is bypassed, allowing hardware to execute DMA with stale physical addresses. Fix by checking for U64_MAX at the start of dma_length() before any arithmetic, consistent with the sentinel value used throughout the driver to detect uninitialized fields. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal Link: https://patch.msgid.link/20260524130319.12747-1-meatuni001@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/accel/ethosu/ethosu_gem.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index 27c5fdbe9a5d..2cb7964ddfa5 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -164,6 +164,9 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info, s8 mode = dma_st->mode; u64 len = dma->len; + if (len == U64_MAX) + return U64_MAX; + if (mode >= 1) { if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len) return U64_MAX; From c0837b9cf6eabbad8b8cbddaff1a46a6d0a2e29d Mon Sep 17 00:00:00 2001 From: Muhammad Bilal Date: Sat, 23 May 2026 19:08:43 +0000 Subject: [PATCH 15/15] accel/ethosu: fix OOB write in ethosu_gem_cmdstream_copy_and_validate() The command stream parsing loop increments the index variable a second time when a 64-bit command word is encountered (bit 14 set), but does not re-check the loop bound before writing the second word: for (i = 0; i < size / 4; i++) { bocmds[i] = cmds[0]; if (cmd & 0x4000) { i++; bocmds[i] = cmds[1]; /* unchecked */ } } The buffer bocmds is backed by a DMA allocation of exactly size bytes from drm_gem_dma_create(ddev, size), giving valid indices [0, size/4-1]. When i == size/4 - 1 on entry to an iteration and bit 14 of cmds[0] is set, bocmds[size/4-1] is written in bounds, i is then incremented to size/4, and bocmds[size/4] writes four bytes past the end of the allocation. Userspace controls both the buffer contents and the size argument via the ioctl, making this a userspace-triggerable heap out-of-bounds write. Fix by checking the incremented index against the buffer bound before the second write and returning -EINVAL if the buffer is too small to contain the extended command. Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal Link: https://patch.msgid.link/20260523190843.33977-1-meatuni001@gmail.com Signed-off-by: Rob Herring (Arm) --- drivers/accel/ethosu/ethosu_gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c index 2cb7964ddfa5..3401883e207f 100644 --- a/drivers/accel/ethosu/ethosu_gem.c +++ b/drivers/accel/ethosu/ethosu_gem.c @@ -401,6 +401,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev, return -EFAULT; i++; + if (i >= size / 4) + return -EINVAL; bocmds[i] = cmds[1]; addr = cmd_to_addr(cmds); }