[PATCH v2 2/2] media: atomisp: bound DVS 6-axis table dimensions to the allocated config

From: Doruk Tan Ozturk

Date: Sat Jun 27 2026 - 02:40:21 EST


atomisp_cp_dvs_6axis_config() allocates the DVS 6-axis coordinate arrays
from the stream grid via ia_css_dvs2_6axis_config_allocate(), but then
uses the user-supplied width_y/height_y/width_uv/height_uv as the
copy_from_compatible() length. The reallocate-on-mismatch path also
re-allocates from the stream grid, so the destination is always
stream-sized while the copy length is user-sized. User dimensions larger
than the allocated grid produce a heap out-of-bounds write with
attacker-controlled length and contents, reachable from
ATOMISP_IOC_S_DIS_VECTOR.

Reject user dimensions that exceed the allocated config in both the
ISP2401 (t_6axis_config) and ISP2400/else (source_6axis_config) branches
before the first copy.

Found by 0sec's autonomous vulnerability analysis (https://0sec.ai).
Found by static analysis; not yet runtime-reproduced (Intel
Baytrail/Cherrytrail ISP hardware required).

Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2")
Signed-off-by: Doruk Tan Ozturk <doruk@xxxxxxx>
---
.../staging/media/atomisp/pci/atomisp_cmd.c | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
index 5046a0ec8bba..9338aa009923 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c
@@ -2630,6 +2630,20 @@ int atomisp_cp_dvs_6axis_config(struct atomisp_sub_device *asd,

dvs_6axis_config->exp_id = t_6axis_config.exp_id;

+ /*
+ * The destination coordinate arrays are sized from the stream
+ * grid by ia_css_dvs2_6axis_config_allocate(); the copy length
+ * below uses the user-supplied dimensions. Reject user dims that
+ * exceed the allocation to avoid a heap out-of-bounds write.
+ */
+ if (t_6axis_config.width_y > dvs_6axis_config->width_y ||
+ t_6axis_config.height_y > dvs_6axis_config->height_y ||
+ t_6axis_config.width_uv > dvs_6axis_config->width_uv ||
+ t_6axis_config.height_uv > dvs_6axis_config->height_uv) {
+ ret = -EINVAL;
+ goto error;
+ }
+
if (copy_from_compatible(dvs_6axis_config->xcoords_y,
t_6axis_config.xcoords_y,
t_6axis_config.width_y *
@@ -2682,6 +2696,20 @@ int atomisp_cp_dvs_6axis_config(struct atomisp_sub_device *asd,

dvs_6axis_config->exp_id = source_6axis_config->exp_id;

+ /*
+ * The destination coordinate arrays are sized from the stream
+ * grid by ia_css_dvs2_6axis_config_allocate(); the copy length
+ * below uses the user-supplied dimensions. Reject user dims that
+ * exceed the allocation to avoid a heap out-of-bounds write.
+ */
+ if (source_6axis_config->width_y > dvs_6axis_config->width_y ||
+ source_6axis_config->height_y > dvs_6axis_config->height_y ||
+ source_6axis_config->width_uv > dvs_6axis_config->width_uv ||
+ source_6axis_config->height_uv > dvs_6axis_config->height_uv) {
+ ret = -EINVAL;
+ goto error;
+ }
+
if (copy_from_compatible(dvs_6axis_config->xcoords_y,
source_6axis_config->xcoords_y,
source_6axis_config->width_y *
--
2.53.0