summaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorSergey Senozhatsky <senozhatsky@chromium.org>2024-10-25 18:56:42 +0200
committerHans Verkuil <hverkuil@xs4all.nl>2024-11-07 11:43:31 +0100
commit45b1a1b348ec178a599323f1ce7d7932aea8c6d4 (patch)
tree2e986c5e9e3c8c8da40e5f6f104e9447959c3c5b /drivers/media
parentmedia: venus: fix enc/dec destruction order (diff)
downloadlinux-45b1a1b348ec178a599323f1ce7d7932aea8c6d4.tar.xz
linux-45b1a1b348ec178a599323f1ce7d7932aea8c6d4.zip
media: venus: sync with threaded IRQ during inst destruction
When destroying an inst we should make sure that we don't race against threaded IRQ (or pending IRQ), otherwise we can concurrently kfree() inst context and inst itself. BUG: KASAN: slab-use-after-free in vb2_queue_error+0x80/0x90 Call trace: dump_backtrace+0x1c4/0x1f8 show_stack+0x38/0x60 dump_stack_lvl+0x168/0x1f0 print_report+0x170/0x4c8 kasan_report+0x94/0xd0 __asan_report_load2_noabort+0x20/0x30 vb2_queue_error+0x80/0x90 venus_helper_vb2_queue_error+0x54/0x78 venc_event_notify+0xec/0x158 hfi_event_notify+0x878/0xd20 hfi_process_msg_packet+0x27c/0x4e0 venus_isr_thread+0x258/0x6e8 hfi_isr_thread+0x70/0x90 venus_isr_thread+0x34/0x50 irq_thread_fn+0x88/0x130 irq_thread+0x160/0x2c0 kthread+0x294/0x328 ret_from_fork+0x10/0x20 Allocated by task 20291: kasan_set_track+0x4c/0x80 kasan_save_alloc_info+0x28/0x38 __kasan_kmalloc+0x84/0xa0 kmalloc_trace+0x7c/0x98 v4l2_m2m_ctx_init+0x74/0x280 venc_open+0x444/0x6d0 v4l2_open+0x19c/0x2a0 chrdev_open+0x374/0x3f0 do_dentry_open+0x710/0x10a8 vfs_open+0x88/0xa8 path_openat+0x1e6c/0x2700 do_filp_open+0x1a4/0x2e0 do_sys_openat2+0xe8/0x508 do_sys_open+0x15c/0x1a0 __arm64_sys_openat+0xa8/0xc8 invoke_syscall+0xdc/0x270 el0_svc_common+0x1ec/0x250 do_el0_svc+0x54/0x70 el0_svc+0x50/0xe8 el0t_64_sync_handler+0x48/0x120 el0t_64_sync+0x1a8/0x1b0 Freed by task 20291: kasan_set_track+0x4c/0x80 kasan_save_free_info+0x3c/0x60 ____kasan_slab_free+0x124/0x1a0 __kasan_slab_free+0x18/0x28 __kmem_cache_free+0x134/0x300 kfree+0xc8/0x1a8 v4l2_m2m_ctx_release+0x44/0x60 venc_close+0x78/0x130 [venus_enc] v4l2_release+0x20c/0x2f8 __fput+0x328/0x7f0 ____fput+0x2c/0x48 task_work_run+0x1e0/0x280 get_signal+0xfb8/0x1190 do_notify_resume+0x34c/0x16a8 el0_svc+0x9c/0xe8 el0t_64_sync_handler+0x48/0x120 el0t_64_sync+0x1a8/0x1b0 Rearrange inst destruction. First remove the inst from the core->instances list, second synchronize IRQ/IRQ-thread to make sure that nothing else would see the inst while we take it down. Fixes: 7472c1c69138 ("[media] media: venus: vdec: add video decoder files") Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Stanimir Varbanov <stanimir.k.varbanov@gmail.com> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/qcom/venus/vdec.c12
-rw-r--r--drivers/media/platform/qcom/venus/venc.c12
2 files changed, 22 insertions, 2 deletions
diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c
index b81439d34d90..90fd4cb4eea9 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -1748,10 +1748,20 @@ static int vdec_close(struct file *file)
vdec_pm_get(inst);
cancel_work_sync(&inst->delayed_process_work);
+ /*
+ * First, remove the inst from the ->instances list, so that
+ * to_instance() will return NULL.
+ */
+ hfi_session_destroy(inst);
+ /*
+ * Second, make sure we don't have IRQ/IRQ-thread currently running
+ * or pending execution, which would race with the inst destruction.
+ */
+ synchronize_irq(inst->core->irq);
+
v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev);
ida_destroy(&inst->dpb_ids);
- hfi_session_destroy(inst);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
vdec_ctrl_deinit(inst);
diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c
index efe1e3837fe8..00819483bdc4 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -1540,9 +1540,19 @@ static int venc_close(struct file *file)
venc_pm_get(inst);
+ /*
+ * First, remove the inst from the ->instances list, so that
+ * to_instance() will return NULL.
+ */
+ hfi_session_destroy(inst);
+ /*
+ * Second, make sure we don't have IRQ/IRQ-thread currently running
+ * or pending execution, which would race with the inst destruction.
+ */
+ synchronize_irq(inst->core->irq);
+
v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev);
- hfi_session_destroy(inst);
v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh);
venc_ctrl_deinit(inst);