All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: David Vernet <void@manifault.com>,
	Andrea Righi <arighi@nvidia.com>,
	Changwoo Min <changwoo@igalia.com>
Cc: sched-ext@lists.linux.dev, Emil Tsalapatis <emil@etsalapatis.com>,
	linux-kernel@vger.kernel.org, Tejun Heo <tj@kernel.org>
Subject: [PATCH v5 sched_ext/for-7.3 12/33] sched_ext: Stop resolving a disabled scheduler's programs
Date: Thu,  9 Jul 2026 12:50:20 -1000	[thread overview]
Message-ID: <20260709225041.1695495-13-tj@kernel.org> (raw)
In-Reply-To: <20260709225041.1695495-1-tj@kernel.org>

A scheduler's BPF programs can outlive it. A timer it armed or a tracing
program it loaded can fire after ops.exit() has run, before the programs are
unloaded, and scx_prog_sched() still resolves the program to its scheduler
through ops->priv. Harmless while kfuncs touch only lifetime-stable state,
but a hazard once a kfunc reads global state a newly loaded scheduler can
change underneath it.

Add scx_sched->dead, set right after ops.exit() and drained with
synchronize_rcu(). It follows exit() rather than preceding it so exit()'s own
kfunc calls still resolve to @sch. scx_prog_sched() returns NULL for a dead
scheduler, so every kfunc's existing !sch bail rejects it at one choke
point.

v2: Check dead in the CONFIG_EXT_SUB_SCHED=n scx_prog_sched() too. (sashiko AI)

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 kernel/sched/ext/ext.c      |  8 ++++++++
 kernel/sched/ext/internal.h | 19 +++++++++++++++----
 kernel/sched/ext/sub.c      |  9 +++++++++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index ba83fe832343..fbf1c3477140 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -5733,6 +5733,14 @@ static void scx_root_disable(struct scx_sched *sch)
 	if (sch->ops.exit)
 		SCX_CALL_OP(sch, exit, NULL, sch->exit_info);
 
+	/*
+	 * @sch's non-ops programs such as timers and tracers can fire after
+	 * ops.exit(). Now that exit is complete, stop scx_prog_sched() from
+	 * resolving to @sch and drain in-flight resolvers.
+	 */
+	WRITE_ONCE(sch->dead, true);
+	synchronize_rcu();
+
 	scx_unlink_sched(sch);
 
 	/*
diff --git a/kernel/sched/ext/internal.h b/kernel/sched/ext/internal.h
index 5b18c4192c62..4452aac89b14 100644
--- a/kernel/sched/ext/internal.h
+++ b/kernel/sched/ext/internal.h
@@ -1202,6 +1202,7 @@ struct scx_sched {
 		struct sched_ext_ops_cid	ops_cid;
 	};
 	bool			is_cid_type;	/* true if registered via bpf_sched_ext_ops_cid */
+	bool			dead;		/* set after ops.exit(), gates scx_prog_sched() */
 
 	/*
 	 * Arena map auto-discovered from member progs at struct_ops attach.
@@ -1976,14 +1977,20 @@ static inline bool scx_task_on_sched(struct scx_sched *sch,
 static inline struct scx_sched *scx_prog_sched(const struct bpf_prog_aux *aux)
 {
 	struct sched_ext_ops *ops;
-	struct scx_sched *root;
+	struct scx_sched *sch, *root;
 
 	ops = bpf_prog_get_assoc_struct_ops(aux);
-	if (likely(ops))
-		return rcu_dereference_all(ops->priv);
+	if (likely(ops)) {
+		sch = rcu_dereference_all(ops->priv);
+		if (sch && unlikely(READ_ONCE(sch->dead)))
+			return NULL;
+		return sch;
+	}
 
 	root = rcu_dereference_all(scx_root);
 	if (root) {
+		if (unlikely(READ_ONCE(root->dead)))
+			return NULL;
 		/*
 		 * COMPAT-v6.19: Schedulers built before sub-sched support was
 		 * introduced may have unassociated non-struct_ops programs.
@@ -2035,7 +2042,11 @@ static inline bool scx_task_on_sched(struct scx_sched *sch,
 
 static inline struct scx_sched *scx_prog_sched(const struct bpf_prog_aux *aux)
 {
-	return rcu_dereference_all(scx_root);
+	struct scx_sched *root = rcu_dereference_all(scx_root);
+
+	if (root && unlikely(READ_ONCE(root->dead)))
+		return NULL;
+	return root;
 }
 
 static inline struct scx_sched *scx_parent(struct scx_sched *sch) { return NULL; }
diff --git a/kernel/sched/ext/sub.c b/kernel/sched/ext/sub.c
index 17ed0d28f383..017225ad492f 100644
--- a/kernel/sched/ext/sub.c
+++ b/kernel/sched/ext/sub.c
@@ -344,6 +344,15 @@ void scx_sub_disable(struct scx_sched *sch)
 
 	if (sch->ops.exit)
 		SCX_CALL_OP(sch, exit, NULL, sch->exit_info);
+
+	/*
+	 * @sch's non-ops programs such as timers and tracers can fire after
+	 * ops.exit(). Now that exit is complete, stop scx_prog_sched() from
+	 * resolving to @sch and drain in-flight resolvers.
+	 */
+	WRITE_ONCE(sch->dead, true);
+	synchronize_rcu();
+
 	if (sch->sub_kset)
 		kobject_del(&sch->sub_kset->kobj);
 	/* not added if enable failed before scx_sched_sysfs_add() */
-- 
2.55.0


  parent reply	other threads:[~2026-07-09 22:50 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-09 22:50 [PATCHSET v5 sched_ext/for-7.3] sched_ext: Capability-based CPU delegation for sub-schedulers Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 01/33] sched_ext: Assert per-task ops run on the task's owner Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 02/33] sched_ext: Make the kick machinery per-sched Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 03/33] sched_ext: Add ops.init_cids() to finalize the cid layout before init Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 04/33] sched_ext: Add CID sharding Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 05/33] sched_ext: Add shard boundaries to scx_bpf_cid_override() Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 06/33] sched_ext: Defer scx_sched kobj sysfs add into the enable workfns Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 07/33] sched_ext: Add per-shard scx_sched storage scaffolding Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 08/33] sched_ext: Add scx_cmask_ref for validated arena cmask access Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 09/33] sched_ext: Build the set_cmask scratch from trusted geometry Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 10/33] sched_ext: RCU-protect the sub-sched tree's children/sibling lists Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 11/33] sched_ext: Add scx_skip_subtree_pre() Tejun Heo
2026-07-09 22:50 ` Tejun Heo [this message]
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 13/33] sched_ext: Add per-shard cap delegation for sub-schedulers Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 14/33] sched_ext: Add coalescing sub_caps_updated() notifier " Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 15/33] sched_ext: Maintain per-cpu effective cap copies for single-read checks Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 16/33] sched_ext: Add sub_ecaps_updated() effective-cap change notifier Tejun Heo
2026-07-14  6:00   ` Andrea Righi
2026-07-14  8:07     ` Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 17/33] sched_ext: Generalize local-DSQ handling to rq-owned DSQs Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 18/33] sched_ext: Add reject DSQ for cap-rejected dispatches Tejun Heo
2026-07-14  6:49   ` Andrea Righi
2026-07-14  8:08     ` Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 19/33] sched_ext: Add SCX_ENQ_IGNORE_CAPS for in-place restore Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 20/33] sched_ext: Add the SCX_CAP_ENQ_IMMED cap Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 21/33] sched_ext: Assign a unique id to each scheduler instance Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 22/33] sched_ext: Route task slice writes through set_task_slice() Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 23/33] sched_ext: Track the cpu a task is runnable on Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 24/33] sched_ext: Tie cpu occupancy to SCX_CAP_BASE through the task slice Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 25/33] sched_ext: Add the SCX_CAP_ENQ cap Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 26/33] sched_ext: Gate kicks on SCX_CAP_BASE and preemption on SCX_CAP_PREEMPT Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 27/33] sched_ext: Authorize remote-move inserts against the placing scheduler Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 28/33] sched_ext: Route ops.update_idle() to sub-schedulers and re-notify owed scheds Tejun Heo
2026-07-14  6:18   ` Andrea Righi
2026-07-14  8:08     ` Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 29/33] sched_ext: Replay ecaps notifications suppressed by bypass Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 30/33] sched_ext: Add scx_bpf_sub_kill() to evict a child sub-scheduler Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 31/33] tools/sched_ext: Add three-mask cmask intersection iterator Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 32/33] tools/sched_ext: scx_qmap - Expand hierarchical sub-scheduling Tejun Heo
2026-07-09 22:50 ` [PATCH v5 sched_ext/for-7.3 33/33] tools/sched_ext: scx_qmap - Add sub-sched cap fault injection Tejun Heo
2026-07-14  7:10 ` [PATCHSET v5 sched_ext/for-7.3] sched_ext: Capability-based CPU delegation for sub-schedulers Andrea Righi
2026-07-14  8:07   ` Tejun Heo
2026-07-14  8:27 ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260709225041.1695495-13-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=arighi@nvidia.com \
    --cc=changwoo@igalia.com \
    --cc=emil@etsalapatis.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sched-ext@lists.linux.dev \
    --cc=void@manifault.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.