Skip to content

Commit 0b4e1bf

Browse files
KevalSanghviQtimichael-jihan-qcom
authored andcommitted
msm: camera: ope: Avoid UAF in ope driver
There is a possibility that UMD can remove the ref_cnt on the kmd_buf and debug_buf used in ope driver which can result in UAF. To avoid this, hold the ref_cnt on that buffer till ope processing is complete for that request. CRs-Fixed: 4257555 Change-Id: Iff8a59f84c5169015b6b815631ea2a5f546bb26d Signed-off-by: Keval Sanghvi <ksanghvi@qti.qualcomm.com> Signed-off-by: Ignatius Michael Jihan <mignatiu@qti.qualcomm.com>
1 parent 8b1dfea commit 0b4e1bf

4 files changed

Lines changed: 79 additions & 5 deletions

File tree

camera/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,26 @@ static void cam_ope_free_io_config(struct cam_ope_request *req)
193193
}
194194
}
195195

196+
static void cam_ope_free_cpu_buf(struct cam_ope_request *req)
197+
{
198+
if (!req)
199+
return;
200+
201+
// Only release KMD buffer if it was acquired and not already released
202+
if (req->ope_kmd_buf.cpu_addr && req->ope_kmd_buf.mem_handle) {
203+
cam_mem_put_cpu_buf(req->ope_kmd_buf.mem_handle);
204+
req->ope_kmd_buf.cpu_addr = 0;
205+
req->ope_kmd_buf.mem_handle = 0;
206+
}
207+
208+
// Only release debug buffer if it was acquired and not already released
209+
if (req->ope_debug_buf.cpu_addr && req->ope_debug_buf.mem_handle) {
210+
cam_mem_put_cpu_buf(req->ope_debug_buf.mem_handle);
211+
req->ope_debug_buf.cpu_addr = 0;
212+
req->ope_debug_buf.mem_handle = 0;
213+
}
214+
}
215+
196216
static void cam_ope_device_timer_stop(struct cam_ope_hw_mgr *hw_mgr)
197217
{
198218
if (hw_mgr->clk_info.watch_dog) {
@@ -1740,6 +1760,8 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
17401760
if (ctx->ctx_state != OPE_CTX_STATE_ACQUIRED) {
17411761
CAM_ERR(CAM_OPE, "ctx %u is in %d state",
17421762
ctx->ctx_id, ctx->ctx_state);
1763+
if (ope_req)
1764+
cam_ope_free_cpu_buf(ope_req);
17431765
mutex_unlock(&ctx->ctx_mutex);
17441766
return;
17451767
}
@@ -1796,6 +1818,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
17961818
ctx->req_cnt--;
17971819

17981820
buf_data.request_id = ope_req->request_id;
1821+
cam_ope_free_cpu_buf(ope_req);
17991822
ope_req->request_id = 0;
18001823
cam_free_clear((void *)ctx->req_list[req_id]->cdm_cmd);
18011824
ctx->req_list[req_id]->cdm_cmd = NULL;
@@ -2319,6 +2342,8 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr,
23192342
ope_request->ope_kmd_buf.iova_cdm_addr);
23202343
} else if (cmd_buf->cmd_buf_usage ==
23212344
OPE_CMD_BUF_DEBUG) {
2345+
ope_request->ope_debug_buf.mem_handle =
2346+
cmd_buf->mem_handle;
23222347
ope_request->ope_debug_buf.cpu_addr =
23232348
cpu_addr;
23242349
ope_request->ope_debug_buf.iova_addr =
@@ -2332,7 +2357,9 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr,
23322357
CAM_DBG(CAM_OPE, "dbg buf = %x",
23332358
ope_request->ope_debug_buf.cpu_addr);
23342359
}
2335-
cam_mem_put_cpu_buf(cmd_buf->mem_handle);
2360+
if ((cmd_buf->cmd_buf_usage != OPE_CMD_BUF_KMD) &&
2361+
(cmd_buf->cmd_buf_usage != OPE_CMD_BUF_DEBUG))
2362+
cam_mem_put_cpu_buf(cmd_buf->mem_handle);
23362363
break;
23372364
}
23382365
case OPE_CMD_BUF_SCOPE_STRIPE: {
@@ -2443,6 +2470,7 @@ static int cam_ope_mgr_process_cmd_desc(struct cam_ope_hw_mgr *hw_mgr,
24432470
if (rc) {
24442471
CAM_ERR(CAM_OPE, "Process OPE cmd io request is failed: %d",
24452472
rc);
2473+
cam_ope_free_cpu_buf(ope_request);
24462474
goto free_buf;
24472475
}
24482476

@@ -3485,6 +3513,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv,
34853513
return rc;
34863514

34873515
free_buf:
3516+
cam_ope_free_cpu_buf(ope_req);
34883517
cam_common_mem_free(ope_cmd_buf_addr);
34893518
end:
34903519
cam_ope_mgr_put_cmd_buf(packet);
@@ -3514,6 +3543,7 @@ static int cam_ope_mgr_handle_config_err(
35143543
ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_ERROR,
35153544
&buf_data);
35163545

3546+
cam_ope_free_cpu_buf(ope_req);
35173547
req_idx = ope_req->req_idx;
35183548
ope_req->request_id = 0;
35193549
cam_free_clear((void *)ctx_data->req_list[req_idx]->cdm_cmd);
@@ -3693,6 +3723,7 @@ static int cam_ope_mgr_flush_req(struct cam_ope_ctx *ctx_data,
36933723
{
36943724
int idx;
36953725
int64_t request_id;
3726+
struct cam_ope_request *ope_req;
36963727

36973728
request_id = *(int64_t *)flush_args->flush_req_pending[0];
36983729
for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) {
@@ -3701,7 +3732,8 @@ static int cam_ope_mgr_flush_req(struct cam_ope_ctx *ctx_data,
37013732

37023733
if (ctx_data->req_list[idx]->request_id != request_id)
37033734
continue;
3704-
3735+
ope_req = ctx_data->req_list[idx];
3736+
cam_ope_free_cpu_buf(ope_req);
37053737
ctx_data->req_list[idx]->request_id = 0;
37063738
cam_free_clear((void *)ctx_data->req_list[idx]->cdm_cmd);
37073739
ctx_data->req_list[idx]->cdm_cmd = NULL;
@@ -3719,6 +3751,7 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data,
37193751
{
37203752
int i, rc;
37213753
struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr;
3754+
struct cam_ope_request *ope_req;
37223755

37233756
rc = cam_cdm_flush_hw(ctx_data->ope_cdm.cdm_handle);
37243757

@@ -3734,7 +3767,8 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data,
37343767
for (i = 0; i < CAM_CTX_REQ_MAX; i++) {
37353768
if (!ctx_data->req_list[i])
37363769
continue;
3737-
3770+
ope_req = ctx_data->req_list[i];
3771+
cam_ope_free_cpu_buf(ope_req);
37383772
ctx_data->req_list[i]->request_id = 0;
37393773
cam_free_clear((void *)ctx_data->req_list[i]->cdm_cmd);
37403774
ctx_data->req_list[i]->cdm_cmd = NULL;

camera/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22
/*
33
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
4-
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
4+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
55
*/
66

77
#ifndef CAM_OPE_HW_MGR_H
@@ -221,13 +221,15 @@ struct cdm_dmi_cmd {
221221
/**
222222
* struct ope_debug_buffer
223223
*
224+
* @mem_handle: Memory handle
224225
* @cpu_addr: CPU address
225226
* @iova_addr: IOVA address
226227
* @len: Buffer length
227228
* @size: Buffer Size
228229
* @offset: buffer offset
229230
*/
230231
struct ope_debug_buffer {
232+
uint32_t mem_handle;
231233
uintptr_t cpu_addr;
232234
dma_addr_t iova_addr;
233235
size_t len;

camera_kt/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,26 @@ static void cam_ope_free_io_config(struct cam_ope_request *req)
194194
}
195195
}
196196

197+
static void cam_ope_free_cpu_buf(struct cam_ope_request *req)
198+
{
199+
if (!req)
200+
return;
201+
202+
// Only release KMD buffer if it was acquired and not already released
203+
if (req->ope_kmd_buf.cpu_addr && req->ope_kmd_buf.mem_handle) {
204+
cam_mem_put_cpu_buf(req->ope_kmd_buf.mem_handle);
205+
req->ope_kmd_buf.cpu_addr = 0;
206+
req->ope_kmd_buf.mem_handle = 0;
207+
}
208+
209+
// Only release debug buffer if it was acquired and not already released
210+
if (req->ope_debug_buf.cpu_addr && req->ope_debug_buf.mem_handle) {
211+
cam_mem_put_cpu_buf(req->ope_debug_buf.mem_handle);
212+
req->ope_debug_buf.cpu_addr = 0;
213+
req->ope_debug_buf.mem_handle = 0;
214+
}
215+
}
216+
197217
static void cam_ope_device_timer_stop(struct cam_ope_hw_mgr *hw_mgr)
198218
{
199219
if (hw_mgr->clk_info.watch_dog) {
@@ -1736,6 +1756,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
17361756
if (ctx->ctx_state != OPE_CTX_STATE_ACQUIRED) {
17371757
CAM_ERR(CAM_OPE, "ctx %u is in %d state",
17381758
ctx->ctx_id, ctx->ctx_state);
1759+
cam_ope_free_cpu_buf(ope_req);
17391760
mutex_unlock(&ctx->ctx_mutex);
17401761
return;
17411762
}
@@ -1792,6 +1813,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
17921813
ctx->req_cnt--;
17931814

17941815
buf_data.request_id = ope_req->request_id;
1816+
cam_ope_free_cpu_buf(ope_req);
17951817
ope_req->request_id = 0;
17961818
cam_free_clear((void *)ctx->req_list[cookie]->cdm_cmd);
17971819
ctx->req_list[cookie]->cdm_cmd = NULL;
@@ -2300,6 +2322,8 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr,
23002322
break;
23012323
} else if (cmd_buf->cmd_buf_usage ==
23022324
OPE_CMD_BUF_DEBUG) {
2325+
ope_request->ope_debug_buf.mem_handle =
2326+
cmd_buf->mem_handle;
23032327
ope_request->ope_debug_buf.cpu_addr =
23042328
cpu_addr;
23052329
ope_request->ope_debug_buf.iova_addr =
@@ -2315,7 +2339,9 @@ static int cam_ope_mgr_process_cmd_buf_req(struct cam_ope_hw_mgr *hw_mgr,
23152339
cam_mem_put_cpu_buf(cmd_buf->mem_handle);
23162340
break;
23172341
}
2318-
cam_mem_put_cpu_buf(cmd_buf->mem_handle);
2342+
if ((cmd_buf->cmd_buf_usage != OPE_CMD_BUF_KMD) &&
2343+
(cmd_buf->cmd_buf_usage != OPE_CMD_BUF_DEBUG))
2344+
cam_mem_put_cpu_buf(cmd_buf->mem_handle);
23192345
break;
23202346
}
23212347
case OPE_CMD_BUF_SCOPE_STRIPE: {
@@ -2429,6 +2455,7 @@ static int cam_ope_mgr_process_cmd_desc(struct cam_ope_hw_mgr *hw_mgr,
24292455
if (rc) {
24302456
CAM_ERR(CAM_OPE, "Process OPE cmd io request is failed: %d",
24312457
rc);
2458+
cam_ope_free_cpu_buf(ope_request);
24322459
goto free_buf;
24332460
}
24342461

@@ -3446,6 +3473,7 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv,
34463473
return rc;
34473474

34483475
free_buf:
3476+
cam_ope_free_cpu_buf(ope_req);
34493477
cam_common_mem_free(ope_cmd_buf_addr);
34503478
end:
34513479
cam_free_clear((void *)ctx_data->req_list[request_idx]->cdm_cmd);
@@ -3475,6 +3503,7 @@ static int cam_ope_mgr_handle_config_err(
34753503
ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_ERROR,
34763504
&buf_data);
34773505

3506+
cam_ope_free_cpu_buf(ope_req);
34783507
req_idx = ope_req->req_idx;
34793508
ope_req->request_id = 0;
34803509
cam_free_clear((void *)ctx_data->req_list[req_idx]->cdm_cmd);
@@ -3655,6 +3684,7 @@ static int cam_ope_mgr_flush_req(struct cam_ope_ctx *ctx_data,
36553684
{
36563685
int idx;
36573686
int64_t request_id;
3687+
struct cam_ope_request *ope_req;
36583688

36593689
request_id = *(int64_t *)flush_args->flush_req_pending[0];
36603690
for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) {
@@ -3664,6 +3694,8 @@ static int cam_ope_mgr_flush_req(struct cam_ope_ctx *ctx_data,
36643694
if (ctx_data->req_list[idx]->request_id != request_id)
36653695
continue;
36663696

3697+
ope_req = ctx_data->req_list[idx];
3698+
cam_ope_free_cpu_buf(ope_req);
36673699
ctx_data->req_list[idx]->request_id = 0;
36683700
cam_free_clear((void *)ctx_data->req_list[idx]->cdm_cmd);
36693701
ctx_data->req_list[idx]->cdm_cmd = NULL;
@@ -3681,6 +3713,7 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data,
36813713
{
36823714
int i, rc;
36833715
struct cam_ope_hw_mgr *hw_mgr = ope_hw_mgr;
3716+
struct cam_ope_request *ope_req;
36843717

36853718
rc = cam_cdm_flush_hw(ctx_data->ope_cdm.cdm_handle);
36863719

@@ -3697,6 +3730,8 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data,
36973730
if (!ctx_data->req_list[i])
36983731
continue;
36993732

3733+
ope_req = ctx_data->req_list[i];
3734+
cam_ope_free_cpu_buf(ope_req);
37003735
ctx_data->req_list[i]->request_id = 0;
37013736
cam_free_clear((void *)ctx_data->req_list[i]->cdm_cmd);
37023737
ctx_data->req_list[i]->cdm_cmd = NULL;

camera_kt/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22
/*
33
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
4+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
45
*/
56

67
#ifndef CAM_OPE_HW_MGR_H
@@ -220,13 +221,15 @@ struct cdm_dmi_cmd {
220221
/**
221222
* struct ope_debug_buffer
222223
*
224+
* @mem_handle: Memory handle
223225
* @cpu_addr: CPU address
224226
* @iova_addr: IOVA address
225227
* @len: Buffer length
226228
* @size: Buffer Size
227229
* @offset: buffer offset
228230
*/
229231
struct ope_debug_buffer {
232+
uint32_t mem_handle;
230233
uintptr_t cpu_addr;
231234
dma_addr_t iova_addr;
232235
size_t len;

0 commit comments

Comments
 (0)