Repository navigation
Conversation
Task and Cgroup wrap the kernel's task_struct and cgroup without an UnsafeCell, so rustc marks a &Task or &Cgroup argument noalias readonly. The kernel and the kfuncs change both while a callback holds them. LLVM may then delete a store made through as_ptr() and reuse a field read from before a kfunc call. Both happen. A plain store to p->scx.disallow from a non-inlined helper taking &Task was compiled away, and a plain read of the slice after scx_bpf_task_set_slice() returned the value read before the call. The library reads fields with read_volatile and writes through kfuncs, so no scheduler in the tree is affected yet. Wrap both in UnsafeCell, which keeps the layout (it is repr(transparent)) and drops the readonly and noalias attributes. as_ptr() now returns the cell's pointer instead of casting away const. Signed-off-by: Andrea Righi <arighi@nvidia.com>
Timer has the problem c2fd7d9 ("scx_rustsched: Let callbacks change the task and cgroup they are passed") fixed for Task and Cgroup. A timer callback holds a &Timer while bpf_timer_init(), bpf_timer_cancel() or a map delete on another CPU can change the timer's words, and start() casts the shared reference to a mutable pointer. Rust never reads or writes those words itself, so nothing can be miscompiled today. This only removes the undefined behaviour. Wrap the words of bpf_timer in an UnsafeCell rather than the struct itself. The verifier finds the timer in a map value by the struct name bpf_timer, which a wrapping UnsafeCell<bpf_timer> would hide. The layout and the generated code stay the same. Signed-off-by: Andrea Righi <arighi@nvidia.com>
sirlucjan
approved these changes
Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The handle types that scx_rustsched callbacks receive (Task, Cgroup and Timer) wrap kernel memory without an UnsafeCell. Rust therefore treats a
&Taskargument as read-only and unaliased, and LLVM is free to assume nothing changes the task while the callback holds it. The kernel and the kfuncs do change it, so this is undefined behaviour.The fix wraps the kernel structure in an UnsafeCell, which keeps the layout and removes the read-only and no-alias assumptions. For Timer the cell goes around the words inside bpf_timer, because the verifier finds a timer in a map value by the struct name bpf_timer.