* [PATCH 1/3] media: iris: Fix runtime PM reference imbalance on failed resume
2026-10-17 3:16 [PATCH 0/3] media: iris: Fix issues in the driver unbind path Vishnu Reddy
@ 2026-10-17 3:16 ` Vishnu Reddy
2026-10-17 3:16 ` [PATCH 2/3] media: iris: Disable the system error work on removal Vishnu Reddy
2026-10-17 3:16 ` [PATCH 3/3] media: iris: Fix use-after-free on unbind with open sessions Vishnu Reddy
2 siblings, 0 replies; 4+ messages in thread
From: Vishnu Reddy @ 2026-10-17 3:16 UTC (permalink / raw)
To: Vikash Garodia, Dikshita Agarwal, Abhinav Kumar,
Bryan O'Donoghue, Mauro Carvalho Chehab, Stefan Schmidt,
Hans Verkuil, Dmitry Baryshkov, Hungyu Lin
Cc: linux-media, linux-arm-msm, linux-kernel, Bryan O'Donoghue,
Vishnu Reddy, stable
pm_runtime_resume_and_get() drops its usage count when the resume
fails. iris_hfi_queue_cmd_write() dropped it a second time on that
path, resulting in a runtime PM usage count underflow warning:
qcom-iris aa00000.video-codec: Runtime PM usage count underflow!
Fixes: bb8a95aa038e ("media: iris: implement power management")
Cc: stable@vger.kernel.org
Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_hfi_queue.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
index bf6db23b53e21..545bbe75e1740 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c
@@ -132,7 +132,7 @@ int iris_hfi_queue_cmd_write(struct iris_core *core, void *pkt, u32 pkt_size)
ret = pm_runtime_resume_and_get(core->dev);
if (ret < 0)
- goto exit;
+ return ret;
mutex_lock(&core->lock);
ret = iris_hfi_queue_cmd_write_locked(core, pkt, pkt_size);
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/3] media: iris: Disable the system error work on removal
2026-10-17 3:16 [PATCH 0/3] media: iris: Fix issues in the driver unbind path Vishnu Reddy
2026-10-17 3:16 ` [PATCH 1/3] media: iris: Fix runtime PM reference imbalance on failed resume Vishnu Reddy
@ 2026-10-17 3:16 ` Vishnu Reddy
2026-10-17 3:16 ` [PATCH 3/3] media: iris: Fix use-after-free on unbind with open sessions Vishnu Reddy
2 siblings, 0 replies; 4+ messages in thread
From: Vishnu Reddy @ 2026-10-17 3:16 UTC (permalink / raw)
To: Vikash Garodia, Dikshita Agarwal, Abhinav Kumar,
Bryan O'Donoghue, Mauro Carvalho Chehab, Stefan Schmidt,
Hans Verkuil, Dmitry Baryshkov, Hungyu Lin
Cc: linux-media, linux-arm-msm, linux-kernel, Bryan O'Donoghue,
Vishnu Reddy, stable
iris_remove() calls cancel_delayed_work_sync() to stop the system error
work. This cancels a pending work and waits for a running one. It does
not stop the work from being queued again afterwards.
A system error interrupt can still arrive after that call. The
interrupt handler queues the work again. The work then runs after the
removal and uses resources that are already freed.
Use disable_delayed_work_sync() instead. Once it returns no new work
can be queued. The work cannot run again during or after the removal.
Fixes: 452480931648 ("media: iris: cancel sys error work on driver removal")
Cc: stable@vger.kernel.org
Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_probe.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 41dec90f3e2b..4cb678bd56f0 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -251,7 +251,7 @@ static void iris_remove(struct platform_device *pdev)
if (!core)
return;
- cancel_delayed_work_sync(&core->sys_error_handler);
+ disable_delayed_work_sync(&core->sys_error_handler);
iris_core_deinit(core);
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 3/3] media: iris: Fix use-after-free on unbind with open sessions
2026-10-17 3:16 [PATCH 0/3] media: iris: Fix issues in the driver unbind path Vishnu Reddy
2026-10-17 3:16 ` [PATCH 1/3] media: iris: Fix runtime PM reference imbalance on failed resume Vishnu Reddy
2026-10-17 3:16 ` [PATCH 2/3] media: iris: Disable the system error work on removal Vishnu Reddy
@ 2026-10-17 3:16 ` Vishnu Reddy
2 siblings, 0 replies; 4+ messages in thread
From: Vishnu Reddy @ 2026-10-17 3:16 UTC (permalink / raw)
To: Vikash Garodia, Dikshita Agarwal, Abhinav Kumar,
Bryan O'Donoghue, Mauro Carvalho Chehab, Stefan Schmidt,
Hans Verkuil, Dmitry Baryshkov, Hungyu Lin
Cc: linux-media, linux-arm-msm, linux-kernel, Bryan O'Donoghue,
Vishnu Reddy, stable
The driver unbind can be triggered through sysfs while a client has a
video session running. The devm resources will be freed when the unbind
completes. That leads to use after free for the running sessions.
Keep the memory of the core and its device allocated until the last
file descriptor is closed. Stop new sessions as soon as the removal
starts. Make sure the interrupt thread cannot run on the core after it
is freed.
Fixes: 38506cb7e8d2 ("media: iris: add platform driver for iris video device")
Cc: stable@vger.kernel.org
Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_probe.c | 56 +++++++++++++++++++--------
1 file changed, 40 insertions(+), 16 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 4cb678bd56f0..25876957381b 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -243,6 +243,15 @@ static int iris_register_video_device(struct iris_core *core, enum domain_type t
return ret;
}
+static void iris_core_release(struct v4l2_device *v4l2_dev)
+{
+ struct iris_core *core = container_of(v4l2_dev, struct iris_core, v4l2_dev);
+
+ mutex_destroy(&core->lock);
+ put_device(core->dev);
+ kfree(core);
+}
+
static void iris_remove(struct platform_device *pdev)
{
struct iris_core *core;
@@ -251,18 +260,20 @@ static void iris_remove(struct platform_device *pdev)
if (!core)
return;
+ video_unregister_device(core->vdev_dec);
+ video_unregister_device(core->vdev_enc);
+
disable_delayed_work_sync(&core->sys_error_handler);
iris_core_deinit(core);
- video_unregister_device(core->vdev_dec);
- video_unregister_device(core->vdev_enc);
+ devm_free_irq(core->dev, core->irq, core);
v4l2_device_unregister(&core->v4l2_dev);
iris_unreserve_iova_region(core->dev, core->iova_state);
- mutex_destroy(&core->lock);
+ v4l2_device_put(&core->v4l2_dev);
}
static void iris_sys_error_handler(struct work_struct *work)
@@ -281,53 +292,64 @@ static int iris_probe(struct platform_device *pdev)
u64 dma_mask;
int ret;
- core = devm_kzalloc(&pdev->dev, sizeof(*core), GFP_KERNEL);
+ core = kzalloc_obj(*core);
if (!core)
return -ENOMEM;
- core->dev = dev;
+ core->dev = get_device(dev);
+
+ core->v4l2_dev.release = iris_core_release;
+ kref_init(&core->v4l2_dev.ref);
core->state = IRIS_CORE_DEINIT;
mutex_init(&core->lock);
init_completion(&core->core_init_done);
core->response_packet = devm_kzalloc(core->dev, IFACEQ_CORE_PKT_SIZE, GFP_KERNEL);
- if (!core->response_packet)
- return -ENOMEM;
+ if (!core->response_packet) {
+ ret = -ENOMEM;
+ goto err_put_core;
+ }
INIT_LIST_HEAD(&core->instances);
INIT_DELAYED_WORK(&core->sys_error_handler, iris_sys_error_handler);
core->reg_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(core->reg_base))
- return PTR_ERR(core->reg_base);
+ if (IS_ERR(core->reg_base)) {
+ ret = PTR_ERR(core->reg_base);
+ goto err_put_core;
+ }
core->irq = platform_get_irq(pdev, 0);
- if (core->irq < 0)
- return core->irq;
+ if (core->irq < 0) {
+ ret = core->irq;
+ goto err_put_core;
+ }
core->iris_platform_data = of_device_get_match_data(core->dev);
core->ubwc_cfg = qcom_ubwc_config_get_data();
- if (IS_ERR(core->ubwc_cfg))
- return PTR_ERR(core->ubwc_cfg);
+ if (IS_ERR(core->ubwc_cfg)) {
+ ret = PTR_ERR(core->ubwc_cfg);
+ goto err_put_core;
+ }
ret = devm_request_threaded_irq(core->dev, core->irq, iris_hfi_isr,
iris_hfi_isr_handler,
IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
"iris", core);
if (ret)
- return ret;
+ goto err_put_core;
iris_init_ops(core);
ret = iris_init_resources(core);
if (ret)
- return ret;
+ goto err_put_core;
ret = iris_reserve_iova_region(dev, &core->iova_state, IRIS_NP_RESERVE_IOVA_START,
IRIS_NP_RESERVE_IOVA_SIZE);
if (ret)
- return ret;
+ goto err_put_core;
ret = v4l2_device_register(dev, &core->v4l2_dev);
if (ret)
@@ -368,6 +390,8 @@ static int iris_probe(struct platform_device *pdev)
v4l2_device_unregister(&core->v4l2_dev);
err_unresv_iova_region:
iris_unreserve_iova_region(dev, core->iova_state);
+err_put_core:
+ v4l2_device_put(&core->v4l2_dev);
return ret;
}
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread