From ff7cf02ef2b043293370f35835fa6f443fdb19a6 Mon Sep 17 00:00:00 2001 From: Yuyuan Chen Date: Tue, 14 Jan 2025 06:45:33 +0000 Subject: [PATCH] kernel: nvidia-oot: Fix Static issues S12/11 Jira CAMERASW-30258 Change-Id: I5fd26611f6bac71ec186458a583622b55ba8735e Signed-off-by: Yuyuan Chen Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3262275 Reviewed-by: Ankur Pawar Reviewed-by: Sumeet Gupta Reviewed-by: Frank Chen GVS: buildbot_gerritrpt Reviewed-by: Ryan Li --- .../camera/fusa-capture/capture-isp-channel.c | 11 ++++ .../tegra/camera/fusa-capture/capture-isp.c | 10 ++- .../camera/fusa-capture/capture-vi-channel.c | 19 ++++-- .../tegra/camera/fusa-capture/capture-vi.c | 17 +----- .../media/platform/tegra/camera/regmap_util.c | 27 +++++--- .../media/platform/tegra/camera/vi/vi5_fops.c | 61 +++++++++++++------ 6 files changed, 97 insertions(+), 48 deletions(-) diff --git a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp-channel.c b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp-channel.c index e698ea94..3ad4b77f 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp-channel.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp-channel.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -519,6 +520,11 @@ int isp_channel_drv_register( chdrv_ = chan_drv; mutex_unlock(&chdrv_lock); + if (isp_channel_major < 0) { + pr_err("%s: Invalid major number for ISP channel\n", __func__); + return -EINVAL; + } + for (i = 0; i < chan_drv->num_channels; i++) { dev_t devt = MKDEV(isp_channel_major, i); @@ -568,6 +574,11 @@ void isp_channel_drv_unregister( WARN_ON(chan_drv->dev != dev); mutex_unlock(&chdrv_lock); + if (isp_channel_major < 0) { + pr_err("%s: Invalid major number for ISP channel\n", __func__); + return; + } + for (i = 0; i < chan_drv->num_channels; i++) { dev_t devt = MKDEV(isp_channel_major, i); 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 4ac8e208..c25fcf28 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c @@ -1156,11 +1156,17 @@ void isp_get_nvhost_device( struct tegra_isp_channel *chan, struct isp_capture_setup *setup) { - uint32_t isp_inst = setup->isp_unit; - + uint32_t isp_inst = 0U; struct tegra_capture_isp_data *info = platform_get_drvdata(chan->isp_capture_pdev); + if (setup == NULL) { + dev_err(chan->isp_dev, "%s: Invalid ISP capture request\n", __func__); + return; + } + + isp_inst = setup->isp_unit; + if (isp_inst >= MAX_ISP_UNITS) { dev_err(chan->isp_dev, "%s: ISP unit index is out of bound\n", __func__); diff --git a/drivers/media/platform/tegra/camera/fusa-capture/capture-vi-channel.c b/drivers/media/platform/tegra/camera/fusa-capture/capture-vi-channel.c index be9a9707..f3cefeeb 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-vi-channel.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-vi-channel.c @@ -322,14 +322,20 @@ static int pin_vi_capture_request_buffers_locked(struct tegra_vi_channel *chan, struct capture_common_unpins *request_unpins) { struct vi_capture *capture = chan->capture_data; - struct capture_descriptor* desc = (struct capture_descriptor*) - (capture->requests.va + - req->buffer_index * capture->request_size); - + struct capture_descriptor *desc = NULL; struct capture_descriptor_memoryinfo* desc_mem = &capture->requests_memoryinfo[req->buffer_index]; int i; int err = 0; + uint32_t buffer_amount = 0; + + if (check_mul_overflow(req->buffer_index, capture->request_size, &buffer_amount)) { + dev_err(chan->dev, "%s: Requests memoryinfo overflow\n", __func__); + return -EFAULT; + } + + desc = (struct capture_descriptor *) + (capture->requests.va + buffer_amount); /* Buffer count: ATOMP surfaces + engine_surface */ BUG_ON(VI_NUM_ATOMP_SURFACES + 1U >= MAX_PIN_BUFFER_PER_REQUEST); @@ -738,6 +744,11 @@ void vi_channel_drv_unregister( WARN_ON(&chan_drv->vi_capture_pdev->dev != dev); mutex_unlock(&chdrv_lock); + if (vi_channel_major < 0) { + pr_err("%s: Invalid major number for VI channel\n", __func__); + return; + } + for (i = 0; i < chan_drv->num_channels; i++) { dev_t devt = MKDEV(vi_channel_major, i); 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 6482e5d6..46e9a64c 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c @@ -1,17 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. - * All rights reserved. - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ +// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. /** * @file drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c @@ -586,8 +574,7 @@ void vi_get_nvhost_device( platform_get_drvdata(chan->vi_capture_pdev); if (setup->csi_stream_id >= MAX_NVCSI_STREAM_IDS) { - dev_err(chan->dev, - "%s: csi stream id is out of bound\n", __func__); + dev_err(&chan->vi_capture_pdev->dev, "CSI stream ID over the limit\n"); return; } diff --git a/drivers/media/platform/tegra/camera/regmap_util.c b/drivers/media/platform/tegra/camera/regmap_util.c index d81aa77a..a968ddb2 100644 --- a/drivers/media/platform/tegra/camera/regmap_util.c +++ b/drivers/media/platform/tegra/camera/regmap_util.c @@ -1,12 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * regmap_util.c - utilities for writing regmap tables - * - * Copyright (c) 2013-2022, NVIDIA Corporation. All Rights Reserved. - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// regmap_util.c - utilities for writing regmap tables #include #include +#include #include int @@ -22,6 +20,7 @@ regmap_util_write_table_8(struct regmap *regmap, int range_start = -1; unsigned int range_count = 0; + int range_end = 0; /* bug 200048392 - * the vi i2c cannot take a FIFO buffer bigger than 16 bytes */ @@ -32,7 +31,12 @@ regmap_util_write_table_8(struct regmap *regmap, /* If we have a range open and */ /* either the address doesn't match */ /* or the temporary storage is full, flush */ - if ((next->addr != range_start + range_count) || + if (check_add_overflow(range_start, (int)range_count, &range_end)) { + pr_err("%s:regmap_util_write_table overflow", __func__); + return -EINVAL; + } + + if ((next->addr != range_end) || (next->addr == end_addr) || (next->addr == wait_ms_addr) || (range_count == max_range_vals)) { @@ -104,6 +108,7 @@ regmap_util_write_table_16_as_8(struct regmap *regmap, int range_start = -1; unsigned int range_count = 0; + int range_end = 0; u8 range_vals[256]; int max_range_vals = ARRAY_SIZE(range_vals) - 1; @@ -111,7 +116,12 @@ regmap_util_write_table_16_as_8(struct regmap *regmap, /* If we have a range open and */ /* either the address doesn't match */ /* or the temporary storage is full, flush*/ - if ((next->addr != range_start + range_count) || + if (check_add_overflow(range_start, (int)range_count, &range_end)) { + pr_err("%s:regmap_util_write_table overflow", __func__); + return -EINVAL; + } + + if ((next->addr != range_end) || (next->addr == end_addr) || (next->addr == wait_ms_addr) || (range_count == max_range_vals)) { @@ -166,4 +176,3 @@ regmap_util_write_table_16_as_8(struct regmap *regmap, EXPORT_SYMBOL_GPL(regmap_util_write_table_16_as_8); MODULE_LICENSE("GPL"); - diff --git a/drivers/media/platform/tegra/camera/vi/vi5_fops.c b/drivers/media/platform/tegra/camera/vi/vi5_fops.c index 008b16d5..6e974dc7 100644 --- a/drivers/media/platform/tegra/camera/vi/vi5_fops.c +++ b/drivers/media/platform/tegra/camera/vi/vi5_fops.c @@ -1,15 +1,6 @@ -// SPDX-License-Identifier: GPL-2.0 -/* SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. - * All rights reserved. - * - * Tegra Video Input 5 device common APIs - * - * Author: Frank Chen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// Tegra Video Input 5 device common APIs. #include #include @@ -264,8 +255,12 @@ static int vi5_channel_open(struct tegra_channel *chan, u32 vi_port) * by the platform will trigger a ENODEV from the * VI capture channel driver */ - if (err == -EBUSY) - channel++; + if (err == -EBUSY) { + if (check_add_overflow(channel, 1, &channel)) { + dev_err(chan->vi->dev, "%s:channel overflow\n", __func__); + return -ENODEV; + } + } else { dev_err(&chan->video->dev, "Error opening VI capture channel node %s with err: %ld\n", @@ -390,22 +385,38 @@ static int tegra_channel_capture_setup(struct tegra_channel *chan, unsigned int static void vi5_setup_surface(struct tegra_channel *chan, struct tegra_channel_buffer *buf, unsigned int descr_index, unsigned int vi_port) { - dma_addr_t offset = buf->addr + chan->buffer_offset[vi_port]; + dma_addr_t offset = 0; u32 height = chan->format.height; u32 width = chan->format.width; u32 format = chan->fmtinfo->img_fmt; u32 bpl = chan->format.bytesperline; u32 data_type = chan->fmtinfo->img_dt; u32 nvcsi_stream = chan->port[vi_port]; + unsigned int range = 0; struct capture_descriptor_memoryinfo *desc_memoryinfo = &chan->tegra_vi_channel[vi_port]-> capture_data->requests_memoryinfo[descr_index]; struct capture_descriptor *desc = &chan->request[vi_port][descr_index]; + if (check_add_overflow(buf->addr, (dma_addr_t)chan->buffer_offset[vi_port], &offset)) { + dev_err(chan->vi->dev, "%s:Buf addr overflow\n", __func__); + return; + } + if (chan->valid_ports > NVCSI_STREAM_1) { height = chan->gang_height; width = chan->gang_width; - offset = buf->addr + chan->buffer_offset[1 - vi_port]; + + if (vi_port > 1) { + dev_err(chan->vi->dev, "%s: Invalid VI port number\n", __func__); + return; + } + + if (check_add_overflow(buf->addr, (dma_addr_t)chan->buffer_offset[1 - vi_port], + &offset)) { + dev_err(chan->vi->dev, "%s: Buf addr overflow\n", __func__); + return; + } } memcpy(desc, &capture_template, sizeof(capture_template)); @@ -444,7 +455,11 @@ static void vi5_setup_surface(struct tegra_channel *chan, = chan->embedded_data_width * BPP_MEM; } //capture sequence should increment for each vi channel - if ((chan->valid_ports - vi_port) == 1) + if (check_sub_overflow(chan->valid_ports, vi_port, &range)) { + dev_err(chan->vi->dev, "%s:Chan valid ports overflow\n", __func__); + return; + } + if (range == 1) chan->capture_descr_sequence += 1; } @@ -453,7 +468,12 @@ static void vi5_release_buffer(struct tegra_channel *chan, { struct vb2_v4l2_buffer *vbuf = &buf->buf; - vbuf->sequence = chan->sequence++; + if (check_add_overflow(chan->sequence, 1U, &chan->sequence)) { + dev_err(chan->vi->dev, "%s:chan sequence overflow\n", __func__); + return; + } + + vbuf->sequence = chan->sequence; vbuf->field = V4L2_FIELD_NONE; vb2_set_plane_payload(&vbuf->vb2_buf, 0, chan->format.sizeimage); @@ -611,6 +631,7 @@ static int vi5_channel_error_recover(struct tegra_channel *chan, { int err = 0; unsigned int vi_port = 0; + unsigned long flags = 0; struct tegra_channel_buffer *buf; struct tegra_mc_vi *vi = chan->vi; struct v4l2_subdev *csi_subdev; @@ -679,7 +700,9 @@ static int vi5_channel_error_recover(struct tegra_channel *chan, chan->capture_reqs_enqueued = 0; /* clear capture channel error state */ + spin_lock_irqsave(&chan->capture_state_lock, flags); chan->capture_state = CAPTURE_IDLE; + spin_unlock_irqrestore(&chan->capture_state_lock, flags); done: return err; @@ -739,10 +762,12 @@ static int tegra_channel_kthread_capture_dequeue(void *data) while (1) { try_to_freeze(); + spin_lock_irqsave(&chan->capture_state_lock, flags); wait_event_interruptible(chan->dequeue_wait, (kthread_should_stop() || !list_empty(&chan->dequeue) || (chan->capture_state == CAPTURE_ERROR))); + spin_unlock_irqrestore(&chan->capture_state_lock, flags); while (!(kthread_should_stop() || list_empty(&chan->dequeue) || (chan->capture_state == CAPTURE_ERROR))) {