msm: camera: core: Add buffer length check to prevent overflow

Previously, context user dumps lacked sufficient checks, risking
buffer overflows. Added length checks for dump headers to ensure
enough buffer space before copying header and exact data from
all kinds of request lists.

CRs-Fixed: 3846871
Change-Id: I02d01af54c9985e5642c31b979c0590494fd5775
Signed-off-by: Atiya Kailany <quic_akailany@quicinc.com>
Signed-off-by: Haochen Yang <quic_haocyang@quicinc.com>
This commit is contained in:
Atiya Kailany 2024-06-26 13:04:12 -07:00 committed by Sridhar Gujje
parent 3ecdc35c98
commit 5fe2c8d7e8

View File

@ -1529,7 +1529,6 @@ static int cam_context_user_dump(struct cam_context *ctx,
struct cam_context_dump_header *hdr;
uint8_t *dst;
uint64_t *addr, *start;
uint32_t min_len;
size_t buf_len, remain_len;
uintptr_t cpu_addr;
uint32_t local_len;
@ -1556,38 +1555,16 @@ static int cam_context_user_dump(struct cam_context *ctx,
return -ENOSPC;
}
spin_lock_bh(&ctx->lock);
if (!list_empty(&ctx->active_req_list)) {
req = list_first_entry(&ctx->active_req_list,
struct cam_ctx_request, list);
} else if (!list_empty(&ctx->wait_req_list)) {
req = list_first_entry(&ctx->wait_req_list,
struct cam_ctx_request, list);
} else if (!list_empty(&ctx->pending_req_list)) {
req = list_first_entry(&ctx->pending_req_list,
struct cam_ctx_request, list);
} else {
CAM_ERR(CAM_CTXT, "[%s][%d] no request to dump",
ctx->dev_name, ctx->ctx_id);
}
spin_unlock_bh(&ctx->lock);
/* Check for min len in case of available request to dump */
if (req != NULL) {
remain_len = buf_len - dump_args->offset;
min_len = sizeof(struct cam_context_dump_header) +
(CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries +
(req->num_out_map_entries * 2)) * sizeof(uint64_t);
if (remain_len < min_len) {
CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u",
remain_len, min_len);
cam_mem_put_cpu_buf(dump_args->buf_handle);
return -ENOSPC;
}
}
/* Dump context info */
remain_len = buf_len - dump_args->offset;
if (remain_len < sizeof(struct cam_context_dump_header)) {
CAM_WARN(CAM_CTXT,
"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
remain_len, sizeof(struct cam_context_dump_header));
cam_mem_put_cpu_buf(dump_args->buf_handle);
return -ENOSPC;
}
dst = (uint8_t *)cpu_addr + dump_args->offset;
hdr = (struct cam_context_dump_header *)dst;
local_len =
@ -1611,6 +1588,15 @@ static int cam_context_user_dump(struct cam_context *ctx,
if (!list_empty(&ctx->wait_req_list)) {
list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) {
for (i = 0; i < req->num_out_map_entries; i++) {
remain_len = buf_len - dump_args->offset;
if (remain_len < sizeof(struct cam_context_dump_header)) {
CAM_WARN(CAM_CTXT,
"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
remain_len, sizeof(struct cam_context_dump_header));
cam_mem_put_cpu_buf(dump_args->buf_handle);
return -ENOSPC;
}
dst = (uint8_t *)cpu_addr + dump_args->offset;
hdr = (struct cam_context_dump_header *)dst;
local_len = dump_args->offset +
@ -1643,6 +1629,15 @@ static int cam_context_user_dump(struct cam_context *ctx,
if (!list_empty(&ctx->pending_req_list)) {
list_for_each_entry_safe(req, req_temp, &ctx->pending_req_list, list) {
for (i = 0; i < req->num_out_map_entries; i++) {
remain_len = buf_len - dump_args->offset;
if (remain_len < sizeof(struct cam_context_dump_header)) {
CAM_WARN(CAM_CTXT,
"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
remain_len, sizeof(struct cam_context_dump_header));
cam_mem_put_cpu_buf(dump_args->buf_handle);
return -ENOSPC;
}
dst = (uint8_t *)cpu_addr + dump_args->offset;
hdr = (struct cam_context_dump_header *)dst;
local_len = dump_args->offset +
@ -1675,6 +1670,15 @@ static int cam_context_user_dump(struct cam_context *ctx,
if (!list_empty(&ctx->active_req_list)) {
list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
for (i = 0; i < req->num_out_map_entries; i++) {
remain_len = buf_len - dump_args->offset;
if (remain_len < sizeof(struct cam_context_dump_header)) {
CAM_WARN(CAM_CTXT,
"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
remain_len, sizeof(struct cam_context_dump_header));
cam_mem_put_cpu_buf(dump_args->buf_handle);
return -ENOSPC;
}
dst = (uint8_t *)cpu_addr + dump_args->offset;
hdr = (struct cam_context_dump_header *)dst;
local_len = dump_args->offset +