mirror of
https://github.com/torvalds/linux.git
synced 2026-09-29 04:22:03 +02:00
sched_ext: Fix premature ops->priv publication in scx_alloc_and_add_sched()
scx_alloc_and_add_sched() publishes @sch through ops->priv before allocating
the cgroup path. If that allocation fails, the unwind path clears ops->priv
and frees @sch immediately. scx_prog_sched() callers can dereference
ops->priv from RCU context the moment it is set, so freeing without a grace
period can use-after-free a concurrent kfunc caller.
Move the publication below the cgroup path allocation so that every failure
path after publication frees @sch through kobject_put(), whose release path
defers the freeing by a grace period.
Fixes: 105dcd005b ("sched_ext: Introduce scx_prog_sched()")
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
This commit is contained in:
parent
db4e9defd2
commit
49b3378a75
|
|
@ -6878,11 +6878,6 @@ static struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
|
||||||
sch->ops = *cmd->ops;
|
sch->ops = *cmd->ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_assign_pointer(ops->priv, sch);
|
|
||||||
|
|
||||||
sch->kobj.kset = scx_kset;
|
|
||||||
INIT_LIST_HEAD(&sch->all);
|
|
||||||
|
|
||||||
#ifdef CONFIG_EXT_SUB_SCHED
|
#ifdef CONFIG_EXT_SUB_SCHED
|
||||||
char *buf = kzalloc(PATH_MAX, GFP_KERNEL);
|
char *buf = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
|
|
@ -6900,7 +6895,19 @@ static struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
|
||||||
sch->cgrp = cgrp;
|
sch->cgrp = cgrp;
|
||||||
INIT_LIST_HEAD(&sch->children);
|
INIT_LIST_HEAD(&sch->children);
|
||||||
INIT_LIST_HEAD(&sch->sibling);
|
INIT_LIST_HEAD(&sch->sibling);
|
||||||
|
#endif /* CONFIG_EXT_SUB_SCHED */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Publishing makes @sch visible to scx_prog_sched() readers. Failure
|
||||||
|
* paths after this point must free @sch through kobject_put() whose
|
||||||
|
* release path defers the actual freeing by an RCU grace period.
|
||||||
|
*/
|
||||||
|
rcu_assign_pointer(ops->priv, sch);
|
||||||
|
|
||||||
|
sch->kobj.kset = scx_kset;
|
||||||
|
INIT_LIST_HEAD(&sch->all);
|
||||||
|
|
||||||
|
#ifdef CONFIG_EXT_SUB_SCHED
|
||||||
if (parent) {
|
if (parent) {
|
||||||
/*
|
/*
|
||||||
* Pin @parent for @sch's lifetime. The kobject hierarchy pins
|
* Pin @parent for @sch's lifetime. The kobject hierarchy pins
|
||||||
|
|
@ -6955,7 +6962,6 @@ static struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
|
||||||
|
|
||||||
#ifdef CONFIG_EXT_SUB_SCHED
|
#ifdef CONFIG_EXT_SUB_SCHED
|
||||||
err_free_lb_resched:
|
err_free_lb_resched:
|
||||||
RCU_INIT_POINTER(ops->priv, NULL);
|
|
||||||
free_cpumask_var(sch->bypass_lb_resched_cpumask);
|
free_cpumask_var(sch->bypass_lb_resched_cpumask);
|
||||||
#endif
|
#endif
|
||||||
err_free_lb_cpumask:
|
err_free_lb_cpumask:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user