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:
Govindaraj Rajagopal
2022-06-28 11:25:59 +05:30
bovenliggende df3fd88dac
commit 06643c1de9
4 gewijzigde bestanden met toevoegingen van 20 en 12 verwijderingen

Bestand weergeven

@@ -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);

Bestand weergeven

@@ -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

Bestand weergeven

@@ -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;
}

Bestand weergeven

@@ -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;
}