Skip to content

Commit e14ed5b

Browse files
committed
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 <tomasz.m.leman@intel.com>
1 parent 0f9fa75 commit e14ed5b

1 file changed

Lines changed: 18 additions & 0 deletions

File tree

src/ipc/ipc3/helper.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,9 @@ int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc)
439439
int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id)
440440
{
441441
struct ipc_comp_dev *ipc_pipe;
442+
struct ipc_comp_dev *icd;
443+
struct list_item *clist;
444+
uint32_t pipeline_id;
442445
int ret;
443446

444447
/* check whether pipeline exists */
@@ -457,6 +460,21 @@ int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id)
457460
if (!cpu_is_me(ipc_pipe->core))
458461
return ipc_process_on_core(ipc_pipe->core, false);
459462

463+
pipeline_id = ipc_pipe->pipeline->pipeline_id;
464+
465+
/* Clear stale cd->pipeline pointers on all components and buffers
466+
* that still belong to this pipeline. A well-behaved host driver
467+
* frees components before freeing the pipeline, but if it does not
468+
* (or in fuzz/error paths) the dangling pointer would be a
469+
* use-after-free on any subsequent IPC referencing that component.
470+
*/
471+
list_for_item(clist, &ipc->comp_list) {
472+
icd = container_of(clist, struct ipc_comp_dev, list);
473+
if (icd->type == COMP_TYPE_COMPONENT &&
474+
icd->cd && icd->cd->pipeline == ipc_pipe->pipeline)
475+
icd->cd->pipeline = NULL;
476+
}
477+
460478
/* free buffer and remove from list */
461479
ret = pipeline_free(ipc_pipe->pipeline);
462480
if (ret < 0) {

0 commit comments

Comments
 (0)