Skip to content

ipc3: helper: clear component pipeline pointers before freeing pipeline#10852

Open
tmleman wants to merge 1 commit into
thesofproject:mainfrom
tmleman:topic/upstream/pr/fix/ipc3/clear_component_pointers
Open

ipc3: helper: clear component pipeline pointers before freeing pipeline#10852
tmleman wants to merge 1 commit into
thesofproject:mainfrom
tmleman:topic/upstream/pr/fix/ipc3/clear_component_pointers

Conversation

@tmleman

@tmleman tmleman commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

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.

Copilot AI review requested due to automatic review settings June 8, 2026 13:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a potential use-after-free in IPC3 pipeline teardown by ensuring components no longer hold dangling cd->pipeline pointers after ipc_pipeline_free() frees the pipeline object.

Changes:

  • Iterate ipc->comp_list during ipc_pipeline_free() and clear cd->pipeline for components still referencing the pipeline being freed.

Comment thread src/ipc/ipc3/helper.c
@tmleman tmleman force-pushed the topic/upstream/pr/fix/ipc3/clear_component_pointers branch from e14ed5b to 9e1dd00 Compare June 8, 2026 14:14
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>

@lgirdwood lgirdwood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbaluta fyi

Comment thread src/ipc/ipc3/helper.c
* 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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description implies that the entire sequence is invalid and the pointers to the already freed pipeline are only indications of this. If this is really a non-critical bug and you are 100% certain that there are no other side effects, I would at least issue a warning; Else, return an error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where? In the place where I set pointers to NULL that's normal flow. Do you mean that instead of setting the pointer to NULL I should insert a warning that there's a component in memory that was part of a pipeline that was deleted and now holds a pointer to freed memory?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is an error then I think you could indeed skip NULL setting. In case of warning (or non-critical error), you would need to keep this code and just add a log.

But if this is the normal flow, then maybe I misinterpreted the phrase "well-behaved host driver" ;) I thought "well-behaved host driver" equals "driver without bugs"... but it also can be interpreted as "minimalistic driver" that doesn't perform optional steps.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I'll do it this way, it seems to me this is the best approach. The driver removes the pipeline and then the module, and this flow is fine. If the driver sends an IPC to the module (in the case that triggered a crash in the fuzzer, this is a stream position request) whose pipeline has already been removed, it will dereference a pointer to memory that has been freed. After this change, the driver will get an error because the module will no longer hold a pointer to the pipeline. I assume it's too late for IPC3 to introduce restrictions on the IPC sending order (remove components first, then the pipeline).

It seems logical to me: you trigger an action on a component that is no longer part of the pipeline and you get an error in return.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the sequence is legal, then the comment is confusing (at least to me):

  1. The phrase "well-behaved" is vague because the opposite might be interpreted as erroneous (misbehaved). I would use something like "conventional" instead.
  2. "any subsequent IPC referencing that component" -> "any subsequent IPC referencing that pipeline" OR "any subsequent IPC referencing that component except COMP_FREE". Because COMP_FREE IPC would still be legal according to your clarification, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants