Skip to content

Commit ce9aaa3

Browse files
htejungregkh
authored andcommitted
sched_ext: Read scx_root under scx_cgroup_ops_rwsem in cgroup setters
[ Upstream commit 80afd4c ] scx_group_set_{weight,idle,bandwidth}() cache scx_root before acquiring scx_cgroup_ops_rwsem, so the pointer can be stale by the time the op runs. If the loaded scheduler is disabled and freed (via RCU work) and another is enabled between the naked load and the rwsem acquire, the reader sees scx_cgroup_enabled=true (the new scheduler's) but dereferences the freed one - UAF on SCX_HAS_OP(sch, ...) / SCX_CALL_OP(sch, ...). scx_cgroup_enabled is toggled only under scx_cgroup_ops_rwsem write (scx_cgroup_{init,exit}), so reading scx_root inside the rwsem read section correlates @sch with the enabled snapshot. Fixes: a5bd6ba ("sched_ext: Use cgroup_lock/unlock() to synchronize against cgroup operations") Cc: stable@vger.kernel.org # v6.18+ Reported-by: Chris Mason <clm@meta.com> Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 30cf8e0 commit ce9aaa3

1 file changed

Lines changed: 6 additions & 3 deletions

File tree

kernel/sched/ext.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3251,9 +3251,10 @@ void scx_cgroup_cancel_attach(struct cgroup_taskset *tset)
32513251

32523252
void scx_group_set_weight(struct task_group *tg, unsigned long weight)
32533253
{
3254-
struct scx_sched *sch = scx_root;
3254+
struct scx_sched *sch;
32553255

32563256
percpu_down_read(&scx_cgroup_ops_rwsem);
3257+
sch = scx_root;
32573258

32583259
if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_weight) &&
32593260
tg->scx.weight != weight)
@@ -3267,9 +3268,10 @@ void scx_group_set_weight(struct task_group *tg, unsigned long weight)
32673268

32683269
void scx_group_set_idle(struct task_group *tg, bool idle)
32693270
{
3270-
struct scx_sched *sch = scx_root;
3271+
struct scx_sched *sch;
32713272

32723273
percpu_down_read(&scx_cgroup_ops_rwsem);
3274+
sch = scx_root;
32733275

32743276
if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_idle))
32753277
SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_idle, NULL,
@@ -3284,9 +3286,10 @@ void scx_group_set_idle(struct task_group *tg, bool idle)
32843286
void scx_group_set_bandwidth(struct task_group *tg,
32853287
u64 period_us, u64 quota_us, u64 burst_us)
32863288
{
3287-
struct scx_sched *sch = scx_root;
3289+
struct scx_sched *sch;
32883290

32893291
percpu_down_read(&scx_cgroup_ops_rwsem);
3292+
sch = scx_root;
32903293

32913294
if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_bandwidth) &&
32923295
(tg->scx.bw_period_us != period_us ||

0 commit comments

Comments
 (0)