Skip to content

chain-dma: fix NULL dereference#11016

Open
lyakh wants to merge 1 commit into
thesofproject:mainfrom
lyakh:chain
Open

chain-dma: fix NULL dereference#11016
lyakh wants to merge 1 commit into
thesofproject:mainfrom
lyakh:chain

Conversation

@lyakh

@lyakh lyakh commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Fix a NULL dereference when terminating a chain-dma stream after schedule_task_free() has been called from chain_task_pause().

If somebody can fix chain DMA instead to not leave the task running after it's freed, that might be a preferred solution

@lyakh
lyakh requested a review from pblaszko as a code owner July 20, 2026 12:34
Copilot AI review requested due to automatic review settings July 20, 2026 12:34

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

This PR hardens the Zephyr low-latency scheduler against a NULL (or otherwise invalid) task->priv_data during task completion, preventing a crash when a chain-dma stream is terminated after schedule_task_free() has been triggered from chain_task_pause().

Changes:

  • Guard zephyr_ll_task_done() against task->priv_data == NULL before checking pdata->freeing.
  • Refresh pdata = task->priv_data after re-acquiring the scheduler lock in zephyr_ll_run() and treat NULL pdata as a condition to complete the task.

Comment thread src/schedule/zephyr_ll.c
Comment on lines -301 to 303
if (pdata->freeing || state == SOF_TASK_STATE_COMPLETED) {
if (!pdata || pdata->freeing || state == SOF_TASK_STATE_COMPLETED) {
zephyr_ll_task_done(sch, task);

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.

Pointer pdata is dereferenced at line 267, so the compiler has the right to assume that it cannot be NULL here and will optimize out this check.
And why are you assigning it a second time?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@tmleman you're right. I first thought that since it only crashes after the call to do_task_run() so it must be happening there, that .pdata gets assigned NULL by the chain-dma component. But then I realised, that that assignment only happens in IPC context and the IPC thread priority is lower than the LL thread, so it cannot preempt it even with the lock dropped. So, I checked and indeed .pdata == NULL already before do_task_run() and it doesn't crash before because of our everybody's favourite #6093 . I've updated the commit.

Fix a NULL dereference when terminating a chain-dma stream after
schedule_task_free() has been called from chain_task_pause().

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
@lgirdwood

Copy link
Copy Markdown
Member

@lyakh can you check CI, could be a false positive. Thanks

@ujfalusi

Copy link
Copy Markdown
Contributor

@lyakh, I think this is probably not the right fix, bisect points to the following commit and a revert of it fixes the problem 48cdc4d

@lgirdwood

Copy link
Copy Markdown
Member

@lyakh, I think this is probably not the right fix, bisect points to the following commit and a revert of it fixes the problem 48cdc4d

@lyakh this is probably a case for an assert then given the pointer scope.

@ujfalusi ujfalusi 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.

It would be better to understand what is the issue before hiding it?

Comment thread src/schedule/zephyr_ll.c
task->state = SOF_TASK_STATE_FREE;

if (pdata->freeing)
if (pdata && pdata->freeing)

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 real issue is with the 48cdc4d + CONFIG_USERSPACE=y
this combination causes the ChainDMA crash on PTL and only on PTL as CONFIG_USERSPACE=y is only set for PTL, all other platform has USERSPACE disabled.
it boils down to some difference due to the use of kernel/sys/sem.c vs kernel/userspace/sem.c for semaphore.

Reverting the commit or disabling USERSPACE fixed the crash on PTL.

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.

7 participants