[PATCH v6] staging: media: atomisp: use kvmalloc_objs() for overflow-safe allocations
From: Feng Ning
Date: Wed Apr 15 2026 - 00:47:36 EST
Replace open-coded width * height * sizeof() multiplications with
kvmalloc_objs() and array_size() to prevent integer overflow in buffer
allocations.
The atomisp driver computes DVS, morphing table, and statistics buffer
sizes using unchecked arithmetic. When dimensions are large, the
product can silently wrap, causing kvmalloc() to allocate an undersized
buffer.
kvmalloc_objs() uses size_mul() internally, which saturates to SIZE_MAX
on overflow, so kvmalloc() returns NULL instead of succeeding with too
few bytes. array_size() provides the same overflow protection for the
two-factor dimension products. Common size expressions are extracted to
local variables to avoid recomputing them across repeated allocations in
the same function.
Suggested-by: Andy Shevchenko <andy.shevchenko@xxxxxxxxx>
Signed-off-by: Feng Ning <feng@xxxxxxxxx>
---
.../media/atomisp/pci/sh_css_param_dvs.c | 18 ++---
.../staging/media/atomisp/pci/sh_css_params.c | 72 +++++++------------
2 files changed, 34 insertions(+), 56 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..2947e0f48 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,9 @@
* Copyright (c) 2015, Intel Corporation.
*/
+#include <linux/overflow.h>
+#include <linux/slab.h>
+
#include "sh_css_param_dvs.h"
#include <assert_support.h>
#include <type_support.h>
@@ -48,16 +51,17 @@ 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),
- GFP_KERNEL);
+ size_t cnt_y = array_size(width_y, height_y);
+ size_t cnt_uv = array_size(width_uv, height_uv);
+
+ dvs_config->xcoords_y = kvmalloc_objs(*dvs_config->xcoords_y, cnt_y);
if (!dvs_config->xcoords_y) {
IA_CSS_ERROR("out of memory");
err = -ENOMEM;
goto exit;
}
- dvs_config->ycoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
- GFP_KERNEL);
+ dvs_config->ycoords_y = kvmalloc_objs(*dvs_config->ycoords_y, cnt_y);
if (!dvs_config->ycoords_y) {
IA_CSS_ERROR("out of memory");
err = -ENOMEM;
@@ -67,16 +71,14 @@ 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),
- GFP_KERNEL);
+ dvs_config->xcoords_uv = kvmalloc_objs(*dvs_config->xcoords_uv, cnt_uv);
if (!dvs_config->xcoords_uv) {
IA_CSS_ERROR("out of memory");
err = -ENOMEM;
goto exit;
}
- dvs_config->ycoords_uv = kvmalloc(width_uv * height_uv * sizeof(uint32_t),
- GFP_KERNEL);
+ dvs_config->ycoords_uv = kvmalloc_objs(*dvs_config->ycoords_uv, cnt_uv);
if (!dvs_config->ycoords_uv) {
IA_CSS_ERROR("out of memory");
err = -ENOMEM;
diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c
index fcebace11..00d126665 100644
--- a/drivers/staging/media/atomisp/pci/sh_css_params.c
+++ b/drivers/staging/media/atomisp/pci/sh_css_params.c
@@ -5,6 +5,8 @@
*/
#include <linux/math.h>
+#include <linux/overflow.h>
+#include <linux/slab.h>
#include "gdc_device.h" /* gdc_lut_store(), ... */
#include "isp.h" /* ISP_VEC_ELEMBITS */
@@ -1380,13 +1382,11 @@ struct ia_css_morph_table *ia_css_morph_table_allocate(
me->coordinates_y[i] = NULL;
}
+ size_t cnt = array_size(height, width);
+
for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
- me->coordinates_x[i] = kvmalloc(height * width *
- sizeof(*me->coordinates_x[i]),
- GFP_KERNEL);
- me->coordinates_y[i] = kvmalloc(height * width *
- sizeof(*me->coordinates_y[i]),
- GFP_KERNEL);
+ me->coordinates_x[i] = kvmalloc_objs(*me->coordinates_x[i], cnt);
+ me->coordinates_y[i] = kvmalloc_objs(*me->coordinates_y[i], cnt);
if ((!me->coordinates_x[i]) ||
(!me->coordinates_y[i])) {
@@ -4206,13 +4206,13 @@ 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_objs(*me->hor_proj,
+ array_size(grid->height, IA_CSS_DVS_NUM_COEF_TYPES));
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_objs(*me->ver_proj,
+ array_size(grid->width, IA_CSS_DVS_NUM_COEF_TYPES));
if (!me->ver_proj)
goto err;
@@ -4245,15 +4245,13 @@ ia_css_dvs_coefficients_allocate(const struct ia_css_dvs_grid_info *grid)
me->grid = *grid;
- me->hor_coefs = kvmalloc(grid->num_hor_coefs *
- IA_CSS_DVS_NUM_COEF_TYPES *
- sizeof(*me->hor_coefs), GFP_KERNEL);
+ me->hor_coefs = kvmalloc_objs(*me->hor_coefs,
+ array_size(grid->num_hor_coefs, IA_CSS_DVS_NUM_COEF_TYPES));
if (!me->hor_coefs)
goto err;
- me->ver_coefs = kvmalloc(grid->num_ver_coefs *
- IA_CSS_DVS_NUM_COEF_TYPES *
- sizeof(*me->ver_coefs), GFP_KERNEL);
+ me->ver_coefs = kvmalloc_objs(*me->ver_coefs,
+ array_size(grid->num_ver_coefs, IA_CSS_DVS_NUM_COEF_TYPES));
if (!me->ver_coefs)
goto err;
@@ -4286,59 +4284,37 @@ ia_css_dvs2_statistics_allocate(const struct ia_css_dvs_grid_info *grid)
me->grid = *grid;
- me->hor_prod.odd_real = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->hor_prod.odd_real),
- GFP_KERNEL);
+ size_t cnt = array_size(grid->aligned_width, grid->aligned_height);
+
+ me->hor_prod.odd_real = kvmalloc_objs(*me->hor_prod.odd_real, cnt);
if (!me->hor_prod.odd_real)
goto err;
- me->hor_prod.odd_imag = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->hor_prod.odd_imag),
- GFP_KERNEL);
+ me->hor_prod.odd_imag = kvmalloc_objs(*me->hor_prod.odd_imag, cnt);
if (!me->hor_prod.odd_imag)
goto err;
- me->hor_prod.even_real = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->hor_prod.even_real),
- GFP_KERNEL);
+ me->hor_prod.even_real = kvmalloc_objs(*me->hor_prod.even_real, cnt);
if (!me->hor_prod.even_real)
goto err;
- me->hor_prod.even_imag = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->hor_prod.even_imag),
- GFP_KERNEL);
+ me->hor_prod.even_imag = kvmalloc_objs(*me->hor_prod.even_imag, cnt);
if (!me->hor_prod.even_imag)
goto err;
- me->ver_prod.odd_real = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->ver_prod.odd_real),
- GFP_KERNEL);
+ me->ver_prod.odd_real = kvmalloc_objs(*me->ver_prod.odd_real, cnt);
if (!me->ver_prod.odd_real)
goto err;
- me->ver_prod.odd_imag = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->ver_prod.odd_imag),
- GFP_KERNEL);
+ me->ver_prod.odd_imag = kvmalloc_objs(*me->ver_prod.odd_imag, cnt);
if (!me->ver_prod.odd_imag)
goto err;
- me->ver_prod.even_real = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->ver_prod.even_real),
- GFP_KERNEL);
+ me->ver_prod.even_real = kvmalloc_objs(*me->ver_prod.even_real, cnt);
if (!me->ver_prod.even_real)
goto err;
- me->ver_prod.even_imag = kvmalloc(grid->aligned_width *
- grid->aligned_height *
- sizeof(*me->ver_prod.even_imag),
- GFP_KERNEL);
+ me->ver_prod.even_imag = kvmalloc_objs(*me->ver_prod.even_imag, cnt);
if (!me->ver_prod.even_imag)
goto err;
--
2.49.0