This repository has been archived by the owner on Jun 18, 2024. It is now read-only.
scx: Close a small race window in the enable path which can lead to use-after-free #205
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.
scx_ops_enable() was iterating all tasks without locking its rq and then calling get_task_struct() on them. However, this can race against task free path. The task struct itself is accessible but its refcnt may already have reached zero by the time get_task_struct() is called. This triggers the following refcnt warning.
WARNING: CPU: 11 PID: 2834521 at lib/refcount.c:25 refcount_warn_saturate+0x7d/0xe0
...
RIP: 0010:refcount_warn_saturate+0x7d/0xe0
...
Call Trace:
bpf_scx_reg+0x851/0x890
bpf_struct_ops_link_create+0xbd/0xe0
__sys_bpf+0x2862/0x2d20
__x64_sys_bpf+0x18/0x20
do_syscall_64+0x3d/0x90
entry_SYSCALL_64_after_hwframe+0x46/0xb0
This can also affect other loops as it can call sched functions on tasks which are already destroyed. Let's fix it by making scx_task_iter_filtered_locked() also filter out TASK_DEAD tasks and switching the scx_task_iter_filtered() usage in scx_ops_enable() to scx_task_iter_filtered_locked(). This makes the next function always test TASK_DEAD while holding the task's rq lock and the rq lock guarantees that the task won't be freed closing the race window.