On Thu Mar 5 18:58:31 2026 +0530, Vishnu Reddy wrote:
> During concurrency testing, multiple instances can run in parallel, and
> each instance uses its own inst->lock while the core->lock protects the
> list of active instances. The race happens because these locks cover
> different scopes, inst->lock protects only the internals of a single
> instance, while the Macro Blocks Per Frame (MBPF) checker walks the
> core list under core->lock and reads fields like fmt_src->width and
> fmt_src->height. At the same time, iris_close() may free fmt_src and
> fmt_dst under inst->lock while the instance is still present in the core
> list. This allows a situation where the MBPF checker, still iterating
> through the core list, reaches an instance whose fmt_src was already
> freed by another thread and ends up dereferencing a dangling pointer,
> resulting in a use-after-free. This happens because the MBPF checker
> assumes that any instance in the core list is fully valid, but the
> freeing of fmt_src and fmt_dst without removing the instance from the
> core list is not correct.
>
> The correct ordering is to defer freeing fmt_src and fmt_dst until after
> the instance has been removed from the core list and all teardown under
> the core lock has completed, ensuring that no dangling pointers are ever
> exposed during MBPF checks.
>
> Reviewed-by: Vikash Garodia <[email protected]>
> Signed-off-by: Vishnu Reddy <[email protected]>
> Reviewed-by: Dikshita Agarwal <[email protected]>
> Fixes: 5ad964ad5656 ("media: iris: Initialize and deinitialize encoder
> instance structure")
> Cc: [email protected]
> Signed-off-by: Bryan O'Donoghue <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
drivers/media/platform/qcom/iris/iris_vdec.c | 6 ------
drivers/media/platform/qcom/iris/iris_vdec.h | 1 -
drivers/media/platform/qcom/iris/iris_venc.c | 6 ------
drivers/media/platform/qcom/iris/iris_venc.h | 1 -
drivers/media/platform/qcom/iris/iris_vidc.c | 6 ++----
5 files changed, 2 insertions(+), 18 deletions(-)
---
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c
b/drivers/media/platform/qcom/iris/iris_vdec.c
index 719217399a30..99d544e2af4f 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -61,12 +61,6 @@ int iris_vdec_inst_init(struct iris_inst *inst)
return iris_ctrls_init(inst);
}
-void iris_vdec_inst_deinit(struct iris_inst *inst)
-{
- kfree(inst->fmt_dst);
- kfree(inst->fmt_src);
-}
-
static const struct iris_fmt iris_vdec_formats_cap[] = {
[IRIS_FMT_NV12] = {
.pixfmt = V4L2_PIX_FMT_NV12,
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h
b/drivers/media/platform/qcom/iris/iris_vdec.h
index ec1ce55d1375..5123d2a340e1 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/iris/iris_vdec.h
@@ -9,7 +9,6 @@
struct iris_inst;
int iris_vdec_inst_init(struct iris_inst *inst);
-void iris_vdec_inst_deinit(struct iris_inst *inst);
int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c
b/drivers/media/platform/qcom/iris/iris_venc.c
index aa27b22704eb..4d886769d958 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -79,12 +79,6 @@ int iris_venc_inst_init(struct iris_inst *inst)
return iris_ctrls_init(inst);
}
-void iris_venc_inst_deinit(struct iris_inst *inst)
-{
- kfree(inst->fmt_dst);
- kfree(inst->fmt_src);
-}
-
static const struct iris_fmt iris_venc_formats_cap[] = {
[IRIS_FMT_H264] = {
.pixfmt = V4L2_PIX_FMT_H264,
diff --git a/drivers/media/platform/qcom/iris/iris_venc.h
b/drivers/media/platform/qcom/iris/iris_venc.h
index c4db7433da53..00c1716b2747 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/iris/iris_venc.h
@@ -9,7 +9,6 @@
struct iris_inst;
int iris_venc_inst_init(struct iris_inst *inst);
-void iris_venc_inst_deinit(struct iris_inst *inst);
int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c
b/drivers/media/platform/qcom/iris/iris_vidc.c
index bd38d84c9cc7..5eb1786b0737 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -289,10 +289,6 @@ int iris_close(struct file *filp)
v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev);
mutex_lock(&inst->lock);
- if (inst->domain == DECODER)
- iris_vdec_inst_deinit(inst);
- else if (inst->domain == ENCODER)
- iris_venc_inst_deinit(inst);
iris_session_close(inst);
iris_inst_change_state(inst, IRIS_INST_DEINIT);
iris_v4l2_fh_deinit(inst, filp);
@@ -304,6 +300,8 @@ int iris_close(struct file *filp)
mutex_unlock(&inst->lock);
mutex_destroy(&inst->ctx_q_lock);
mutex_destroy(&inst->lock);
+ kfree(inst->fmt_src);
+ kfree(inst->fmt_dst);
kfree(inst);
return 0;
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]