Messages in this thread |  | | Date | Mon, 08 Dec 2025 14:27:47 +0000 | | Subject | Re: [RFC][PATCH] sched/ext: Avoid null ptr traversal when ->put_prev_task() is called with NULL next | | From | Kuba Piecuch <> |
| |
On Mon Dec 8, 2025 at 11:15 AM UTC, Kuba Piecuch wrote: > On Mon Dec 8, 2025 at 10:10 AM UTC, Kuba Piecuch wrote: >> It looks like it's impossible for an outside observer holding a CPU's rq lock >> to observe a task that is running on that CPU and isn't queued, i.e. >> 'running' implies 'queued' (I'm new to the scheduler so I may be wrong here). > > A task that blocks in __schedule() can drop the rq lock while picking the next > task, which is after try_to_block_task() dequeues prev. So it's very much > possible for a task on another CPU to grab the rq lock and observe prev as > dequeued but still running.
Even with that, I'm not convinced that it's possible to do a NULL deref with the current code.
In order for sched_change_begin() to do the NULL deref in put_prev_task_scx(), we would need to have:
* rq->donor == p (for sched_change_begin() to call put_prev_task()) * p->on_rq != TASK_ON_RQ_QUEUED (for sched_change_begin() to not call dequeue_task() beforehand) * p->scx.flags & SCX_TASK_QUEUED (for put_prev_task_scx() to enter the branch with the @next deref)
From a brief survey of the code, __assuming proxy execution is disabled__, I don't think it's possible for a remote task holding @rq's lock to observe the second and third condition to be true.
Every time p->on_rq is changed away from TASK_ON_RQ_QUEUED, it happens under the rq lock and is paired with a dequeue (see block_task(), deactivate_task()). dequeue_task_scx() always clears SCX_TASK_QUEUED from p->scx.flags.
Every time SCX_TASK_QUEUED is set in p->scx.flags (i.e. enqueue_task_scx() is called), it happens under the rq lock and is either gated by p->on_rq == TASK_ON_RQ_QUEUED (see ttwu_runnable(), sched_change_end()) or is paired with p->on_rq being set to TASK_ON_RQ_QUEUED (see activate_task()). It also happens in proxy_tag_curr(), which is a no-op if proxy execution is disabled. Even when it's enabled, proxy_tag_curr() does a dequeue-enqueue cycle while holding the rq lock, which doesn't look dangerous.
I'm not trying to say that we shouldn't add a NULL check, all this is just for my own understanding.
|  |