From 3aa403fa33333b9ecfce43f76d6b5f6779c8f3c9 Mon Sep 17 00:00:00 2001 From: Bob Zhang Date: Thu, 2 Jan 2025 01:47:27 +0000 Subject: [PATCH] kernel: nvidia-oot: Fix Linux KMD coverity defects Fix INT30-C and INT08-C coverity defects for capture-vi.c and tegracam_ctrls.c. Fix MISSING_LOCK coverity defects for channel.c. JIRA CAMERASW-30788 Change-Id: I6ad218cb9184f09d04d862a4c8f3f6db35db65cf Signed-off-by: Bob Zhang Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3275901 Reviewed-by: svcacv Reviewed-by: Xiaoming Xiang Reviewed-by: Anubhav Rai Reviewed-by: Sumeet Gupta GVS: buildbot_gerritrpt Reviewed-by: Ankur Pawar --- .../tegra/camera/fusa-capture/capture-vi.c | 36 +++++++++++++++--- .../platform/tegra/camera/tegracam_ctrls.c | 38 ++++++++++++++++--- .../media/platform/tegra/camera/vi/channel.c | 13 +++++++ 3 files changed, 76 insertions(+), 11 deletions(-) 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 46e9a64c..dcedd8b6 100644 --- a/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c +++ b/drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c @@ -1,5 +1,6 @@ // 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-vi.c @@ -1400,14 +1401,24 @@ static uint32_t vi_capture_get_num_progress( struct vi_capture_req *req) { struct vi_capture *capture = chan->capture_data; - struct capture_descriptor* desc = (struct capture_descriptor*) - (capture->requests.va + - req->buffer_index * capture->request_size); - struct vi_channel_config* config = &desc->ch_cfg; const uint16_t minProgress = 2U; uint16_t numProgress = minProgress; + struct capture_descriptor *desc; + struct vi_channel_config *config; + + unsigned int mul_value = 0; + + if (check_mul_overflow(req->buffer_index, capture->request_size, &mul_value)) { + dev_err(chan->dev, + "%s:capture descriptor offset failed due to an overflow\n", __func__); + return minProgress; + } + + desc = (struct capture_descriptor *)(capture->requests.va + mul_value); + config = &desc->ch_cfg; + /* Minimum of two progress fences for PXL_SOF and PXL_EOF */ if (config->flush_enable == 0x1UL) { @@ -1433,7 +1444,14 @@ static uint32_t vi_capture_get_num_progress( */ if (((config->frame.frame_y - config->flush_first) % config->flush) == 0U) { - numProgress--; + if (numProgress < minProgress) { + dev_err(chan->dev, + "%s:numProgress is less than the minimum value\n", + __func__); + numProgress = minProgress; + } else { + numProgress--; + } } } return (uint32_t)numProgress; @@ -1446,6 +1464,7 @@ int vi_capture_request( struct vi_capture *capture = chan->capture_data; struct CAPTURE_MSG capture_desc; int err = 0; + uint32_t sum_value = 0; nv_camera_log(chan->ndev, __arch_counter_get_cntvct(), @@ -1495,7 +1514,12 @@ int vi_capture_request( } // Progress syncpoints + 1 for status syncpoint - capture->progress_sp.threshold += vi_capture_get_num_progress(chan, req) + 1; + if (check_add_overflow(vi_capture_get_num_progress(chan, req), 1U, &sum_value)) { + dev_err(chan->dev, "%s: check_sub failed due to an overflow\n", __func__); + } else if (check_add_overflow(capture->progress_sp.threshold, sum_value, + &capture->progress_sp.threshold)) { + dev_err(chan->dev, "%s: procress_sp failed due to an overflow\n", __func__); + } mutex_unlock(&capture->reset_lock); diff --git a/drivers/media/platform/tegra/camera/tegracam_ctrls.c b/drivers/media/platform/tegra/camera/tegracam_ctrls.c index 6ae08bc5..1ef42e71 100644 --- a/drivers/media/platform/tegra/camera/tegracam_ctrls.c +++ b/drivers/media/platform/tegra/camera/tegracam_ctrls.c @@ -1,8 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 -/* +// SPDX-License-Identifier: GPL-2.0-only +/* SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + * * tegracam_ctrls - control framework for tegra camera drivers * - * Copyright (c) 2017-2024, NVIDIA CORPORATION. All rights reserved. */ #include @@ -899,8 +900,35 @@ static int tegracam_check_ctrl_ops( "ERROR: Can not mix normal and extended sensor controls\n"); return -EINVAL; } - total_ops = sensor_ops + mode_ops + string_ops + default_ops + compound_ops; - total_ops += sensor_ex_ops + default_ex_ops; + + if (check_add_overflow(total_ops, sensor_ops, &total_ops)) { + dev_err(dev, "%s:sensor ops failed due to an overflow\n", __func__); + return -EINVAL; + } + if (check_add_overflow(total_ops, mode_ops, &total_ops)) { + dev_err(dev, "%s:mode ops failed due to an overflow\n", __func__); + return -EINVAL; + } + if (check_add_overflow(total_ops, string_ops, &total_ops)) { + dev_err(dev, "%s:string ops failed due to an overflow\n", __func__); + return -EINVAL; + } + if (check_add_overflow(total_ops, default_ops, &total_ops)) { + dev_err(dev, "%s:default ops failed due to an overflow\n", __func__); + return -EINVAL; + } + if (check_add_overflow(total_ops, compound_ops, &total_ops)) { + dev_err(dev, "%s:compound ops failed due to an overflow\n", __func__); + return -EINVAL; + } + if (check_add_overflow(total_ops, sensor_ex_ops, &total_ops)) { + dev_err(dev, "%s:sensor ex ops failed due to an overflow\n", __func__); + return -EINVAL; + } + if (check_add_overflow(total_ops, default_ex_ops, &total_ops)) { + dev_err(dev, "%s:default ex ops failed due to an overflow\n", __func__); + return -EINVAL; + } if (total_ops != (ops->numctrls + TEGRACAM_DEF_CTRLS)) { dev_err(dev, diff --git a/drivers/media/platform/tegra/camera/vi/channel.c b/drivers/media/platform/tegra/camera/vi/channel.c index c27d389e..45f97d91 100644 --- a/drivers/media/platform/tegra/camera/vi/channel.c +++ b/drivers/media/platform/tegra/camera/vi/channel.c @@ -411,6 +411,7 @@ void release_buffer(struct tegra_channel *chan, { struct vb2_v4l2_buffer *vbuf = &buf->buf; s64 frame_arrived_ts = 0; + unsigned long flags; /* release one frame */ vbuf->sequence = chan->sequence; @@ -423,6 +424,7 @@ void release_buffer(struct tegra_channel *chan, vb2_set_plane_payload(&vbuf->vb2_buf, 0, chan->format.sizeimage); + spin_lock_irqsave(&chan->capture_state_lock, flags); /* * WAR to force buffer state if capture state is not good * WAR - After sync point timeout or error frame capture @@ -431,6 +433,7 @@ void release_buffer(struct tegra_channel *chan, */ if (chan->capture_state != CAPTURE_GOOD || vbuf->sequence < 2) buf->state = VB2_BUF_STATE_ERROR; + spin_unlock_irqrestore(&chan->capture_state_lock, flags); if (chan->sequence == 1) { /* @@ -507,6 +510,7 @@ void free_ring_buffers(struct tegra_channel *chan, int frames) { struct vb2_v4l2_buffer *vbuf; s64 frame_arrived_ts = 0; + unsigned long flags; spin_lock(&chan->buffer_lock); @@ -529,6 +533,7 @@ void free_ring_buffers(struct tegra_channel *chan, int frames) vb2_set_plane_payload(&vbuf->vb2_buf, 0, chan->format.sizeimage); + spin_lock_irqsave(&chan->capture_state_lock, flags); /* * WAR to force buffer state if capture state is not good * WAR - After sync point timeout or error frame capture @@ -540,6 +545,7 @@ void free_ring_buffers(struct tegra_channel *chan, int frames) chan->released_bufs < 2) chan->buffer_state[chan->free_index] = VB2_BUF_STATE_ERROR; + spin_unlock_irqrestore(&chan->capture_state_lock, flags); if (chan->sequence == 1) { /* @@ -587,6 +593,7 @@ static void add_buffer_to_ring(struct tegra_channel *chan, static void update_state_to_buffer(struct tegra_channel *chan, int state) { int save_index = ((int)chan->save_index - PREVIOUS_BUFFER_DEC_INDEX); + unsigned long flags; /* save index decrements by 2 as 3 bufs are added in ring buffer */ if (save_index < 0) @@ -594,29 +601,35 @@ static void update_state_to_buffer(struct tegra_channel *chan, int state) /* update state for the previous buffer */ chan->buffer_state[save_index] = state; + spin_lock_irqsave(&chan->capture_state_lock, flags); /* for timeout/error case update the current buffer state as well */ if (chan->capture_state != CAPTURE_GOOD) chan->buffer_state[chan->save_index] = state; + spin_unlock_irqrestore(&chan->capture_state_lock, flags); } void tegra_channel_ring_buffer(struct tegra_channel *chan, struct vb2_v4l2_buffer *vb, struct timespec64 *ts, int state) { + unsigned long flags; if (!chan->bfirst_fstart) chan->bfirst_fstart = true; else update_state_to_buffer(chan, state); + spin_lock_irqsave(&chan->capture_state_lock, flags); /* Capture state is not GOOD, release all buffers and re-init state */ if (chan->capture_state != CAPTURE_GOOD) { free_ring_buffers(chan, chan->num_buffers); tegra_channel_init_ring_buffer(chan); + spin_unlock_irqrestore(&chan->capture_state_lock, flags); return; } else { /* TODO: granular time code information */ vb->timecode.seconds = ts->tv_sec; } + spin_unlock_irqrestore(&chan->capture_state_lock, flags); /* release buffer N at N+2 frame start event */ if (chan->num_buffers >= (chan->capture_queue_depth - 1))