]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
sched_ext: Reject setting disallow from init_task outside the enable path
authorTejun Heo <tj@kernel.org>
Thu, 16 Jul 2026 20:43:25 +0000 (10:43 -1000)
committerTejun Heo <tj@kernel.org>
Sat, 18 Jul 2026 07:28:57 +0000 (21:28 -1000)
The p->scx.disallow revert assumes the root enable path, where the switching
loop reads the reverted policy right afterwards and leaves the task off SCX.
The sub-scheduler disable path also reaches it when re-initializing the
returned tasks on a root parent. Nothing reads the policy there: the task is
enabled on root anyway and keeps running on the ext class with a silently
rewritten policy.

Kill the sched instead, matching the fork and non-root branches, and update
the disallow documentation, which equated !fork with the load path and
pointed at a stale debugfs path for nr_rejected.

Fixes: 337ec00b1d9c ("sched_ext: Implement cgroup sub-sched enabling and disabling")
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
include/linux/sched/ext.h
kernel/sched/ext/ext.c

index 20b2343aa344be34131a33ea52ba60e811b642af..87e353f7e0112e811e1d53d6ec44be6f570a848e 100644 (file)
@@ -244,11 +244,11 @@ struct sched_ext_entity {
         * to %SCHED_EXT with -%EACCES.
         *
         * Can be set from ops.init_task() while the BPF scheduler is being
-        * loaded (!scx_init_task_args->fork). If set and the task's policy is
-        * already %SCHED_EXT, the task's policy is rejected and forcefully
-        * reverted to %SCHED_NORMAL. The number of such events are reported
-        * through /sys/kernel/debug/sched_ext::nr_rejected. Setting this flag
-        * during fork is not allowed.
+        * loaded. If set and the task's policy is already %SCHED_EXT, the
+        * task's policy is rejected and forcefully reverted to %SCHED_NORMAL.
+        * The number of such events are reported through
+        * /sys/kernel/sched_ext/nr_rejected. Setting this flag from any other
+        * ops.init_task() invocation, such as during fork, fails the scheduler.
         */
        bool                    disallow;       /* reject switching into SCX */
 
index e3fa7b2fac9dfc66bee17b031b5d11d2b0775158..46f135bddd460b1221ca97420c705a5a848465dd 100644 (file)
@@ -3606,6 +3606,9 @@ static int __scx_init_task(struct scx_sched *sch, struct task_struct *p, bool fo
                } else if (unlikely(fork)) {
                        scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] during fork",
                                  p->comm, p->pid);
+               } else if (unlikely(scx_enable_state() != SCX_ENABLING)) {
+                       scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] outside the enable path",
+                                 p->comm, p->pid);
                } else {
                        struct rq *rq;
                        struct rq_flags rf;