[PATCH v3] staging: media: atomisp: use array3_size() for overflow-safe allocation

From: Feng Ning

Date: Sat Apr 11 2026 - 20:06:07 EST


Replace open-coded width * height * sizeof() multiplications with
array3_size() to prevent integer overflow in buffer allocations.

The atomisp driver computes DVS, morphing table, shading table and
statistics buffer sizes using unchecked arithmetic. When dimensions
are attacker-controlled or simply large, the product can silently wrap,
causing kvmalloc() to allocate an undersized buffer.

array3_size() saturates to SIZE_MAX on overflow, so kvmalloc() returns
NULL instead of succeeding with too few bytes.

Signed-off-by: Feng Ning <feng@xxxxxxxxx>
---
.../media/atomisp/pci/sh_css_param_dvs.c | 11 +++---
.../media/atomisp/pci/sh_css_param_shading.c | 4 ++-
.../staging/media/atomisp/pci/sh_css_params.c | 35 +++++++++++--------
3 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c b/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c
index 9ccdb66de..6a6e9fe2e 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c
@@ -4,6 +4,7 @@
* Copyright (c) 2015, Intel Corporation.
*/

+#include <linux/overflow.h>
#include "sh_css_param_dvs.h"
#include <assert_support.h>
#include <type_support.h>
@@ -48,7 +49,7 @@ alloc_dvs_6axis_table(const struct ia_css_resolution *frame_res,
}

/* Generate Y buffers */
- dvs_config->xcoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
+ dvs_config->xcoords_y = kvmalloc(array3_size(width_y, height_y, sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->xcoords_y) {
IA_CSS_ERROR("out of memory");
@@ -56,7 +57,7 @@ alloc_dvs_6axis_table(const struct ia_css_resolution *frame_res,
goto exit;
}

- dvs_config->ycoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
+ dvs_config->ycoords_y = kvmalloc(array3_size(width_y, height_y, sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->ycoords_y) {
IA_CSS_ERROR("out of memory");
@@ -67,7 +68,8 @@ alloc_dvs_6axis_table(const struct ia_css_resolution *frame_res,
/* Generate UV buffers */
IA_CSS_LOG("UV W %d H %d", width_uv, height_uv);

- dvs_config->xcoords_uv = kvmalloc(width_uv * height_uv * sizeof(uint32_t),
+ dvs_config->xcoords_uv = kvmalloc(array3_size(width_uv, height_uv,
+ sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->xcoords_uv) {
IA_CSS_ERROR("out of memory");
@@ -75,7 +77,8 @@ alloc_dvs_6axis_table(const struct ia_css_resolution *frame_res,
goto exit;
}

- dvs_config->ycoords_uv = kvmalloc(width_uv * height_uv * sizeof(uint32_t),
+ dvs_config->ycoords_uv = kvmalloc(array3_size(width_uv, height_uv,
+ sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->ycoords_uv) {
IA_CSS_ERROR("out of memory");
diff --git a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c
index 9105334c7..a7584deb6 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_param_shading.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_param_shading.c
@@ -4,6 +4,7 @@
* Copyright (c) 2015, Intel Corporation.
*/

+#include <linux/overflow.h>
#include <linux/math.h>
#include <linux/slab.h>

@@ -339,7 +340,8 @@ ia_css_shading_table_alloc(
me->fraction_bits = 0;
for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
me->data[i] =
- kvmalloc(width * height * sizeof(*me->data[0]),
+ kvmalloc(array3_size(width, height,
+ sizeof(*me->data[0])),
GFP_KERNEL);
if (!me->data[i]) {
unsigned int j;
diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c
index fcebace11..843338888 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_params.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_params.c
@@ -4,6 +4,7 @@
* Copyright (c) 2015, Intel Corporation.
*/

+#include <linux/overflow.h>
#include <linux/math.h>

#include "gdc_device.h" /* gdc_lut_store(), ... */
@@ -1381,11 +1382,11 @@ struct ia_css_morph_table *ia_css_morph_table_allocate(
}

for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
- me->coordinates_x[i] = kvmalloc(height * width *
- sizeof(*me->coordinates_x[i]),
+ me->coordinates_x[i] = kvmalloc(array3_size(height, width,
+ sizeof(*me->coordinates_x[i])),
GFP_KERNEL);
- me->coordinates_y[i] = kvmalloc(height * width *
- sizeof(*me->coordinates_y[i]),
+ me->coordinates_y[i] = kvmalloc(array3_size(height, width,
+ sizeof(*me->coordinates_y[i])),
GFP_KERNEL);

if ((!me->coordinates_x[i]) ||
@@ -4206,13 +4207,17 @@ ia_css_dvs_statistics_allocate(const struct ia_css_dvs_grid_info *grid)
goto err;

me->grid = *grid;
- me->hor_proj = kvmalloc(grid->height * IA_CSS_DVS_NUM_COEF_TYPES *
- sizeof(*me->hor_proj), GFP_KERNEL);
+ me->hor_proj = kvmalloc(array3_size(grid->height,
+ IA_CSS_DVS_NUM_COEF_TYPES,
+ sizeof(*me->hor_proj)),
+ GFP_KERNEL);
if (!me->hor_proj)
goto err;

- me->ver_proj = kvmalloc(grid->width * IA_CSS_DVS_NUM_COEF_TYPES *
- sizeof(*me->ver_proj), GFP_KERNEL);
+ me->ver_proj = kvmalloc(array3_size(grid->width,
+ IA_CSS_DVS_NUM_COEF_TYPES,
+ sizeof(*me->ver_proj)),
+ GFP_KERNEL);
if (!me->ver_proj)
goto err;

@@ -4478,24 +4483,26 @@ ia_css_dvs2_6axis_config_allocate(const struct ia_css_stream *stream)
params->pipe_dvs_6axis_config[IA_CSS_PIPE_ID_VIDEO]->height_uv;
IA_CSS_LOG("table Y: W %d H %d", width_y, height_y);
IA_CSS_LOG("table UV: W %d H %d", width_uv, height_uv);
- dvs_config->xcoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
+ dvs_config->xcoords_y = kvmalloc(array3_size(width_y, height_y,
+ sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->xcoords_y)
goto err;

- dvs_config->ycoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
+ dvs_config->ycoords_y = kvmalloc(array3_size(width_y, height_y,
+ sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->ycoords_y)
goto err;

- dvs_config->xcoords_uv = kvmalloc(width_uv * height_uv *
- sizeof(uint32_t),
+ dvs_config->xcoords_uv = kvmalloc(array3_size(width_uv, height_uv,
+ sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->xcoords_uv)
goto err;

- dvs_config->ycoords_uv = kvmalloc(width_uv * height_uv *
- sizeof(uint32_t),
+ dvs_config->ycoords_uv = kvmalloc(array3_size(width_uv, height_uv,
+ sizeof(uint32_t)),
GFP_KERNEL);
if (!dvs_config->ycoords_uv)
goto err;
--
2.43.0