From cd6a1c3a7dc5d797bfa2010edd2ca0c41c53a386 Mon Sep 17 00:00:00 2001 From: Junsheng Chen Date: Wed, 18 Dec 2024 02:56:04 +0000 Subject: [PATCH] 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 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270228 Reviewed-by: svcacv GVS: buildbot_gerritrpt Reviewed-by: Sumeet Gupta Reviewed-by: Zhiyuan Wang Reviewed-by: Ankur Pawar --- .../camera/fusa-capture/capture-common.c | 9 +-- .../tegra/camera/fusa-capture/capture-isp.c | 67 ++++++++++++++----- .../tegra/camera/fusa-capture/capture-vi.c | 5 +- .../platform/tegra/camera/tegracam_utils.c | 29 +++++--- drivers/media/platform/tegra/camera/vi/core.c | 28 ++++++-- 5 files changed, 100 insertions(+), 38 deletions(-) diff --git a/drivers/media/platform/tegra/camera/fusa-capture/capture-common.c b/drivers/media/platform/tegra/camera/fusa-capture/capture-common.c index 9a80e535..28dfd8bb 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-common.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-common.c @@ -1,5 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2017-2023 NVIDIA Corporation. All rights reserved. +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. /** * @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) { if (mem_offset_adjusted < sg_dma_len(sg)) { iova = (sg_dma_address(sg) == 0) ? sg_phys(sg) : sg_dma_address(sg); - iova += mem_offset_adjusted; - if (iova < mem_offset_adjusted) { - /** It means iova has wrapped */ + if (check_add_overflow(iova, mem_offset_adjusted, &iova)) return 0; - } break; } mem_offset_adjusted -= sg_dma_len(sg); diff --git a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c index d3b4479f..4ac8e208 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c @@ -461,8 +461,12 @@ static int isp_capture_setup_inputfences( reloc_page_addr = vmap_base; for (i = 0; i < req->inputfences_relocs.num_relocs; i++) { - inputfences_offset = request_offset + - inpfences_relocs[i]; + if (check_add_overflow( + request_offset, (int)inpfences_relocs[i], (int *)(&inputfences_offset))) { + err = -EOVERFLOW; + goto fail; + } + err = isp_capture_populate_fence_info(chan, inputfences_offset, req->gos_relative, req->sp_relative, reloc_page_addr); if (err < 0) { @@ -551,8 +555,12 @@ static int isp_capture_setup_prefences( reloc_page_addr = vmap_base; for (i = 0; i < req->prefences_relocs.num_relocs; i++) { - prefence_offset = request_offset + - prefence_relocs[i]; + if (check_add_overflow( + request_offset, (int)prefence_relocs[i], (int *)(&prefence_offset))) { + err = -EOVERFLOW; + goto fail; + } + err = isp_capture_populate_fence_info(chan, prefence_offset, req->gos_relative, req->sp_relative, reloc_page_addr); if (err < 0) { @@ -681,6 +689,7 @@ static int isp_capture_program_prepare( struct memoryinfo_surface *meminfo; struct isp_program_descriptor *desc; uint32_t request_offset; + uint32_t mem_offset; if (capture == NULL) { dev_err(chan->isp_dev, @@ -743,9 +752,12 @@ static int isp_capture_program_prepare( request_offset = req->buffer_index * 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, (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->size, &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, uint32_t buffer_index) { + uint32_t buffer_slot = 0; + uint32_t buffer_depth = 0; + 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 * notifiers; add the process status buffer depth as an offset. */ (void)capture_common_set_progress_status( &capture->progress_status_notifier, - buffer_index + - capture->capture_desc_ctx.progress_status_buffer_depth, - capture->program_desc_ctx.progress_status_buffer_depth + - capture->capture_desc_ctx.progress_status_buffer_depth, + buffer_slot, + buffer_depth, PROGRESS_STATUS_DONE); } else { /* @@ -1746,9 +1767,7 @@ static int pin_isp_capture_request_buffers_locked( { struct isp_desc_rec *capture_desc_ctx = &chan->capture_data->capture_desc_ctx; - struct isp_capture_descriptor *desc = (struct isp_capture_descriptor *) - (capture_desc_ctx->requests.va + - req->buffer_index * capture_desc_ctx->request_size); + struct isp_capture_descriptor *desc; struct isp_capture_descriptor_memoryinfo *desc_mem = &((struct isp_capture_descriptor_memoryinfo *) @@ -1759,14 +1778,32 @@ static int pin_isp_capture_request_buffers_locked( chan->capture_data->buffer_ctx; int i, j; int err = 0; + uint32_t desc_offset = 0; /* Pushbuffer 2 is located after isp desc, in same ringbuffer */ - uint32_t request_offset = req->buffer_index * - capture_desc_ctx->request_size; + uint32_t request_offset = 0; + 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, (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.size, request_unpins); diff --git a/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c b/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c index e8074d30..6482e5d6 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c @@ -1057,15 +1057,14 @@ EXPORT_SYMBOL_GPL(vi_capture_release); static int vi_capture_control_send_message( struct tegra_vi_channel *chan, - const struct CAPTURE_CONTROL_MSG *msg_cpy, + struct CAPTURE_CONTROL_MSG *msg_cpy, size_t size) { int err = 0; struct vi_capture *capture = chan->capture_data; - struct CAPTURE_MSG_HEADER *header; 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; switch (header->msg_id) { diff --git a/drivers/media/platform/tegra/camera/tegracam_utils.c b/drivers/media/platform/tegra/camera/tegracam_utils.c index 5530c9b7..6b044788 100644 --- a/drivers/media/platform/tegra/camera/tegracam_utils.c +++ b/drivers/media/platform/tegra/camera/tegracam_utils.c @@ -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 - * - * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved. */ #include @@ -47,11 +47,18 @@ EXPORT_SYMBOL_GPL(conv_u16_u8arr); static inline int is_valid_blob(struct sensor_blob *blob, u32 size) { + u32 blob_size = 0; + if (!blob) return -EINVAL; - if ((blob->num_cmds >= MAX_COMMANDS) || - ((blob->buf_size + size) >= MAX_BLOB_SIZE)) + if (blob->num_cmds >= MAX_COMMANDS) + return -ENOMEM; + + if (check_add_overflow(blob->buf_size, size, &blob_size)) + return -EOVERFLOW; + + if (blob_size > MAX_BLOB_SIZE) return -ENOMEM; return 0; @@ -73,7 +80,8 @@ int prepare_write_cmd(struct sensor_blob *blob, 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; } @@ -93,7 +101,8 @@ int prepare_read_cmd(struct sensor_blob *blob, cmd->opcode = ((SENSOR_OPCODE_READ << 24) | size); cmd->addr = addr; - blob->buf_size += size; + if (check_add_overflow(blob->buf_size, size, &blob->buf_size)) + return -EOVERFLOW; return 0; } @@ -141,6 +150,7 @@ int convert_table_to_blob(struct sensor_blob *blob, int range_start = -1; u32 range_count = 0; u8 buf[16]; + u16 range_pos = 0; for (next = table;; next++) { val = next->val; @@ -148,8 +158,11 @@ int convert_table_to_blob(struct sensor_blob *blob, if (range_start == -1) range_start = next->addr; + if (check_add_overflow((u16)range_start, (u16)range_count, &range_pos)) + return 0; + if (range_count == 16 || - (addr != (range_start + range_count))) { + (addr != range_pos)) { /* write opcode and size for store index*/ prepare_write_cmd(blob, range_count, range_start, &buf[0]); diff --git a/drivers/media/platform/tegra/camera/vi/core.c b/drivers/media/platform/tegra/camera/vi/core.c index f0bde35a..30ed1307 100644 --- a/drivers/media/platform/tegra/camera/vi/core.c +++ b/drivers/media/platform/tegra/camera/vi/core.c @@ -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 - * - * Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved. */ #include @@ -39,8 +39,13 @@ static const struct tegra_video_format tegra_default_format[] = { u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan, 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 */ - if (index > (chan->num_video_formats - 1)) + if (index > cal_index) return V4L2_PIX_FMT_SGRBG10; 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, 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, 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); }