video: driver: fix use-after-free issues with __read_queue() api
Incase of synchronous cmd(HFI_CMD_INIT, HFI_CMD_STOP, HFI_CMD_CLOSE) timeout cases, video driver will attempt to do core_deinit sequence and will free all interface queues mappings as part of core_deinit. If at same time ISR handler is fired then reverse thread will attempt to dequeue packets from message and debug queue. Reverse thread will not acquire core->lock for performance reasone. Dequeueing packets without acquiring core->lock might lead to use-after-free issues. Uploaded change to address above mentioned issue. Change-Id: I2047b28d69611129c4fdefcfb8a843c895e11dbb Signed-off-by: Govindaraj Rajagopal <quic_grajagop@quicinc.com>
This commit is contained in:
@@ -68,6 +68,8 @@ int venus_hfi_set_ir_period(struct msm_vidc_inst *inst, u32 ir_type,
|
||||
void venus_hfi_pm_work_handler(struct work_struct *work);
|
||||
irqreturn_t venus_hfi_isr(int irq, void *data);
|
||||
irqreturn_t venus_hfi_isr_handler(int irq, void *data);
|
||||
int venus_hfi_interface_queues_init(struct msm_vidc_core *core);
|
||||
void venus_hfi_interface_queues_deinit(struct msm_vidc_core *core);
|
||||
|
||||
int __write_register_masked(struct msm_vidc_core *core,
|
||||
u32 reg, u32 value, u32 mask);
|
||||
|
@@ -359,6 +359,8 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
|
||||
|
||||
msm_vidc_core_deinit(core, true);
|
||||
|
||||
venus_hfi_interface_queues_deinit(core);
|
||||
|
||||
d_vpr_h("depopulating sub devices\n");
|
||||
/*
|
||||
* Trigger remove for each sub-device i.e. qcom,msm-vidc,context-bank.
|
||||
@@ -547,6 +549,12 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
|
||||
goto sub_dev_failed;
|
||||
}
|
||||
|
||||
rc = venus_hfi_interface_queues_init(core);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: interface queues init failed\n", __func__);
|
||||
goto queues_init_failed;
|
||||
}
|
||||
|
||||
rc = msm_vidc_core_init(core);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: sys init failed\n", __func__);
|
||||
@@ -557,6 +565,8 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
|
||||
return rc;
|
||||
|
||||
core_init_failed:
|
||||
venus_hfi_interface_queues_deinit(core);
|
||||
queues_init_failed:
|
||||
of_platform_depopulate(&pdev->dev);
|
||||
sub_dev_failed:
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER
|
||||
|
@@ -2203,7 +2203,7 @@ static void __set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
|
||||
q_hdr->qhdr_write_idx = 0x0;
|
||||
}
|
||||
|
||||
static void __interface_queues_deinit(struct msm_vidc_core *core)
|
||||
void venus_hfi_interface_queues_deinit(struct msm_vidc_core *core)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -2227,7 +2227,7 @@ static void __interface_queues_deinit(struct msm_vidc_core *core)
|
||||
core->sfr.align_device_addr = 0;
|
||||
}
|
||||
|
||||
static int __interface_queues_init(struct msm_vidc_core *core)
|
||||
int venus_hfi_interface_queues_init(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
struct hfi_queue_table_header *q_tbl_hdr;
|
||||
@@ -2342,10 +2342,6 @@ static int __interface_queues_init(struct msm_vidc_core *core)
|
||||
/* write sfr buffer size in first word */
|
||||
*((u32 *)core->sfr.align_virtual_addr) = core->sfr.mem_size;
|
||||
|
||||
rc = call_venus_op(core, setup_ucregion_memmap, core);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
fail_alloc_queue:
|
||||
return -ENOMEM;
|
||||
@@ -2501,6 +2497,11 @@ int __load_fw(struct msm_vidc_core *core)
|
||||
__hand_off_regulators(core);
|
||||
trace_msm_v4l2_vidc_fw_load("END");
|
||||
|
||||
/* configure interface_queues memory to firmware */
|
||||
rc = call_venus_op(core, setup_ucregion_memmap, core);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
fail_protect_mem:
|
||||
if (core->dt->fw_cookie)
|
||||
@@ -2704,10 +2705,6 @@ int venus_hfi_core_init(struct msm_vidc_core *core)
|
||||
if (rc)
|
||||
goto error;
|
||||
|
||||
rc = __interface_queues_init(core);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
||||
rc = call_venus_op(core, boot_firmware, core);
|
||||
if (rc)
|
||||
goto error;
|
||||
@@ -2772,7 +2769,6 @@ int venus_hfi_core_deinit(struct msm_vidc_core *core, bool force)
|
||||
*/
|
||||
if (msm_vidc_fw_dump)
|
||||
fw_coredump(core);
|
||||
__interface_queues_deinit(core);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1945,7 +1945,7 @@ static int handle_session_response(struct msm_vidc_core *core,
|
||||
|
||||
inst = get_inst(core, hdr->session_id);
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
d_vpr_e("%s: Invalid inst\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
Verwijs in nieuw issue
Block a user