From f9ffa46551497ff874a2f8c907f7d8a61faa4358 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 11 Jun 2026 12:56:13 +0200 Subject: [PATCH 1/2] ipc4: chain_dma: free stale ipc_comp_dev on error path When ipc4_chain_dma_state() fails for a freshly created chain DMA unlink and free the ipc_comp_dev as well, not just the comp_dev Signed-off-by: Adrian Bonislawski --- src/ipc/ipc4/handler-user.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index 5a5f3d6d6f32..75b07c0d67ea 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -601,6 +601,8 @@ __cold static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4) ret = ipc4_chain_dma_state(cdma_comp->cd, &cdma); if (ret < 0) { comp_free(cdma_comp->cd); + list_item_del(&cdma_comp->list); + rfree(cdma_comp); return IPC4_FAILURE; } From 2bcaf7bdad67142588d3abc4425e907973db670c Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 11 Jun 2026 13:15:52 +0200 Subject: [PATCH 2/2] ipc: clear dangling pipeline comp refs on instance free ipc_comp_free() freed a component that a completed pipeline still referenced via source_comp/sink_comp/sched_comp, so a later SET_PIPELINE_STATE dereferenced the freed comp_dev. Clear those references on free and bail out of pipeline_get_host_dev() when an endpoint is gone. Signed-off-by: Adrian Bonislawski --- src/ipc/ipc-helper.c | 19 +++++++++++++++++++ src/ipc/ipc4/handler-user.c | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/src/ipc/ipc-helper.c b/src/ipc/ipc-helper.c index ad7b3771a16b..b7ef418e0339 100644 --- a/src/ipc/ipc-helper.c +++ b/src/ipc/ipc-helper.c @@ -291,6 +291,7 @@ __cold int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) struct ipc_comp_dev *icd; struct comp_buffer *buffer; struct comp_buffer *safe; + struct list_item *clist; uint32_t flags; assert_can_be_cold(); @@ -348,6 +349,24 @@ __cold int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) irq_local_enable(flags); + /* + * A completed pipeline stores raw comp_dev pointers in its + * source_comp/sink_comp/sched_comp fields. + */ + list_for_item(clist, &ipc->comp_list) { + struct ipc_comp_dev *ppl_icd = container_of(clist, struct ipc_comp_dev, list); + + if (ppl_icd->type != COMP_TYPE_PIPELINE) + continue; + + if (ppl_icd->pipeline->source_comp == icd->cd) + ppl_icd->pipeline->source_comp = NULL; + if (ppl_icd->pipeline->sink_comp == icd->cd) + ppl_icd->pipeline->sink_comp = NULL; + if (ppl_icd->pipeline->sched_comp == icd->cd) + ppl_icd->pipeline->sched_comp = NULL; + } + /* free component and remove from list */ comp_free(icd->cd); diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c index 75b07c0d67ea..5f1f92fd2e83 100644 --- a/src/ipc/ipc4/handler-user.c +++ b/src/ipc/ipc4/handler-user.c @@ -149,6 +149,11 @@ static struct ipc_comp_dev *pipeline_get_host_dev(struct ipc_comp_dev *ppl_icd) struct ipc *ipc = ipc_get(); int host_id; + if (!ppl_icd->pipeline->source_comp || !ppl_icd->pipeline->sink_comp) { + ipc_cmd_err(&ipc_tr, "pipeline %d: source/sink comp freed", ppl_icd->id); + return NULL; + } + /* If the source component's direction is not set but the sink's direction is, * this block will copy the direction from the sink to the source component and * mark the source's direction as set.