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:
parent
3ecdc35c98
commit
5fe2c8d7e8
@ -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 +
|
||||
|
Loading…
Reference in New Issue
Block a user