From 9e1dd001d39d2bf2c3d0bc592fb966f2eae2e2a9 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Mon, 1 Jun 2026 14:13:14 +0200 Subject: [PATCH] ipc3: helper: clear component pipeline pointers before freeing pipeline When ipc_pipeline_free() frees a pipeline, component devices that were connected to it retain stale cd->pipeline pointers. If an IPC (e.g. stream position request) later dereferences that pointer, it triggers a use-after-free. Fix this by iterating all components in the IPC comp_list and setting cd->pipeline = NULL for any component whose pipeline matches the one being freed. This makes the existing NULL checks in handler.c effective and prevents the dangling pointer dereference. Found by fuzzing with AddressSanitizer enabled. Signed-off-by: Tomasz Leman --- src/ipc/ipc3/helper.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c index 4d87f042dd1d..149ff6008a1a 100644 --- a/src/ipc/ipc3/helper.c +++ b/src/ipc/ipc3/helper.c @@ -439,6 +439,8 @@ int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) { struct ipc_comp_dev *ipc_pipe; + struct ipc_comp_dev *icd; + struct list_item *clist; int ret; /* check whether pipeline exists */ @@ -457,6 +459,19 @@ int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) if (!cpu_is_me(ipc_pipe->core)) return ipc_process_on_core(ipc_pipe->core, false); + /* Clear stale cd->pipeline pointers on all components and buffers + * that still belong to this pipeline. A well-behaved host driver + * frees components before freeing the pipeline, but if it does not + * (or in fuzz/error paths) the dangling pointer would be a + * use-after-free on any subsequent IPC referencing that component. + */ + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type == COMP_TYPE_COMPONENT && + icd->cd && icd->cd->pipeline == ipc_pipe->pipeline) + icd->cd->pipeline = NULL; + } + /* free buffer and remove from list */ ret = pipeline_free(ipc_pipe->pipeline); if (ret < 0) {