Merge "msm: camera: jpeg: Avoid UAF in jpeg driver" into camera-kernel.lnx.7.0

This commit is contained in:
cheese Service 2024-07-26 02:36:08 -07:00 committed by Gerrit - the friendly Code Review server
commit 179c50c49e
2 changed files with 32 additions and 34 deletions

View File

@ -106,10 +106,6 @@ static int cam_jpeg_add_command_buffers(struct cam_packet *packet,
struct cam_cmd_buf_desc *cmd_desc = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL;
struct cam_jpeg_request_data *jpeg_request_data; struct cam_jpeg_request_data *jpeg_request_data;
struct cam_kmd_buf_info kmd_buf; struct cam_kmd_buf_info kmd_buf;
struct cam_jpeg_config_inout_param_info *inout_params;
uint32_t *cmd_buf_kaddr;
uintptr_t kaddr;
size_t len;
unsigned int num_entry = 0; unsigned int num_entry = 0;
unsigned int i; unsigned int i;
int rc; int rc;
@ -157,9 +153,10 @@ static int cam_jpeg_add_command_buffers(struct cam_packet *packet,
num_entry++; num_entry++;
jpeg_request_data->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type; jpeg_request_data->dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
jpeg_request_data->encode_size_buffer_ptr = NULL;
jpeg_request_data->request_id = packet->header.request_id; jpeg_request_data->request_id = packet->header.request_id;
jpeg_request_data->thumbnail_threshold_size = 0; jpeg_request_data->thumbnail_threshold_size = 0;
jpeg_request_data->out_size_mem_handle = 0;
jpeg_request_data->out_size_offset = 0;
CAM_DBG(CAM_JPEG, CAM_DBG(CAM_JPEG,
"Change_Base HW_Entry. Offset: 0x%x Length: %u mem_handle: 0x%x num_entry: %d", "Change_Base HW_Entry. Offset: 0x%x Length: %u mem_handle: 0x%x num_entry: %d",
@ -193,29 +190,8 @@ static int cam_jpeg_add_command_buffers(struct cam_packet *packet,
num_entry++; num_entry++;
break; break;
case CAM_JPEG_PACKET_INOUT_PARAM: case CAM_JPEG_PACKET_INOUT_PARAM:
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle, jpeg_request_data->out_size_mem_handle = cmd_desc[i].mem_handle;
(uintptr_t *)&kaddr, &len); jpeg_request_data->out_size_offset = cmd_desc[i].offset;
if (rc) {
CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d");
return rc;
}
cmd_buf_kaddr = (uint32_t *)kaddr;
if (cmd_desc[i].offset >= len) {
CAM_ERR(CAM_JPEG, "Invalid offset: %u cmd buf len: %zu",
cmd_desc[i].offset, len);
cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
return -EINVAL;
}
cmd_buf_kaddr += (cmd_desc[i].offset / sizeof(uint32_t));
inout_params = (struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr;
jpeg_request_data->encode_size_buffer_ptr = &inout_params->output_size;
CAM_DBG(CAM_JPEG, "encode_size_buf_ptr: 0x%p",
jpeg_request_data->encode_size_buffer_ptr);
cam_mem_put_cpu_buf(cmd_desc[i].mem_handle);
break; break;
case CAM_JPEG_PACKET_GENERIC_BLOB: case CAM_JPEG_PACKET_GENERIC_BLOB:
rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[i], rc = cam_packet_util_process_generic_cmd_buffer(&cmd_desc[i],
@ -391,6 +367,11 @@ static int cam_jpeg_mgr_bottom_half_irq(void *priv, void *data)
struct cam_ctx_request *req; struct cam_ctx_request *req;
struct cam_jpeg_misr_dump_args misr_args; struct cam_jpeg_misr_dump_args misr_args;
struct cam_jpeg_hw_buf_done_evt_data jpeg_done_evt; struct cam_jpeg_hw_buf_done_evt_data jpeg_done_evt;
struct cam_jpeg_config_inout_param_info *inout_params;
uint32_t *cmd_buf_kaddr;
uintptr_t kaddr;
size_t len;
size_t inout_param_size;
if (!data || !priv) { if (!data || !priv) {
CAM_ERR(CAM_JPEG, "Invalid data"); CAM_ERR(CAM_JPEG, "Invalid data");
@ -467,10 +448,26 @@ static int cam_jpeg_mgr_bottom_half_irq(void *priv, void *data)
} }
jpeg_req = irq_cb_data->jpeg_req; jpeg_req = irq_cb_data->jpeg_req;
inout_param_size = sizeof(struct cam_jpeg_config_inout_param_info);
if (jpeg_req->dev_type == CAM_JPEG_RES_TYPE_ENC) { if (jpeg_req->dev_type == CAM_JPEG_RES_TYPE_ENC) {
if (jpeg_req->encode_size_buffer_ptr) rc = cam_mem_get_cpu_buf(jpeg_req->out_size_mem_handle,
*jpeg_req->encode_size_buffer_ptr = task_data->u.output_encode_size; (uintptr_t *)&kaddr, &len);
if (!rc) {
if ((inout_param_size > len) ||
(jpeg_req->out_size_offset >= (len - inout_param_size)))
CAM_ERR(CAM_JPEG,
"Inval off = %u cmd buf len = %zu inout_param_size = %d",
jpeg_req->out_size_offset, len, inout_param_size);
else {
cmd_buf_kaddr = (uint32_t *)kaddr;
cmd_buf_kaddr += (jpeg_req->out_size_offset / sizeof(uint32_t));
inout_params =
(struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr;
inout_params->output_size = task_data->u.output_encode_size;
}
cam_mem_put_cpu_buf(jpeg_req->out_size_mem_handle);
}
else else
CAM_ERR(CAM_JPEG, "Buffer pointer for inout param is null"); CAM_ERR(CAM_JPEG, "Buffer pointer for inout param is null");

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#ifndef CAM_JPEG_HW_MGR_INTF_H #ifndef CAM_JPEG_HW_MGR_INTF_H
@ -23,15 +23,16 @@ enum cam_jpeg_hw_type {
* struct cam_jpeg_request_data - Jpeg request data received from command buffers * struct cam_jpeg_request_data - Jpeg request data received from command buffers
* @dev_type : Jpeg device type(ENC vs DMA) * @dev_type : Jpeg device type(ENC vs DMA)
* @request_id : Request ID * @request_id : Request ID
* @encode_size_buffer_ptr : Pointer to the buffer location for storing the encode
size of the result
* @thumbnail_threshold_size : Threshold size for thumbnail image * @thumbnail_threshold_size : Threshold size for thumbnail image
* @out_size_mem_handle : handle to the buffer to share encoded output size with userspace
* @out_size_offset : offset to memory where out_size_mem_handle is stored
*/ */
struct cam_jpeg_request_data { struct cam_jpeg_request_data {
uint32_t dev_type; uint32_t dev_type;
uint64_t request_id; uint64_t request_id;
uint32_t *encode_size_buffer_ptr;
uint32_t thumbnail_threshold_size; uint32_t thumbnail_threshold_size;
__s32 out_size_mem_handle;
uint32_t out_size_offset;
}; };
typedef void (*cam_jpeg_mini_dump_cb)(void *priv, void *dst); typedef void (*cam_jpeg_mini_dump_cb)(void *priv, void *dst);