diff --git a/drivers/media/platform/tegra/camera/camera_common.c b/drivers/media/platform/tegra/camera/camera_common.c index c0111bee..4c22e28e 100644 --- a/drivers/media/platform/tegra/camera/camera_common.c +++ b/drivers/media/platform/tegra/camera/camera_common.c @@ -1,6 +1,6 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES. + * SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -524,6 +524,10 @@ static const struct camera_common_colorfmt *find_matching_color_fmt( if (cur_props->pixel_format == camera_common_color_fmts[i].pix_fmt && !matched[i]) { + if (match_num == INT_MAX) { + dev_err(s_data->dev, "Number of matched color format exceeds the limit\n"); + return NULL; + } match_num++; match_index = i; // Found index @@ -624,9 +628,14 @@ int camera_common_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) hdr_control.id = TEGRA_CAMERA_CID_HDR_EN; /* mode_type can be filled in sensor driver */ - if (!(v4l2_g_ctrl(s_data->ctrl_handler, &hdr_control))) - mode_type |= - switch_ctrl_qmenu[hdr_control.value] ? HDR_ENABLE : 0; + if (!(v4l2_g_ctrl(s_data->ctrl_handler, &hdr_control))) { + if ((hdr_control.value < 0) || (hdr_control.value >= ARRAY_SIZE(switch_ctrl_qmenu))) { + dev_err(sd->dev, "Number of tried camera common format exceeds the limit\n"); + return -EINVAL; + } + mode_type |= switch_ctrl_qmenu[hdr_control.value] ? HDR_ENABLE : 0; + } + s_data->mode = s_data->def_mode; s_data->mode_prop_idx = 0; @@ -898,7 +907,15 @@ void camera_common_dpd_disable(struct camera_common_data *s_data) int i; int io_idx; /* 2 lanes per port, divide by two to get numports */ - int numports = (s_data->numlanes + 1) >> 1; + int result_add1 = 0; + int numports = 0; + + if (__builtin_add_overflow(1, s_data->numlanes, &result_add1)) { + dev_err(s_data->dev, "Number of data lanes exceeds the limit\n"); + spec_bar(); + return; + } + numports = result_add1 >> 1; /* disable CSI IOs DPD mode to turn on camera */ for (i = 0; i < numports; i++) { @@ -934,7 +951,15 @@ void camera_common_dpd_enable(struct camera_common_data *s_data) int i; int io_idx; /* 2 lanes per port, divide by two to get numports */ - int numports = (s_data->numlanes + 1) >> 1; + int result_add1 = 0; + int numports = 0; + + if (__builtin_add_overflow(1, s_data->numlanes, &result_add1)) { + dev_err(s_data->dev, "Number of data lanes exceeds the limit\n"); + spec_bar(); + return; + } + numports = result_add1 >> 1; /* disable CSI IOs DPD mode to turn on camera */ for (i = 0; i < numports; i++) { diff --git a/drivers/media/platform/tegra/camera/csi/csi.c b/drivers/media/platform/tegra/camera/csi/csi.c index 7e3dfb3a..f9686d3a 100644 --- a/drivers/media/platform/tegra/camera/csi/csi.c +++ b/drivers/media/platform/tegra/camera/csi/csi.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -// SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. /* * NVIDIA Tegra CSI Device */ @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -276,10 +277,17 @@ static int update_video_source(struct tegra_csi_device *csi, int on, int is_tpg) { mutex_lock(&csi->source_update); if (!on) { - if (is_tpg) - csi->tpg_active--; - else - csi->sensor_active--; + if (is_tpg) { + if (csi->tpg_active > INT_MIN) + csi->tpg_active--; + else + goto stream_fail; + } else { + if (csi->sensor_active > INT_MIN) + csi->sensor_active--; + else + goto stream_fail; + } WARN_ON(csi->tpg_active < 0 || csi->sensor_active < 0); goto stream_okay; } @@ -291,6 +299,7 @@ static int update_video_source(struct tegra_csi_device *csi, int on, int is_tpg) csi->sensor_active++; goto stream_okay; } +stream_fail: mutex_unlock(&csi->source_update); dev_err(csi->dev, "Request rejected for new %s stream\n", is_tpg ? "tpg" : "sensor"); @@ -420,10 +429,45 @@ unsigned int tegra_csi_ths_settling_time( const unsigned int csicil_clk_mhz, const unsigned int mipi_clk_mhz) { - unsigned int cil_settletime; + unsigned int cil_settletime = 0; + + /* The calculation formula is as follows: + * (115 * csicil_clk_mhz + 8000 * csicil_clk_mhz / (2 * mipi_clk_mhz) - 5500) / 1000 + */ + unsigned int result_mul1 = 0; + unsigned int result_mul2 = 0; + unsigned int result_mul3 = 0; + unsigned int result_add1 = 0; + unsigned int result_sub1 = 0; + + if (__builtin_umul_overflow(115, csicil_clk_mhz, &result_mul1)) { + dev_err(csi->dev, "Number of calculated tegra csi ths settling time exceeds the limit\n"); + return cil_settletime; + } + + if (__builtin_umul_overflow(8000, csicil_clk_mhz, &result_mul2)) { + dev_err(csi->dev, "Number of calculated tegra csi ths settling time exceeds the limit\n"); + return cil_settletime; + } + + if (__builtin_umul_overflow(2, mipi_clk_mhz, &result_mul3) || (result_mul3 == 0)) { + dev_err(csi->dev, "Number of calculated tegra csi ths settling time exceeds the limit " \ + "or bad param of mipi clk mhz value is 0\n"); + return cil_settletime; + } + + if (__builtin_uadd_overflow(result_mul1, (result_mul2 / result_mul3), &result_add1)) { + dev_err(csi->dev, "Number of calculated tegra csi ths settling time exceeds the limit\n"); + return cil_settletime; + } + + if (__builtin_usub_overflow(result_add1, 5500, &result_sub1)) { + dev_err(csi->dev, "Number of calculated tegra csi ths settling time exceeds the limit\n"); + return cil_settletime; + } + + cil_settletime = result_sub1 / 1000; - cil_settletime = (115 * csicil_clk_mhz + 8000 * csicil_clk_mhz - / (2 * mipi_clk_mhz) - 5500) / 1000; return cil_settletime; } EXPORT_SYMBOL(tegra_csi_ths_settling_time); @@ -432,9 +476,24 @@ unsigned int tegra_csi_clk_settling_time( struct tegra_csi_device *csi, const unsigned int csicil_clk_mhz) { - unsigned int clk_settletime; + unsigned int clk_settletime = 0; - clk_settletime = ((95 + 300) * csicil_clk_mhz - 13000) / 2000; + /* The calculation formula is as follows: + * ((95 + 300) * csicil_clk_mhz - 13000) / 2000; + */ + unsigned int result_mul1 = 0; + unsigned int result_sub1 = 0; + + if (__builtin_umul_overflow((95 + 300), csicil_clk_mhz, &result_mul1)) { + dev_err(csi->dev, "Number of calculated tegra csi clk settling time exceeds the limit\n"); + return clk_settletime; + } + + if (__builtin_usub_overflow(result_mul1, 13000, &result_sub1)) { + dev_err(csi->dev, "Number of calculated tegra csi clk settling time exceeds the limit\n"); + return clk_settletime; + } + clk_settletime = result_sub1 / 2000; return clk_settletime; } EXPORT_SYMBOL(tegra_csi_clk_settling_time); @@ -903,8 +962,16 @@ static int tegra_csi_channel_init_one(struct tegra_csi_channel *chan) * pp means pixel parser, correspond to port[0] below. * tpg id correspond to chan->id */ - chan->port[0] = (chan->id - csi->num_channels) - % NUM_TPG_INSTANCE; + + int result_sub1 = 0; + + if (__builtin_sub_overflow(chan->id, csi->num_channels, &result_sub1)) { + dev_err(chan->csi->dev, "Number of calculated channel port exceeds the limit“\ + ”\n"); + return -ENOMEM; + } + + chan->port[0] = result_sub1 % NUM_TPG_INSTANCE; WARN_ON(chan->port[0] > csi->num_tpg_channels); chan->ports[0].stream_id = chan->port[0]; chan->ports[0].virtual_channel_id @@ -987,7 +1054,9 @@ static int csi_parse_dt(struct tegra_csi_device *csi, if (strncmp(node->name, "nvcsi", 5)) { node = of_find_node_by_name(node, "nvcsi"); - strncpy(csi->devname, "nvcsi", 6); + if (sizeof(csi->devname) >= sizeof("nvcsi")) { + strncpy(csi->devname, "nvcsi", 6); + } } if (node) { diff --git a/include/media/camera_common.h b/include/media/camera_common.h index 6b5ae91d..a7a1d267 100644 --- a/include/media/camera_common.h +++ b/include/media/camera_common.h @@ -1,8 +1,19 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2023, NVIDIA Corporation. All rights reserved. + * SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. * - * camera_common.h - utilities for tegra camera driver + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #ifndef __camera_common__ @@ -271,7 +282,16 @@ struct camera_common_focuser_data { static inline void msleep_range(unsigned int delay_base) { - usleep_range(delay_base * 1000, delay_base * 1000 + 500); + unsigned int time_start = 0; + unsigned int time_end = 0; + + if (__builtin_umul_overflow(delay_base, 1000, &time_start)) + return; + + if (__builtin_uadd_overflow(time_start, 500, &time_end)) + return; + + usleep_range(time_start, time_end); } static inline struct camera_common_data *to_camera_common_data(