linux: kmd: static analysis S12/11 part 4

Under the following path:
- drivers/media/platform/tegra/camera/fusa-capture/capture-common.c
- drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c
- drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c
- drivers/media/platform/tegra/camera/tegracam_utils.c
- drivers/media/platform/tegra/camera/vi/core.c

Jira CAMERASW-30251

Change-Id: Iec7c29a184a060b8e7f44f3614bcbc9f8182aea6
Signed-off-by: Junsheng Chen <junshengc@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270228
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
Reviewed-by: Zhiyuan Wang <zhiwang@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
This commit is contained in:
Junsheng Chen
2024-12-18 02:56:04 +00:00
committed by Jon Hunter
parent 0f04d6c204
commit cd6a1c3a7d
5 changed files with 100 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2017-2023 NVIDIA Corporation. All rights reserved. // SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/** /**
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-common.c * @file drivers/media/platform/tegra/camera/fusa-capture/capture-common.c
@@ -139,11 +139,8 @@ static inline dma_addr_t mapping_iova(
for_each_sgtable_dma_sg(pin->sgt, sg, i) { for_each_sgtable_dma_sg(pin->sgt, sg, i) {
if (mem_offset_adjusted < sg_dma_len(sg)) { if (mem_offset_adjusted < sg_dma_len(sg)) {
iova = (sg_dma_address(sg) == 0) ? sg_phys(sg) : sg_dma_address(sg); iova = (sg_dma_address(sg) == 0) ? sg_phys(sg) : sg_dma_address(sg);
iova += mem_offset_adjusted; if (check_add_overflow(iova, mem_offset_adjusted, &iova))
if (iova < mem_offset_adjusted) {
/** It means iova has wrapped */
return 0; return 0;
}
break; break;
} }
mem_offset_adjusted -= sg_dma_len(sg); mem_offset_adjusted -= sg_dma_len(sg);

View File

@@ -461,8 +461,12 @@ static int isp_capture_setup_inputfences(
reloc_page_addr = vmap_base; reloc_page_addr = vmap_base;
for (i = 0; i < req->inputfences_relocs.num_relocs; i++) { for (i = 0; i < req->inputfences_relocs.num_relocs; i++) {
inputfences_offset = request_offset + if (check_add_overflow(
inpfences_relocs[i]; request_offset, (int)inpfences_relocs[i], (int *)(&inputfences_offset))) {
err = -EOVERFLOW;
goto fail;
}
err = isp_capture_populate_fence_info(chan, inputfences_offset, err = isp_capture_populate_fence_info(chan, inputfences_offset,
req->gos_relative, req->sp_relative, reloc_page_addr); req->gos_relative, req->sp_relative, reloc_page_addr);
if (err < 0) { if (err < 0) {
@@ -551,8 +555,12 @@ static int isp_capture_setup_prefences(
reloc_page_addr = vmap_base; reloc_page_addr = vmap_base;
for (i = 0; i < req->prefences_relocs.num_relocs; i++) { for (i = 0; i < req->prefences_relocs.num_relocs; i++) {
prefence_offset = request_offset + if (check_add_overflow(
prefence_relocs[i]; request_offset, (int)prefence_relocs[i], (int *)(&prefence_offset))) {
err = -EOVERFLOW;
goto fail;
}
err = isp_capture_populate_fence_info(chan, prefence_offset, err = isp_capture_populate_fence_info(chan, prefence_offset,
req->gos_relative, req->sp_relative, reloc_page_addr); req->gos_relative, req->sp_relative, reloc_page_addr);
if (err < 0) { if (err < 0) {
@@ -681,6 +689,7 @@ static int isp_capture_program_prepare(
struct memoryinfo_surface *meminfo; struct memoryinfo_surface *meminfo;
struct isp_program_descriptor *desc; struct isp_program_descriptor *desc;
uint32_t request_offset; uint32_t request_offset;
uint32_t mem_offset;
if (capture == NULL) { if (capture == NULL) {
dev_err(chan->isp_dev, dev_err(chan->isp_dev,
@@ -743,9 +752,12 @@ static int isp_capture_program_prepare(
request_offset = req->buffer_index * request_offset = req->buffer_index *
capture->program_desc_ctx.request_size; capture->program_desc_ctx.request_size;
if (check_add_overflow((uint32_t)desc->isp_pb1_mem, request_offset, &mem_offset))
return -EOVERFLOW;
err = capture_common_pin_and_get_iova(chan->capture_data->buffer_ctx, err = capture_common_pin_and_get_iova(chan->capture_data->buffer_ctx,
(uint32_t)(desc->isp_pb1_mem >> 32U), /* mem handle */ (uint32_t)(desc->isp_pb1_mem >> 32U), /* mem handle */
((uint32_t)desc->isp_pb1_mem) + request_offset, /* offset */ mem_offset, /* offset */
&meminfo->base_address, &meminfo->base_address,
&meminfo->size, &meminfo->size,
&capture->program_desc_ctx.unpins_list[req->buffer_index]); &capture->program_desc_ctx.unpins_list[req->buffer_index]);
@@ -849,17 +861,26 @@ static inline void isp_capture_ivc_program_signal(
struct isp_capture *capture, struct isp_capture *capture,
uint32_t buffer_index) uint32_t buffer_index)
{ {
uint32_t buffer_slot = 0;
uint32_t buffer_depth = 0;
if (capture->is_progress_status_notifier_set) { if (capture->is_progress_status_notifier_set) {
if (check_add_overflow(buffer_index,
capture->capture_desc_ctx.progress_status_buffer_depth, &buffer_slot))
return;
if (check_add_overflow(capture->program_desc_ctx.progress_status_buffer_depth,
capture->capture_desc_ctx.progress_status_buffer_depth, &buffer_depth))
return;
/* /*
* Program status notifiers are after the process status * Program status notifiers are after the process status
* notifiers; add the process status buffer depth as an offset. * notifiers; add the process status buffer depth as an offset.
*/ */
(void)capture_common_set_progress_status( (void)capture_common_set_progress_status(
&capture->progress_status_notifier, &capture->progress_status_notifier,
buffer_index + buffer_slot,
capture->capture_desc_ctx.progress_status_buffer_depth, buffer_depth,
capture->program_desc_ctx.progress_status_buffer_depth +
capture->capture_desc_ctx.progress_status_buffer_depth,
PROGRESS_STATUS_DONE); PROGRESS_STATUS_DONE);
} else { } else {
/* /*
@@ -1746,9 +1767,7 @@ static int pin_isp_capture_request_buffers_locked(
{ {
struct isp_desc_rec *capture_desc_ctx = struct isp_desc_rec *capture_desc_ctx =
&chan->capture_data->capture_desc_ctx; &chan->capture_data->capture_desc_ctx;
struct isp_capture_descriptor *desc = (struct isp_capture_descriptor *) struct isp_capture_descriptor *desc;
(capture_desc_ctx->requests.va +
req->buffer_index * capture_desc_ctx->request_size);
struct isp_capture_descriptor_memoryinfo *desc_mem = struct isp_capture_descriptor_memoryinfo *desc_mem =
&((struct isp_capture_descriptor_memoryinfo *) &((struct isp_capture_descriptor_memoryinfo *)
@@ -1759,14 +1778,32 @@ static int pin_isp_capture_request_buffers_locked(
chan->capture_data->buffer_ctx; chan->capture_data->buffer_ctx;
int i, j; int i, j;
int err = 0; int err = 0;
uint32_t desc_offset = 0;
/* Pushbuffer 2 is located after isp desc, in same ringbuffer */ /* Pushbuffer 2 is located after isp desc, in same ringbuffer */
uint32_t request_offset = req->buffer_index * uint32_t request_offset = 0;
capture_desc_ctx->request_size; uint32_t isp_pb2_mem_offset = 0;
if (check_mul_overflow(req->buffer_index, capture_desc_ctx->request_size, &desc_offset)) {
err = -EOVERFLOW;
goto fail;
}
desc = (struct isp_capture_descriptor *)(capture_desc_ctx->requests.va + desc_offset);
if (check_mul_overflow(req->buffer_index, capture_desc_ctx->request_size, &request_offset)) {
err = -EOVERFLOW;
goto fail;
}
if (check_add_overflow((uint32_t)desc->isp_pb2_mem, request_offset, &isp_pb2_mem_offset)) {
err = -EOVERFLOW;
goto fail;
}
err = capture_common_pin_and_get_iova(buffer_ctx, err = capture_common_pin_and_get_iova(buffer_ctx,
(uint32_t)(desc->isp_pb2_mem >> 32U), (uint32_t)(desc->isp_pb2_mem >> 32U),
((uint32_t)desc->isp_pb2_mem) + request_offset, isp_pb2_mem_offset,
&desc_mem->isp_pb2_mem.base_address, &desc_mem->isp_pb2_mem.base_address,
&desc_mem->isp_pb2_mem.size, &desc_mem->isp_pb2_mem.size,
request_unpins); request_unpins);

View File

@@ -1057,15 +1057,14 @@ EXPORT_SYMBOL_GPL(vi_capture_release);
static int vi_capture_control_send_message( static int vi_capture_control_send_message(
struct tegra_vi_channel *chan, struct tegra_vi_channel *chan,
const struct CAPTURE_CONTROL_MSG *msg_cpy, struct CAPTURE_CONTROL_MSG *msg_cpy,
size_t size) size_t size)
{ {
int err = 0; int err = 0;
struct vi_capture *capture = chan->capture_data; struct vi_capture *capture = chan->capture_data;
struct CAPTURE_MSG_HEADER *header;
uint32_t resp_id; uint32_t resp_id;
header = (struct CAPTURE_MSG_HEADER *)msg_cpy; struct CAPTURE_MSG_HEADER *header = &msg_cpy->header;
header->channel_id = capture->channel_id; header->channel_id = capture->channel_id;
switch (header->msg_id) { switch (header->msg_id) {

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2018-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/* /*
* tegracam_utils - tegra camera framework utilities * tegracam_utils - tegra camera framework utilities
*
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
*/ */
#include <linux/types.h> #include <linux/types.h>
@@ -47,11 +47,18 @@ EXPORT_SYMBOL_GPL(conv_u16_u8arr);
static inline int is_valid_blob(struct sensor_blob *blob, u32 size) static inline int is_valid_blob(struct sensor_blob *blob, u32 size)
{ {
u32 blob_size = 0;
if (!blob) if (!blob)
return -EINVAL; return -EINVAL;
if ((blob->num_cmds >= MAX_COMMANDS) || if (blob->num_cmds >= MAX_COMMANDS)
((blob->buf_size + size) >= MAX_BLOB_SIZE)) return -ENOMEM;
if (check_add_overflow(blob->buf_size, size, &blob_size))
return -EOVERFLOW;
if (blob_size > MAX_BLOB_SIZE)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
@@ -73,7 +80,8 @@ int prepare_write_cmd(struct sensor_blob *blob,
memcpy(&blob->buf[blob->buf_size], buf, size); memcpy(&blob->buf[blob->buf_size], buf, size);
blob->buf_size += size; if (check_add_overflow(blob->buf_size, size, &blob->buf_size))
return -EOVERFLOW;
return 0; return 0;
} }
@@ -93,7 +101,8 @@ int prepare_read_cmd(struct sensor_blob *blob,
cmd->opcode = ((SENSOR_OPCODE_READ << 24) | size); cmd->opcode = ((SENSOR_OPCODE_READ << 24) | size);
cmd->addr = addr; cmd->addr = addr;
blob->buf_size += size; if (check_add_overflow(blob->buf_size, size, &blob->buf_size))
return -EOVERFLOW;
return 0; return 0;
} }
@@ -141,6 +150,7 @@ int convert_table_to_blob(struct sensor_blob *blob,
int range_start = -1; int range_start = -1;
u32 range_count = 0; u32 range_count = 0;
u8 buf[16]; u8 buf[16];
u16 range_pos = 0;
for (next = table;; next++) { for (next = table;; next++) {
val = next->val; val = next->val;
@@ -148,8 +158,11 @@ int convert_table_to_blob(struct sensor_blob *blob,
if (range_start == -1) if (range_start == -1)
range_start = next->addr; range_start = next->addr;
if (check_add_overflow((u16)range_start, (u16)range_count, &range_pos))
return 0;
if (range_count == 16 || if (range_count == 16 ||
(addr != (range_start + range_count))) { (addr != range_pos)) {
/* write opcode and size for store index*/ /* write opcode and size for store index*/
prepare_write_cmd(blob, range_count, prepare_write_cmd(blob, range_count,
range_start, &buf[0]); range_start, &buf[0]);

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/* /*
* NVIDIA Tegra Video Input Device Driver Core Helpers * NVIDIA Tegra Video Input Device Driver Core Helpers
*
* Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved.
*/ */
#include <linux/export.h> #include <linux/export.h>
@@ -39,8 +39,13 @@ static const struct tegra_video_format tegra_default_format[] = {
u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan, u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan,
unsigned int index) unsigned int index)
{ {
unsigned int cal_index = 0;
if (check_sub_overflow(chan->num_video_formats, 1U, &cal_index))
return V4L2_PIX_FMT_SGRBG10;
/* return default fourcc format if the index out of bounds */ /* return default fourcc format if the index out of bounds */
if (index > (chan->num_video_formats - 1)) if (index > cal_index)
return V4L2_PIX_FMT_SGRBG10; return V4L2_PIX_FMT_SGRBG10;
index = array_index_nospec(index, chan->num_video_formats); index = array_index_nospec(index, chan->num_video_formats);
@@ -58,7 +63,12 @@ EXPORT_SYMBOL(tegra_core_get_fourcc_by_idx);
u32 tegra_core_get_word_count(unsigned int frame_width, u32 tegra_core_get_word_count(unsigned int frame_width,
const struct tegra_video_format *fmt) const struct tegra_video_format *fmt)
{ {
return frame_width * fmt->width / 8; unsigned int pixels_num = 0;
if (check_mul_overflow(frame_width, fmt->width, &pixels_num))
return 0;
return pixels_num / 8;
} }
/** /**
@@ -177,7 +187,13 @@ EXPORT_SYMBOL(tegra_core_get_format_by_fourcc);
u32 tegra_core_bytes_per_line(unsigned int width, unsigned int align, u32 tegra_core_bytes_per_line(unsigned int width, unsigned int align,
const struct tegra_video_format *fmt) const struct tegra_video_format *fmt)
{ {
u32 value = ((width * fmt->bpp.numerator) / fmt->bpp.denominator); unsigned int mul_value = 0;
unsigned int value = 0;
if (check_mul_overflow(width, fmt->bpp.numerator, &mul_value))
return 0;
value = (mul_value / fmt->bpp.denominator);
return roundup(value, align); return roundup(value, align);
} }