mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-06 03:45:24 -04:00
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 <quic_chengxue@quicinc.com>
This commit is contained in:
parent
ba6bfdd6ee
commit
3b061e5b70
3 changed files with 115 additions and 67 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <linux/string.h>
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue