Re: [PATCH v4 sched_ext/for-7.3 02/40] sched_ext: Fix premature ops->priv publication in scx_alloc_and_add_sched()

From: Andrea Righi

Date: Thu Jul 09 2026 - 16:42:41 EST


On Wed, Jul 08, 2026 at 11:23:51AM -1000, Tejun Heo wrote:
> 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: 105dcd005be2 ("sched_ext: Introduce scx_prog_sched()")
> Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>

Reviewed-by: Andrea Righi <arighi@xxxxxxxxxx>

Thanks,
-Andrea

> ---
> kernel/sched/ext/ext.c | 18 ++++++++++++------
> 1 file changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index 1a0ec985da77..f4725698f5ef 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -6363,11 +6363,6 @@ struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
> 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
> char *buf = kzalloc(PATH_MAX, GFP_KERNEL);
> if (!buf) {
> @@ -6385,7 +6380,19 @@ struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
> sch->cgrp = cgrp;
> INIT_LIST_HEAD(&sch->children);
> 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) {
> /*
> * Pin @parent for @sch's lifetime. The kobject hierarchy pins
> @@ -6440,7 +6447,6 @@ struct scx_sched *scx_alloc_and_add_sched(struct scx_enable_cmd *cmd,
>
> #ifdef CONFIG_EXT_SUB_SCHED
> err_free_lb_resched:
> - RCU_INIT_POINTER(ops->priv, NULL);
> free_cpumask_var(sch->stall_cpus);
> #endif
> err_free_lb_resched_cpumask:
> --
> 2.54.0
>