diff --git a/drivers/media/platform/tegra/cam_fsync/cam_fsync.c b/drivers/media/platform/tegra/cam_fsync/cam_fsync.c index c0473ab1..ae757716 100644 --- a/drivers/media/platform/tegra/cam_fsync/cam_fsync.c +++ b/drivers/media/platform/tegra/cam_fsync/cam_fsync.c @@ -516,7 +516,8 @@ static int compute_edge_regs(struct edge_reg_info *info, u64 ticks, bool loop) while ((ticks > 0U) && (info->count < MAX_EDGE_REGS)) { u32 const current_ticks = (u32)min(ticks, (u64)EDGE_OFFSET_MASK); - info->regs[info->count++] = current_ticks; + info->regs[info->count] = current_ticks; + info->count++; ticks -= current_ticks; } @@ -528,6 +529,9 @@ static int compute_edge_regs(struct edge_reg_info *info, u64 ticks, bool loop) if (ticks > 0U) return -EFAULT; + if (info->count > MAX_EDGE_REGS || info->count < 1U) { + return -EFAULT; + } /** Update the flags for last edge register */ info->regs[info->count-1] |= flags; return 0; @@ -537,19 +541,26 @@ static int cam_fsync_program_group_generator_edges(struct fsync_generator_group { struct cam_fsync_generator *generator; u32 max_freq_hz_lcm = cam_fsync_find_max_freq_hz_lcm(group); - u64 const ticks_per_hz = DIV_ROUND_CLOSEST(NS_PER_SEC, group->features->ns_per_tick); + u32 const ticks_per_hz = DIV_ROUND_CLOSEST(NS_PER_SEC, group->features->ns_per_tick); bool const can_generate_precise_freq = cam_fsync_can_generate_precise_freq(group); struct cam_fsync_extra_ticks_and_period extra = {0, 1}; list_for_each_entry(generator, &group->generators, list) { - u64 ref_ticks_in_period = DIV_ROUND_CLOSEST_ULL(ticks_per_hz, max_freq_hz_lcm); - u64 ticks_in_period = ref_ticks_in_period * - (max_freq_hz_lcm / generator->config.freq_hz); + u32 ref_ticks_in_period = DIV_ROUND_CLOSEST(ticks_per_hz, max_freq_hz_lcm); + u64 ticks_in_period = (u64)ref_ticks_in_period * + (u64)(max_freq_hz_lcm / generator->config.freq_hz); u64 ticks_active = mult_frac(ticks_in_period, generator->config.duty_cycle, 100); - u64 ticks_inactive = ticks_in_period - ticks_active; + u64 ticks_inactive = 0; struct edge_reg_info edge_info = {0}; u32 i; + if (check_sub_overflow(ticks_in_period, ticks_active, &ticks_inactive)) { + dev_err(group->dev, + "%s: calculate the ticks_inactive due to an underflow\n", + __func__); + return -EINVAL; + } + /** * Generating a freq with period that is not multiple of TSC unit will * cause the signal to drift over time. To avoid this, if precise signal @@ -564,15 +575,22 @@ static int cam_fsync_program_group_generator_edges(struct fsync_generator_group for (i = 0; i < extra.num_periods; i++) { int ret; u64 extra_ticks = (extra.extra_ticks > 0) ? 1 : 0; + u64 tmp_ticks = 0; + + if (check_add_overflow(ticks_inactive, extra_ticks, &tmp_ticks)) { + dev_err(group->dev, + "%s: calculate the ticks due to an underflow\n", + __func__); + return -EINVAL; + } extra.extra_ticks -= (extra_ticks > 0); ret = compute_edge_regs(&edge_info, ticks_active, false); if (ret < 0) return ret; - ret = compute_edge_regs(&edge_info, - ticks_inactive + extra_ticks, - (i == extra.num_periods - 1)); + ret = compute_edge_regs(&edge_info, tmp_ticks, + (i == extra.num_periods - 1)); if (ret < 0) return ret; } @@ -640,7 +658,13 @@ static u64 cam_fsync_get_default_start_ticks(struct cam_fsync_controller *contro u64 default_start_ticks = mult_frac( TSC_GENX_START_OFFSET_MS, NS_PER_MS, controller->features->ns_per_tick); - default_start_ticks += cam_fsync_get_current_tsc_ticks(); + u64 current_ticks = cam_fsync_get_current_tsc_ticks(); + + if (check_add_overflow(default_start_ticks, current_ticks, &default_start_ticks)) { + dev_err(controller->dev, + "%s: calculate the default start ticks due to an overflow\n", __func__); + return 0; + } return default_start_ticks; } diff --git a/drivers/media/platform/tegra/cdi/cam_cdi_tsc.c b/drivers/media/platform/tegra/cdi/cam_cdi_tsc.c index bffe8f5a..52c3767a 100644 --- a/drivers/media/platform/tegra/cdi/cam_cdi_tsc.c +++ b/drivers/media/platform/tegra/cdi/cam_cdi_tsc.c @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* SPDX-FileCopyrightText: Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */ +// SPDX-License-Identifier: GPL-2.0 +/* SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION. All rights reserved. */ /* * cam_cdi_tsc.c - tsc driver. */ @@ -317,7 +317,14 @@ static int cdi_tsc_program_generator_edges(struct tsc_signal_controller *control if (controller->features->rational_locking.enforced) { ticks_in_period = DIV_ROUND_CLOSEST(ticks_per_hz, max_freq_hz_lcm); - ticks_in_period *= max_freq_hz_lcm / generator->config.freq_hz; + if (check_mul_overflow(ticks_in_period, + (max_freq_hz_lcm / generator->config.freq_hz), + &ticks_in_period)) { + dev_err(controller->dev, + "%s: calculate the ticks_in_period due to an overflow\n", + __func__); + return -EINVAL; + } } else { ticks_in_period = DIV_ROUND_CLOSEST(ticks_per_hz, generator->config.freq_hz); } diff --git a/drivers/media/platform/tegra/cdi/cdi_dev.c b/drivers/media/platform/tegra/cdi/cdi_dev.c index 3cb59efb..bf00a1ac 100644 --- a/drivers/media/platform/tegra/cdi/cdi_dev.c +++ b/drivers/media/platform/tegra/cdi/cdi_dev.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2015-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-FileCopyrightText: Copyright (c) 2015-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include @@ -254,7 +254,12 @@ int cdi_dev_raw_wr( cdi_dev_dump(__func__, info, offset, val, size); num_msgs = size / MAX_MSG_SIZE; - num_msgs += (size % MAX_MSG_SIZE) ? 1 : 0; + if (check_add_overflow(num_msgs, + (unsigned int)((size % MAX_MSG_SIZE) ? 1 : 0), &num_msgs)) { + dev_err(info->dev, "%s: calculate the num_msgs due to an overflow\n", + __func__); + return -ENOMEM; + } i2cmsg = kzalloc((sizeof(struct i2c_msg)*num_msgs), GFP_KERNEL); if (!i2cmsg) {