[PATCH v5 3/6] media: meson: vdec: Set cur_sess before hardware vdec_poweron()

From: Anand Moon

Date: Mon May 25 2026 - 05:56:20 EST


vdec_poweron() initializes hardware and unmasks device interrupts. If an
interrupt fires before core->cur_sess is set, vdec_isr() dereferences a
NULL pointer when updating sess->last_irq_jiffies, leading to a kernel
panic.

Fix this by assigning core->cur_sess and updating sess->status under
core->lock before calling vdec_poweron(). This ensures the interrupt
handler always sees a valid session pointer. On the error path, clear
core->cur_sess and reset sess->status to STATUS_STOPPED to avoid stale
references.

Following change also strengthens the hardware exclusivity check by
holding core->lock during session assignment, preventing concurrent
sessions from racing through cur_sess == NULL and corrupting hardware
state.

Cc: Nicolas Dufresne <nicolas@xxxxxxxxxxxx>
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Closes: https://lore.kernel.org/all/20260521090944.F35401F00A3D@xxxxxxxxxxxxxxx/
Fixes: 3e7f51bd9607 ("media: meson: add v4l2 m2m video decoder driver")
Signed-off-by: Anand Moon <linux.amoon@xxxxxxxxx>
---
v5: [Critical] Race condition between hardware power-on and `core->cur_sess`
initialization leads to a NULL pointer dereference in the IRQ handler.
---
drivers/staging/media/meson/vdec/vdec.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
index e72f54af026e..52ace4de967c 100644
--- a/drivers/staging/media/meson/vdec/vdec.c
+++ b/drivers/staging/media/meson/vdec/vdec.c
@@ -334,6 +334,11 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
atomic_set(&sess->esparser_queued_bufs, 0);
v4l2_ctrl_s_ctrl(sess->ctrl_min_buf_capture, 1);

+ mutex_lock(&core->lock);
+ core->cur_sess = sess;
+ sess->status = STATUS_INIT;
+ mutex_unlock(&core->lock);
+
ret = vdec_poweron(sess);
if (ret)
goto vififo_free;
@@ -344,12 +349,14 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
sess->recycle_thread = kthread_run(vdec_recycle_thread, sess,
"vdec_recycle");

- sess->status = STATUS_INIT;
- core->cur_sess = sess;
schedule_work(&sess->esparser_queue_work);
return 0;

vififo_free:
+ mutex_lock(&core->lock);
+ core->cur_sess = NULL;
+ sess->status = STATUS_STOPPED;
+ mutex_unlock(&core->lock);
dma_free_coherent(sess->core->dev, sess->vififo_size,
sess->vififo_vaddr, sess->vififo_paddr);
bufs_done:
--
2.50.1