From 2bb93e932969b1ba48abb1a079637fb34c8c63c2 Mon Sep 17 00:00:00 2001 From: Swami Reddy Reddy Date: Wed, 24 Jul 2024 18:53:36 +0530 Subject: [PATCH 1/9] msm: camera: sensor: TOCTOU error handling - Proper Handling in case of invalid pinctrl index - Removing dead code and unused variables - Change to dereference s_ctrl only after proper NULL Dereference Check. CRs-Fixed: 3875406 Change-Id: I8e2c717b22efff2a7d6503d38c048e30eff230da Signed-off-by: Swami Reddy Reddy (cherry picked from commit 79d77de659ef7ae0727af4165c5894804ab72d60) --- drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c | 13 ++++++++----- .../cam_sensor_module/cam_sensor/cam_sensor_core.c | 5 +++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 5165f6b2d1c9..146967f076a9 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -379,7 +380,7 @@ static int cam_res_mgr_shared_pinctrl_select_state( cam_res->pctrl_res[idx].pstatus = PINCTRL_STATUS_SUSPEND; } - return 0; + return rc; } static int cam_res_mgr_add_device(struct device *dev, @@ -577,11 +578,9 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) bool need_free = true; int dev_num = 0; struct cam_gpio_res *gpio_res = NULL; - bool is_shared_gpio = false; bool is_shared_pctrl_gpio = false; int pctrl_idx = -1; - is_shared_gpio = cam_res_mgr_gpio_is_in_shared_gpio(gpio); is_shared_pctrl_gpio = cam_res_mgr_gpio_is_in_shared_pctrl_gpio(gpio); @@ -634,8 +633,12 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) pctrl_idx = cam_res_mgr_util_get_idx_from_shared_pctrl_gpio( gpio); - cam_res_mgr_shared_pinctrl_select_state( - pctrl_idx, false); + if (pctrl_idx >= 0) { + cam_res_mgr_shared_pinctrl_select_state( + pctrl_idx, false); + } else { + CAM_ERR(CAM_RES, "invalid pinctrl idx: %d", pctrl_idx); + } } CAM_DBG(CAM_RES, "freeing gpio: %u", gpio); diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 999fec038324..a31023e4101c 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -719,13 +719,14 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, { int rc = 0, pkt_opcode = 0; struct cam_control *cmd = (struct cam_control *)arg; - struct cam_sensor_power_ctrl_t *power_info = - &s_ctrl->sensordata->power_info; + struct cam_sensor_power_ctrl_t *power_info = NULL; if (!s_ctrl || !arg) { CAM_ERR(CAM_SENSOR, "s_ctrl is NULL"); return -EINVAL; } + power_info = &s_ctrl->sensordata->power_info; + if (cmd->op_code != CAM_SENSOR_PROBE_CMD) { if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { CAM_ERR(CAM_SENSOR, "Invalid handle type: %d", From 08d0784e99c42d301d4aac169cf6e7140529ed3d Mon Sep 17 00:00:00 2001 From: jinguiw Date: Thu, 11 Jul 2024 18:03:15 +0530 Subject: [PATCH 2/9] msm: camera: ope: check cpu buffer offset and cmd buf idx No check for cpu buffer offset, which may lead to out of cpu buffer map. No check for cmd buffer index, which may lead to out of bound or negative index. Adding check for cpu buffer map offset and adding check for cmd buffer index. CRs-Fixed: 3864084 Change-Id: I39494b0a9f323cb5569d37a0c033b2eaf8fbd32c Signed-off-by: jinguiw --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 64ed8f360348..31cad8f760a8 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -2192,6 +2192,14 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr, hw_mgr->iommu_hdl); goto end; } + if ((len <= frame_process->cmd_buf[i][j].offset) || + (frame_process->cmd_buf[i][j].size < + frame_process->cmd_buf[i][j].length) || + ((len - frame_process->cmd_buf[i][j].offset) < + frame_process->cmd_buf[i][j].length)) { + CAM_ERR(CAM_OPE, "Invalid offset."); + return -EINVAL; + } cpu_addr = cpu_addr + frame_process->cmd_buf[i][j].offset; CAM_DBG(CAM_OPE, "Hdl %x size %d len %d off %d", @@ -2240,6 +2248,10 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr, uint32_t s_idx = 0; s_idx = cmd_buf->stripe_idx; + if (s_idx < 0 || s_idx >= OPE_MAX_STRIPES) { + CAM_ERR(CAM_OPE, "Invalid index."); + return -EINVAL; + } num_cmd_bufs = ope_request->num_stripe_cmd_bufs[i][s_idx]; From c74ff3c92db62a2f48db0ca1e7bf26ffdf364112 Mon Sep 17 00:00:00 2001 From: jinguiw Date: Tue, 2 Jul 2024 15:22:37 +0530 Subject: [PATCH 3/9] msm: camera: icp: io buf config num validation There are only limitations for CAM_BUF_IN and CAM_BUF_OUT in config validation, but there will be CAM_BUF_IN_OUT type also. In process io config, both CAM_BUF_OUT and CAM_BUF_IN_OUT types are in out_map_entries. No limitation for CAM_BUF_IN_OUT will lead to out of bound for out_map_entries. This change adds check for num of io config need in out_map_entries to avoid out of bound risk. CRs-Fixed: 3857308 Change-Id: I69163a4264d226d617cbe4f37ba1deb4e6434e31 Signed-off-by: jinguiw --- drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 56ebba91e6bf..3889b58679de 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4162,7 +4162,8 @@ static bool cam_icp_mgr_is_valid_outconfig(struct cam_packet *packet) packet->io_configs_offset/4); for (i = 0 ; i < packet->num_io_configs; i++) - if (io_cfg_ptr[i].direction == CAM_BUF_OUTPUT) + if ((io_cfg_ptr[i].direction == CAM_BUF_OUTPUT) || + (io_cfg_ptr[i].direction == CAM_BUF_IN_OUT)) num_out_map_entries++; if (num_out_map_entries <= CAM_MAX_OUT_RES) { @@ -4313,10 +4314,17 @@ static int cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr, if (io_cfg_ptr[i].direction == CAM_BUF_INPUT) { sync_in_obj[j++] = io_cfg_ptr[i].fence; prepare_args->num_in_map_entries++; - } else { + } else if ((io_cfg_ptr[i].direction == CAM_BUF_OUTPUT) || + (io_cfg_ptr[i].direction == CAM_BUF_IN_OUT)) { prepare_args->out_map_entries[k++].sync_id = io_cfg_ptr[i].fence; prepare_args->num_out_map_entries++; + } else { + CAM_ERR(CAM_ICP, "dir: %d, max_out:%u, out %u", + io_cfg_ptr[i].direction, + prepare_args->max_out_map_entries, + prepare_args->num_out_map_entries); + return -EINVAL; } CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u memh %x", From 4bc8ff3984e6accb136871b12b7017d0aa943812 Mon Sep 17 00:00:00 2001 From: jinguiw Date: Wed, 31 Jul 2024 15:01:07 +0530 Subject: [PATCH 4/9] msm: camera: sensor: handling condition for random read Get i2c setting count twice in different location for i2c setting, may lead to out of bound for reg settings. Record i2c setting count in the first fetch to avoid this risk. CRs-Fixed: 3885312 Change-Id: I2a81410fecdf41910d7d2eb0daf233621fe0b452 Signed-off-by: jinguiw --- .../cam_sensor_utils/cam_sensor_util.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index fd423ef3da0a..325e52e6a5a2 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -395,10 +395,11 @@ static int32_t cam_sensor_handle_random_read( struct cam_buf_io_cfg *io_cfg) { struct i2c_settings_list *i2c_list; - int32_t rc = 0, cnt = 0; + int32_t rc = 0, cnt = 0, payload_count = 0; + payload_count = cmd_i2c_random_rd->header.count; i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings, - cmd_i2c_random_rd->header.count); + payload_count); if ((i2c_list == NULL) || (i2c_list->i2c_settings.reg_setting == NULL)) { CAM_ERR(CAM_SENSOR, @@ -413,7 +414,7 @@ static int32_t cam_sensor_handle_random_read( } else { *cmd_length_in_bytes = sizeof(struct i2c_rdwr_header) + (sizeof(struct cam_cmd_read) * - (cmd_i2c_random_rd->header.count)); + payload_count); i2c_list->op_code = CAM_SENSOR_I2C_READ_RANDOM; i2c_list->i2c_settings.addr_type = cmd_i2c_random_rd->header.addr_type; @@ -422,8 +423,7 @@ static int32_t cam_sensor_handle_random_read( i2c_list->i2c_settings.size = cmd_i2c_random_rd->header.count; - for (cnt = 0; cnt < (cmd_i2c_random_rd->header.count); - cnt++) { + for (cnt = 0; cnt < payload_count; cnt++) { i2c_list->i2c_settings.reg_setting[cnt].reg_addr = cmd_i2c_random_rd->data_read[cnt].reg_data; } From ba6bfdd6ee634e5b53c23c094d0a0194b278aaee Mon Sep 17 00:00:00 2001 From: Nirmal Abraham Date: Wed, 26 Jun 2024 18:08:57 +0530 Subject: [PATCH 5/9] msm: camera: common: Add missing put_cpu_buf calls Add cam_mem_put_cpu_buf calls in error scenarios to avoid memory leak. CRs-Fixed: 3866880 Change-Id: I26ee4c58ab88458d109b13a04cfcaea3502b31a3 Signed-off-by: Nirmal Abraham --- drivers/cam_isp/cam_isp_context.c | 6 ++++-- .../cam_actuator/cam_actuator_core.c | 4 +++- .../cam_csiphy/cam_csiphy_core.c | 9 +++++++++ .../cam_sensor_module/cam_flash/cam_flash_core.c | 16 ++++++++++++---- drivers/cam_sensor_module/cam_ois/cam_ois_core.c | 5 +++-- .../cam_sensor/cam_sensor_core.c | 4 +++- .../cam_sensor_utils/cam_sensor_util.c | 2 +- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index da0a59be2353..b324b25e1a05 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4791,8 +4791,10 @@ static int __cam_isp_ctx_config_dev_in_top_state( if ((len < sizeof(struct cam_packet)) || ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) { CAM_ERR(CAM_ISP, "invalid buff length: %zu or offset", len); - rc = -EINVAL; - goto free_req; + spin_lock_bh(&ctx->lock); + list_add_tail(&req->list, &ctx->free_req_list); + spin_unlock_bh(&ctx->lock); + return -EINVAL; } remain_len -= (size_t)cmd->offset; diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 6d3c7a50207b..39241c3e0f4b 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -507,8 +507,10 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, /* Loop through multiple command buffers */ for (i = 0; i < csl_packet->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); - if (rc) + if (rc) { + cam_mem_put_cpu_buf(config.packet_handle); return rc; + } total_cmd_buf_in_bytes = cmd_desc[i].length; if (!total_cmd_buf_in_bytes) diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 59946e481246..2ec5799e7651 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -379,6 +379,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, CAM_ERR(CAM_CSIPHY, "Inval cam_packet strut size: %zu, len_of_buff: %zu", sizeof(struct cam_packet), len); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); rc = -EINVAL; return rc; } @@ -390,6 +391,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, if (cam_packet_util_validate_packet(csl_packet, remain_len)) { CAM_ERR(CAM_CSIPHY, "Invalid packet params"); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); rc = -EINVAL; return rc; } @@ -400,6 +402,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, csl_packet->cmd_buf_offset / 4); else { CAM_ERR(CAM_CSIPHY, "num_cmd_buffers = %d", csl_packet->num_cmd_buf); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); rc = -EINVAL; return rc; } @@ -407,6 +410,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, rc = cam_packet_util_validate_cmd_desc(cmd_desc); if (rc) { CAM_ERR(CAM_CSIPHY, "Invalid cmd desc ret: %d", rc); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); return rc; } @@ -415,6 +419,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, if (rc < 0) { CAM_ERR(CAM_CSIPHY, "Failed to get cmd buf Mem address : %d", rc); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); return rc; } @@ -422,6 +427,8 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, (cmd_desc->offset > (len - sizeof(struct cam_csiphy_info)))) { CAM_ERR(CAM_CSIPHY, "Not enough buffer provided for cam_cisphy_info"); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); + cam_mem_put_cpu_buf(cmd_desc->mem_handle); rc = -EINVAL; return rc; } @@ -433,6 +440,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, index = cam_csiphy_get_instance_offset(csiphy_dev, cfg_dev->dev_handle); if (index < 0 || index >= csiphy_dev->session_max_device_support) { CAM_ERR(CAM_CSIPHY, "index in invalid: %d", index); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); cam_mem_put_cpu_buf(cmd_desc->mem_handle); return -EINVAL; } @@ -443,6 +451,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, CAM_ERR(CAM_CSIPHY, "Wrong configuration lane_cnt: %u", cam_cmd_csiphy_info->lane_cnt); + cam_mem_put_cpu_buf((int32_t)cfg_dev->packet_handle); cam_mem_put_cpu_buf(cmd_desc->mem_handle); return rc; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 029ec542d491..cbe33b043a51 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1065,9 +1065,10 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) /* Loop through multiple command buffers */ for (i = 1; i < csl_packet->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); - if (rc) + if (rc) { + cam_mem_put_cpu_buf(config.packet_handle); return rc; - + } total_cmd_buf_in_bytes = cmd_desc[i].length; processed_cmd_buf_in_bytes = 0; if (!total_cmd_buf_in_bytes) @@ -1278,8 +1279,8 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) rc = fctrl->func_tbl.apply_setting(fctrl, 1); if (rc) { CAM_ERR(CAM_FLASH, "cannot apply fire settings rc = %d", rc); - return rc; } + cam_mem_put_cpu_buf(config.packet_handle); return rc; } break; @@ -1344,8 +1345,10 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) goto update_req_mgr; } case CAM_FLASH_PACKET_OPCODE_STREAM_OFF: { - if (fctrl->streamoff_count > 0) + if (fctrl->streamoff_count > 0) { + cam_mem_put_cpu_buf(config.packet_handle); return rc; + } CAM_DBG(CAM_FLASH, "Received Stream off Settings"); i2c_data = &(fctrl->i2c_data); @@ -1362,6 +1365,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) if (rc) { CAM_ERR(CAM_FLASH, "Failed in parsing i2c Stream off packets"); + cam_mem_put_cpu_buf(config.packet_handle); return rc; } break; @@ -1638,6 +1642,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr + cmd_desc->offset); if (!cmd_buf) { + cam_mem_put_cpu_buf(cmd_desc->mem_handle); + cam_mem_put_cpu_buf(config.packet_handle); rc = -EINVAL; return rc; } @@ -1654,6 +1660,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) CAM_WARN(CAM_FLASH, "Rxed Flash fire ops without linking"); flash_data->cmn_attr.is_settings_valid = false; + cam_mem_put_cpu_buf(cmd_desc->mem_handle); + cam_mem_put_cpu_buf(config.packet_handle); return -EINVAL; } if (remain_len < sizeof(struct cam_flash_set_on_off)) { diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index e62e00d88d27..45a63a9eb9cb 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -544,9 +544,10 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) /* Loop through multiple command buffers */ for (i = 0; i < csl_packet->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); - if (rc) + if (rc) { + cam_mem_put_cpu_buf(dev_config.packet_handle); return rc; - + } total_cmd_buf_in_bytes = cmd_desc[i].length; if (!total_cmd_buf_in_bytes) continue; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 999fec038324..a274928c94e3 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -556,8 +556,10 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl) for (i = 0; i < pkt->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); - if (rc) + if (rc) { + cam_mem_put_cpu_buf(handle); return rc; + } if (!(cmd_desc[i].length)) continue; diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 325e52e6a5a2..4e9fabc0d822 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -316,12 +316,12 @@ static int32_t cam_sensor_get_io_buffer( (uint8_t *)buf_addr + io_cfg->offsets[0]; i2c_settings->read_buff_len = buf_size - io_cfg->offsets[0]; + cam_mem_put_cpu_buf(io_cfg->mem_handle[0]); } else { CAM_ERR(CAM_SENSOR, "Invalid direction: %d", io_cfg->direction); rc = -EINVAL; } - cam_mem_put_cpu_buf(io_cfg->mem_handle[0]); return rc; } From 3b061e5b701448256a1748b73bc8c93cc39723d8 Mon Sep 17 00:00:00 2001 From: chengxue Date: Tue, 8 Oct 2024 15:38:01 +0800 Subject: [PATCH 6/9] msm: camera: ois: Copy packet header in kernel After getting the mapped buffer through cam_mem_get_cpu_buf() in kernel, userspace is still able to access those buffers. This change copy ois packet header in kernel to avoid TOCTOU issue. CRs-Fixed: 3885381 Change-Id: I185381f81a6a736a029b516dc7f99cce1cac7129 Signed-off-by: chengxue --- .../cam_sensor_module/cam_ois/cam_ois_core.c | 130 +++++++++--------- drivers/cam_utils/cam_common_util.c | 34 +++++ drivers/cam_utils/cam_common_util.h | 18 +++ 3 files changed, 115 insertions(+), 67 deletions(-) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 45a63a9eb9cb..d8766a225046 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -493,11 +493,13 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) size_t pkt_len; size_t remain_len = 0; struct cam_packet *csl_packet = NULL; + struct cam_packet *csl_packet_u = NULL; size_t len_of_buff = 0; uint32_t *offset = NULL, *cmd_buf; struct cam_ois_soc_private *soc_private = (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info; + size_t packet_size = 0; ioctl_ctrl = (struct cam_control *)arg; if (copy_from_user(&dev_config, @@ -519,22 +521,36 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "Inval cam_packet strut size: %zu, len_of_buff: %zu", sizeof(struct cam_packet), pkt_len); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + rc = -EINVAL; + goto put_ref; } remain_len -= (size_t)dev_config.offset; - csl_packet = (struct cam_packet *) + csl_packet_u = (struct cam_packet *) (generic_pkt_addr + (uint32_t)dev_config.offset); + packet_size = csl_packet_u->header.size; + if (packet_size <= remain_len) { + rc = cam_common_mem_kdup((void **)&csl_packet, + csl_packet_u, packet_size); + if (rc) { + CAM_ERR(CAM_OIS, "Alloc and copy request %lld packet fail", + csl_packet_u->header.request_id); + goto put_ref; + } + } else { + CAM_ERR(CAM_OIS, "Invalid packet header size %u", + packet_size); + rc = -EINVAL; + goto put_ref; + } if (cam_packet_util_validate_packet(csl_packet, remain_len)) { CAM_ERR(CAM_OIS, "Invalid packet params"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + rc = -EINVAL; + goto end; } - switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_OIS_PACKET_OPCODE_INIT: offset = (uint32_t *)&csl_packet->payload; @@ -545,9 +561,10 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) for (i = 0; i < csl_packet->num_cmd_buf; i++) { rc = cam_packet_util_validate_cmd_desc(&cmd_desc[i]); if (rc) { - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + CAM_ERR(CAM_OIS, "Invalid cmd desc"); + goto end; } + total_cmd_buf_in_bytes = cmd_desc[i].length; if (!total_cmd_buf_in_bytes) continue; @@ -557,15 +574,14 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Failed to get cpu buf : 0x%x", cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } cmd_buf = (uint32_t *)generic_ptr; if (!cmd_buf) { CAM_ERR(CAM_OIS, "invalid cmd buf"); + rc = -EINVAL; cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + goto end; } if ((len_of_buff < sizeof(struct common_header)) || @@ -573,9 +589,9 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) sizeof(struct common_header)))) { CAM_ERR(CAM_OIS, "Invalid length for sensor cmd"); + rc = -EINVAL; cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + goto end; } remain_len = len_of_buff - cmd_desc[i].offset; cmd_buf += cmd_desc[i].offset / sizeof(uint32_t); @@ -588,9 +604,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in parsing slave info"); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } break; case CAMERA_SENSOR_CMD_TYPE_PWR_UP: @@ -604,9 +618,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc) { CAM_ERR(CAM_OIS, "Failed: parse power settings"); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } break; default: @@ -624,9 +636,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "init parsing failed: %d", rc); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } } else if ((o_ctrl->is_ois_calib != 0) && (o_ctrl->i2c_calib_data.is_settings_valid == @@ -643,22 +653,22 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Calib parsing failed: %d", rc); - cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + break; } } break; } cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); + + if (rc < 0) + goto end; } if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) { rc = cam_ois_power_up(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, " OIS Power up failed"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } o_ctrl->cam_ois_state = CAM_OIS_CONFIG; } @@ -715,8 +725,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_WARN(CAM_OIS, "Not in right state to control OIS: %d", o_ctrl->cam_ois_state); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); @@ -729,23 +738,20 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply mode settings"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = delete_request(i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Fail deleting Mode data: rc: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } break; case CAM_OIS_PACKET_OPCODE_READ: { @@ -757,16 +763,14 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_WARN(CAM_OIS, "Not in right state to read OIS: %d", o_ctrl->cam_ois_state); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } CAM_DBG(CAM_OIS, "number of I/O configs: %d:", csl_packet->num_io_configs); if (csl_packet->num_io_configs == 0) { CAM_ERR(CAM_OIS, "No I/O configs to process"); rc = -EINVAL; - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } INIT_LIST_HEAD(&(i2c_read_settings.list_head)); @@ -779,8 +783,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (io_cfg == NULL) { CAM_ERR(CAM_OIS, "I/O config is invalid(NULL)"); rc = -EINVAL; - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } offset = (uint32_t *)&csl_packet->payload; @@ -793,8 +796,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_desc, 1, &io_cfg[0]); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS read pkt parsing failed: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_sensor_i2c_read_data( @@ -803,8 +805,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "cannot read data rc: %d", rc); delete_request(&i2c_read_settings); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } if (csl_packet->num_io_configs > 1) { @@ -814,8 +815,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "write qtimer failed rc: %d", rc); delete_request(&i2c_read_settings); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } } @@ -823,8 +823,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in deleting the read settings"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } break; } @@ -834,8 +833,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "Not in right state to write time to OIS: %d", o_ctrl->cam_ois_state); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); @@ -848,47 +846,45 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) cmd_desc, 1, NULL); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_ois_update_time(i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot update time"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply mode settings"); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } rc = delete_request(i2c_reg_settings); if (rc < 0) { CAM_ERR(CAM_OIS, "Fail deleting Mode data: rc: %d", rc); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; + goto end; } break; } default: CAM_ERR(CAM_OIS, "Invalid Opcode: %d", (csl_packet->header.op_code & 0xFFFFFF)); - cam_mem_put_cpu_buf(dev_config.packet_handle); - return -EINVAL; + rc = -EINVAL; + goto end; } - if (!rc) { - cam_mem_put_cpu_buf(dev_config.packet_handle); - return rc; - } + if (!rc) + goto end; + pwr_dwn: - cam_mem_put_cpu_buf(dev_config.packet_handle); cam_ois_power_down(o_ctrl); +end: + cam_common_mem_free(csl_packet); +put_ref: + cam_mem_put_cpu_buf(dev_config.packet_handle); return rc; } diff --git a/drivers/cam_utils/cam_common_util.c b/drivers/cam_utils/cam_common_util.c index 23681509f490..c221741bdeff 100644 --- a/drivers/cam_utils/cam_common_util.c +++ b/drivers/cam_utils/cam_common_util.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -72,3 +73,36 @@ void cam_common_util_thread_switch_delay_detect( } } + +int cam_common_mem_kdup(void **dst, + void *src, size_t size) +{ + gfp_t flag = GFP_KERNEL; + + if (!src || !dst || !size) { + CAM_ERR(CAM_UTIL, "Invalid params src: %pK dst: %pK size: %u", + src, dst, size); + return -EINVAL; + } + + if (!in_task()) + flag = GFP_ATOMIC; + + *dst = kzalloc(size, flag); + if (!*dst) { + CAM_ERR(CAM_UTIL, "Failed to allocate memory with size: %u", size); + return -ENOMEM; + } + + memcpy(*dst, src, size); + CAM_DBG(CAM_UTIL, "Allocate and copy memory with size: %u", size); + + return 0; +} +EXPORT_SYMBOL(cam_common_mem_kdup); + +void cam_common_mem_free(void *memory) +{ + kfree(memory); +} +EXPORT_SYMBOL(cam_common_mem_free); diff --git a/drivers/cam_utils/cam_common_util.h b/drivers/cam_utils/cam_common_util.h index 867aa5753f5a..8ef0c52f90d8 100644 --- a/drivers/cam_utils/cam_common_util.h +++ b/drivers/cam_utils/cam_common_util.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_COMMON_UTIL_H_ @@ -85,4 +86,21 @@ uint32_t cam_common_util_remove_duplicate_arr(int32_t *array, void cam_common_util_thread_switch_delay_detect(const char *token, ktime_t scheduled_time, uint32_t threshold); +/** + * @brief: Memory alloc and copy + * + * @dst: Address of destination address of memory + * @src: Source address of memory + * @size: Length of memory + * + * @return 0 if success in register non-zero if failes + */ +int cam_common_mem_kdup(void **dst, void *src, size_t size); + +/** + * @brief: Free the memory + * + * @memory: Address of memory + */ +void cam_common_mem_free(void *memory); #endif /* _CAM_COMMON_UTIL_H_ */ From bca82b35630747e34cbf2a8f830d5ce6216f176c Mon Sep 17 00:00:00 2001 From: Vivek Yadav Date: Tue, 12 Aug 2025 10:58:23 +0530 Subject: [PATCH 7/9] msm: camera: isp: Fix potential illegal access in Acquire HW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix potential illegal acquire_hw memory access due to following scenario. Even though ioctl is synchronous, the kernel performs 1. copy_from_user(&api_version, ...) — reads just the version. 2. Allocates buffer based on version. 3. copy_from_user(acquire_ptr, ...) — reads the full structure. If another thread modifies the user-space buffer (cmd->handle) between steps 1 and 3, the kernel will * Allocate a buffer for version 1. * But read data formatted for version 1, by modifying api version v2. * Call the isp_ctx: acquire_hw_in_acquired. * Now even though the allocated strructure version is v1, in acquire_hw_in_acquired call to api of version v2 would get invoked. * Leading to OOB reads/writes. CRs-Fixed: 4216838 Change-Id: I88d1c76438b56d6ccfa014aa440a536ac5bdd27a Signed-off-by: Vivek Yadav (cherry picked from commit 55273537c3c23152bba518402a96a86918e3f56c) --- drivers/cam_core/cam_node.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index d27bcdd6bf0d..4561aecb6f7e 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -812,6 +812,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) } case CAM_ACQUIRE_HW: { uint32_t api_version; + uint32_t struct_version; void *acquire_ptr = NULL; size_t acquire_size; @@ -846,6 +847,16 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) } if (api_version == 1) { + struct_version = + ((struct cam_acquire_hw_cmd_v1 *)acquire_ptr)->struct_version; + if (struct_version != api_version) { + CAM_ERR(CAM_CORE, + "Unmatched struct api version %u and struct version %u", + api_version, struct_version); + rc = -EINVAL; + goto acquire_free; + } + rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr); if (rc) { CAM_ERR(CAM_CORE, @@ -853,6 +864,16 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) goto acquire_kfree; } } else if (api_version == 2) { + struct_version = + ((struct cam_acquire_hw_cmd_v2 *)acquire_ptr)->struct_version; + if (struct_version != api_version) { + CAM_ERR(CAM_CORE, + "Unmatched struct api version %u and struct version %u", + api_version, struct_version); + rc = -EINVAL; + goto acquire_free; + } + rc = __cam_node_handle_acquire_hw_v2(node, acquire_ptr); if (rc) { CAM_ERR(CAM_CORE, From 7e0e21453804d632bf99d20266e5eadbfd1a9a5b Mon Sep 17 00:00:00 2001 From: Ajith Rajana Date: Fri, 5 Sep 2025 23:01:11 +0530 Subject: [PATCH 8/9] msm: camera: isp: Fix potential illegal access in Acquire HW. Fix for above Change-Id: I524598236aec47f3e80ef0325326ee75a809b197 Signed-off-by: Ajith Rajana --- drivers/cam_core/cam_node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 4561aecb6f7e..f9fa98fe6c5c 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -854,7 +854,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) "Unmatched struct api version %u and struct version %u", api_version, struct_version); rc = -EINVAL; - goto acquire_free; + goto acquire_kfree; } rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr); @@ -871,7 +871,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd) "Unmatched struct api version %u and struct version %u", api_version, struct_version); rc = -EINVAL; - goto acquire_free; + goto acquire_kfree; } rc = __cam_node_handle_acquire_hw_v2(node, acquire_ptr); From 542be35e0e4883f60bd4839364eb6c142e96858b Mon Sep 17 00:00:00 2001 From: Parag Singhal Date: Wed, 17 Jun 2026 10:57:44 +0530 Subject: [PATCH 9/9] msm: camera: common: Fix OOB access in bandwidth path handling Invalid input from user can lead to an index going below the valid range after offset calculation. Existing validation only checked the upper bound, allowing negative values to pass and cause out-of-bounds memory access. Add complete bounds validation to ensure safe access. CRs-Fixed: 4544133 Change-Id: Ib37b25ab84e9004eaeb216302857d65df18a2516 Signed-off-by: Parag Singhal (cherry picked from commit d6cee3f552be8126f0c8b29ea833228bf3357fa8) --- drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index 31cad8f760a8..d4137ef50e5f 100644 --- a/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2022, The Linux Foundation. All rights reserved. - * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -783,7 +783,7 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) .path_data_type - CAM_AXI_PATH_DATA_OPE_START_OFFSET; - if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + if (path_index < 0 || path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { CAM_WARN(CAM_OPE, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i] @@ -1466,7 +1466,7 @@ static bool cam_ope_update_bw_v2(struct cam_ope_hw_mgr *hw_mgr, ctx_data->clk_info.axi_path[i].path_data_type - CAM_AXI_PATH_DATA_OPE_START_OFFSET; - if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + if (path_index < 0 || path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { CAM_WARN(CAM_OPE, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i].path_data_type, @@ -1503,7 +1503,7 @@ static bool cam_ope_update_bw_v2(struct cam_ope_hw_mgr *hw_mgr, ctx_data->clk_info.axi_path[i].path_data_type - CAM_AXI_PATH_DATA_OPE_START_OFFSET; - if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + if (path_index < 0 || path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { CAM_WARN(CAM_OPE, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i].path_data_type, @@ -2899,7 +2899,7 @@ static int cam_ope_mgr_remove_bw(struct cam_ope_hw_mgr *hw_mgr, int ctx_id) ctx_data->clk_info.axi_path[i].path_data_type - CAM_AXI_PATH_DATA_OPE_START_OFFSET; - if (path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { + if (path_index < 0 || path_index >= CAM_OPE_MAX_PER_PATH_VOTES) { CAM_WARN(CAM_OPE, "Invalid path %d, start offset=%d, max=%d", ctx_data->clk_info.axi_path[i].path_data_type,