Skip to content

Commit 70615c4

Browse files
committed
schedule: zephyr_ll: fix NULL pointer dereference and race conditions during task free
When a task is freed by zephyr_ll_task_free(), zephyr_ll_run() can still hold a reference to the task's pdata structure across the LL lock boundary. Re-fetching task->priv_data under zephyr_ll_lock() prevents evaluating pdata->freeing on a stale/freed pointer. Additionally, add NULL checks for pdata in zephyr_ll_task_done() and task/pdata in zephyr_ll_task_free(). Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
1 parent cf89a85 commit 70615c4

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

src/schedule/zephyr_ll.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static void zephyr_ll_task_done(struct zephyr_ll *sch,
132132

133133
task->state = SOF_TASK_STATE_FREE;
134134

135-
if (pdata->freeing)
135+
if (pdata && pdata->freeing)
136136
/*
137137
* zephyr_ll_task_free() is trying to free this task. Complete
138138
* it and signal the semaphore to let the function proceed
@@ -297,8 +297,9 @@ static void zephyr_ll_run(void *data)
297297
#ifndef CONFIG_SOF_USERSPACE_LL
298298
zephyr_ll_lock(sch, &flags);
299299
#endif
300+
pdata = task->priv_data;
300301

301-
if (pdata->freeing || state == SOF_TASK_STATE_COMPLETED) {
302+
if (!pdata || pdata->freeing || state == SOF_TASK_STATE_COMPLETED) {
302303
zephyr_ll_task_done(sch, task);
303304
} else {
304305
/*
@@ -457,9 +458,16 @@ static int zephyr_ll_task_free(void *data, struct task *task)
457458
{
458459
struct zephyr_ll *sch = data;
459460
uint32_t flags;
460-
struct zephyr_ll_pdata *pdata = task->priv_data;
461+
struct zephyr_ll_pdata *pdata;
461462
bool must_wait, on_list = true;
462463

464+
if (!task)
465+
return 0;
466+
467+
pdata = task->priv_data;
468+
if (!pdata)
469+
return 0;
470+
463471
zephyr_ll_assert_core(sch);
464472

465473
#ifndef CONFIG_SOF_USERSPACE_LL

0 commit comments

Comments
 (0)