msm: camera: core: Out of Bound write in cam_context_user_dump
addr variable to have address bound check, due to that increamenting of that variable can go corrupt other memory address which could lead to our of bound access. This change will add extra address change before access addr variable. CRs-Fixed: 3802568 Change-Id: I0a2804403dc92fa005f8dda5263242eeb01f4765 Signed-off-by: Soumen Ghosh <quic_soumeng@quicinc.com>
This commit is contained in:
parent
8bdffe141e
commit
6ddbe8dd37
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CONTEXT_H_
|
||||
@ -276,6 +276,38 @@ struct cam_context {
|
||||
struct timespec64 cdm_done_ts;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_context_stream_dump - camera context stream information
|
||||
*
|
||||
* @hw_mgr_ctx_id: Hw Mgr context id returned from hw mgr
|
||||
* @dev_id: ID of device associated
|
||||
* @dev_hdl: Device handle
|
||||
* @link_hdl: Link handle
|
||||
* @sessoin_hdl: Session handle
|
||||
* @refcount: Context object refcount
|
||||
* @last_flush_req: Last request to flush
|
||||
* @state: Current state for top level state machine
|
||||
*/
|
||||
struct cam_context_stream_dump {
|
||||
uint32_t hw_mgr_ctx_id;
|
||||
uint32_t dev_id;
|
||||
uint32_t dev_hdl;
|
||||
uint32_t link_hdl;
|
||||
uint32_t session_hdl;
|
||||
uint32_t refcount;
|
||||
uint32_t last_flush_req;
|
||||
enum cam_context_state state;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_context_each_req_info - camera each request information
|
||||
*
|
||||
* @request_id: request id
|
||||
*/
|
||||
struct cam_context_each_req_info {
|
||||
uint64_t request_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_context_dump_header - Function for context dump header
|
||||
*
|
||||
|
@ -1487,6 +1487,40 @@ end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_context_dump_data_validaion(void *src, void *dest,
|
||||
uint32_t base_len, uint32_t actual_len, uint32_t bytes_required)
|
||||
{
|
||||
if (base_len + bytes_required >= actual_len) {
|
||||
CAM_ERR(CAM_CTXT, "actual len %pK base len %pK",
|
||||
actual_len, base_len);
|
||||
return -ENOSPC;
|
||||
}
|
||||
memcpy(dest, src, bytes_required);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_context_stream_dump_validation(struct cam_context *ctx,
|
||||
uint64_t *addr, uint32_t local_len, uint32_t buf_len)
|
||||
{
|
||||
struct cam_context_stream_dump stream_dump;
|
||||
|
||||
stream_dump.hw_mgr_ctx_id = ctx->hw_mgr_ctx_id;
|
||||
stream_dump.dev_id = ctx->dev_id;
|
||||
stream_dump.dev_hdl = ctx->dev_hdl;
|
||||
stream_dump.link_hdl = ctx->link_hdl;
|
||||
stream_dump.session_hdl = ctx->session_hdl;
|
||||
stream_dump.refcount = refcount_read(&(ctx->refcount.refcount));
|
||||
stream_dump.last_flush_req = ctx->last_flush_req;
|
||||
stream_dump.state = ctx->state;
|
||||
if (cam_context_dump_data_validaion(&stream_dump, addr,
|
||||
local_len, buf_len,
|
||||
sizeof(struct cam_context_stream_dump))) {
|
||||
CAM_WARN(CAM_CTXT, "failed to copy the stream info");
|
||||
return -ENOSPC;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_context_user_dump(struct cam_context *ctx,
|
||||
struct cam_hw_dump_args *dump_args)
|
||||
{
|
||||
@ -1498,6 +1532,7 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
uint32_t min_len;
|
||||
size_t buf_len, remain_len;
|
||||
uintptr_t cpu_addr;
|
||||
uint32_t local_len;
|
||||
|
||||
if (!ctx || !dump_args) {
|
||||
CAM_ERR(CAM_CORE, "Invalid parameters %pK %pK",
|
||||
@ -1555,73 +1590,19 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
/* Dump context info */
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
local_len =
|
||||
(dump_args->offset + sizeof(struct cam_context_dump_header));
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_CTX_INFO:", ctx->dev_name);
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
*addr++ = ctx->hw_mgr_ctx_id;
|
||||
*addr++ = ctx->dev_id;
|
||||
*addr++ = ctx->dev_hdl;
|
||||
*addr++ = ctx->link_hdl;
|
||||
*addr++ = ctx->session_hdl;
|
||||
*addr++ = refcount_read(&(ctx->refcount.refcount));
|
||||
*addr++ = ctx->last_flush_req;
|
||||
*addr++ = ctx->state;
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
|
||||
/* Dump pending request IDs */
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_OUT_FENCE_PENDING_REQUESTS:", ctx->dev_name);
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
if (!list_empty(&ctx->pending_req_list)) {
|
||||
list_for_each_entry_safe(req, req_temp, &ctx->pending_req_list, list) {
|
||||
*addr++ = req->request_id;
|
||||
}
|
||||
if (cam_context_stream_dump_validation(ctx, addr, local_len, buf_len)) {
|
||||
CAM_WARN(CAM_CTXT, "%s_CTX_INFO failed to copy the stream info ", ctx->dev_name);
|
||||
cam_mem_put_cpu_buf(dump_args->buf_handle);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
|
||||
/* Dump wait request IDs */
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_OUT_FENCE_APPLIED_REQUESTS:", ctx->dev_name);
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
if (!list_empty(&ctx->wait_req_list)) {
|
||||
list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) {
|
||||
*addr++ = req->request_id;
|
||||
}
|
||||
}
|
||||
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
|
||||
/* Dump active request IDs */
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_OUT_FENCE_ACTIVE_REQUESTS:", ctx->dev_name);
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
if (!list_empty(&ctx->active_req_list)) {
|
||||
list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
|
||||
*addr++ = req->request_id;
|
||||
}
|
||||
}
|
||||
|
||||
addr = addr + sizeof(struct cam_context_stream_dump);
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
@ -1632,6 +1613,8 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
for (i = 0; i < req->num_out_map_entries; i++) {
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
local_len = dump_args->offset +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_OUT_FENCE_REQUEST_APPLIED.%d.%d.%d:",
|
||||
ctx->dev_name,
|
||||
@ -1641,7 +1624,14 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
*addr++ = req->request_id;
|
||||
if (cam_context_dump_data_validaion(&req->request_id, addr,
|
||||
local_len, buf_len,
|
||||
sizeof(struct cam_context_each_req_info))) {
|
||||
CAM_WARN(CAM_CTXT, "%s_CTX_INFO waiting_req: failed to copy the request info",
|
||||
ctx->dev_name);
|
||||
goto cleanup;
|
||||
}
|
||||
addr = addr + sizeof(struct cam_context_each_req_info);
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
@ -1655,6 +1645,8 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
for (i = 0; i < req->num_out_map_entries; i++) {
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
local_len = dump_args->offset +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_OUT_FENCE_REQUEST_PENDING.%d.%d.%d:",
|
||||
ctx->dev_name,
|
||||
@ -1664,7 +1656,14 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
*addr++ = req->request_id;
|
||||
if (cam_context_dump_data_validaion(&req->request_id, addr,
|
||||
local_len, buf_len,
|
||||
sizeof(struct cam_context_each_req_info))) {
|
||||
CAM_WARN(CAM_CTXT, "%s_CTX_INFO pending_req: failed to copy the request info",
|
||||
ctx->dev_name);
|
||||
goto cleanup;
|
||||
}
|
||||
addr = addr + sizeof(struct cam_context_each_req_info);
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
@ -1678,6 +1677,8 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
for (i = 0; i < req->num_out_map_entries; i++) {
|
||||
dst = (uint8_t *)cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_context_dump_header *)dst;
|
||||
local_len = dump_args->offset +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
scnprintf(hdr->tag, CAM_CTXT_DUMP_TAG_MAX_LEN,
|
||||
"%s_OUT_FENCE_REQUEST_ACTIVE.%d.%d.%d:",
|
||||
ctx->dev_name,
|
||||
@ -1687,14 +1688,21 @@ static int cam_context_user_dump(struct cam_context *ctx,
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
|
||||
start = addr;
|
||||
*addr++ = req->request_id;
|
||||
if (cam_context_dump_data_validaion(&req->request_id, addr,
|
||||
local_len, buf_len,
|
||||
sizeof(struct cam_context_each_req_info))) {
|
||||
CAM_WARN(CAM_CTXT, "%s_CTX_INFO active_req: failed to copy the request info",
|
||||
ctx->dev_name);
|
||||
goto cleanup;
|
||||
}
|
||||
addr = addr + sizeof(struct cam_context_each_req_info);
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_context_dump_header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cam_mem_put_cpu_buf(dump_args->buf_handle);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user