All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Tejun Heo" <tj@kernel.org>
Cc: sched-ext@lists.linux.dev
Subject: Re: [PATCH v4 sched_ext/for-7.3 39/40] tools/sched_ext: scx_qmap - Expand hierarchical sub-scheduling
Date: Wed, 08 Jul 2026 22:03:52 +0000	[thread overview]
Message-ID: <20260708220353.392CD1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260708212429.3405787-40-tj@kernel.org>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Medium] `dispatch_highpri()` ignores hierarchical CID delegation, allowing the parent scheduler to dispatch its high-priority tasks to CPUs exclusively delegated to child schedulers.
- [Medium] Unsynchronized modification of `qa.sub_sched_ctxs` array during `qmap_sub_attach` and `qmap_sub_detach` causes data races with partition rebuilding.
- [Medium] Double read (TOCTOU race) of `qa.sub_sched_ctxs[owner].cgroup_id` in `qmap_dispatch` can pass 0 to `scx_bpf_sub_dispatch`.
- [Medium] Userspace `feed_weights()` overwrites child weight with stale data due to concurrent sub-scheduler detach/attach (TOCTOU).
- [Medium] Negative error codes from `scx_bpf_task_cid()` are used directly as array and bitmask indices without bounds checking.
--

--- Patch [39]: [PATCH v4 sched_ext/for-7.3 39/40] tools/sched_ext: scx_qmap - Expand hierarchical sub-scheduling ---
commit d8ef8ae12fe2035b97cf3007ec38b1e29eef5a35
Author: Tejun Heo <tj@kernel.org>

tools/sched_ext: scx_qmap - Expand hierarchical sub-scheduling

This commit expands the scx_qmap test scheduler to demonstrate hierarchical
sub-scheduling. It allows a parent to delegate exclusive and shared CPUs
(cids) to child cgroups based on cpu.weight.

> diff --git a/tools/sched_ext/scx_qmap.bpf.c b/tools/sched_ext/scx_qmap.bpf.c
> index f6cfe63425d36..5b1c3b10ac746 100644
> --- a/tools/sched_ext/scx_qmap.bpf.c
> +++ b/tools/sched_ext/scx_qmap.bpf.c
[ ... ]
> @@ -416,7 +476,8 @@ void BPF_STRUCT_OPS(qmap_enqueue, struct task_struct *p, u64 enq_flags)
>  	 */
>  	if (taskc->force_local) {
>  		taskc->force_local = false;
> -		scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL, slice_ns, enq_flags);
> +		scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL, slice_ns,
> +				   enq_flags | needs_immed(scx_bpf_task_cid(p)));
>  		return;
>  	}

[Severity: Medium]
The core kernel kfunc scx_bpf_task_cid() can return an s32 negative error 
code (such as -EINVAL) if the CID table is uninitialized or the CPU mapping 
is missing.

When this return value is passed directly to needs_immed(), the negative 
value is used to index into the qa.cid_shared array without bounds checking. 
Can this lead to an out-of-bounds memory read within the BPF arena?

Similarly, in pick_direct_dispatch_cid(), prev_cid is passed to bitmask 
operations like cmask_test_and_clear() and cmask_test(). Should there be a 
check to ensure the returned CID is >= 0 before using it as an index?

[ ... ]
> @@ -541,7 +604,7 @@ static bool dispatch_highpri(bool from_timer)
[ ... ]
>  		if (scx_bpf_dsq_move(BPF_FOR_EACH_ITER, p, SCX_DSQ_LOCAL_ON | cid,
> -				     SCX_ENQ_PREEMPT)) {
> +				     SCX_ENQ_PREEMPT | needs_immed(cid))) {
>  			if (cid == this_cid) {
>  				dispatched = true;

[Severity: Medium]
In qmap_dispatch(), dispatch_highpri(false) is called unconditionally before 
checking qa.part.cid_owner. 

Inside dispatch_highpri(), tasks are moved to the local DSQ without verifying 
if the target cid is restricted by qa.self_cids.mask.

Does this sequence allow the parent scheduler's high-priority tasks to be 
dispatched to CPUs that are exclusively delegated to child sub-schedulers, 
thereby violating the delegation policy?

[ ... ]
> @@ -567,12 +630,35 @@ void BPF_STRUCT_OPS(qmap_dispatch, s32 cid, struct task_struct *prev)
[ ... ]
> +	} else if (owner >= 0 && owner < MAX_SUB_SCHEDS &&
> +		   qa.sub_sched_ctxs[owner].cgroup_id) {
> +		if (scx_bpf_sub_dispatch(qa.sub_sched_ctxs[owner].cgroup_id))
> +			__sync_fetch_and_add(&qa.sub_sched_ctxs[owner].nr_dsps, 1);
> +		return;
> +	}

[Severity: Medium]
The cgroup_id is read twice without protection here. The first read evaluates 
qa.sub_sched_ctxs[owner].cgroup_id as a condition for the if statement. 

Immediately after, the same memory location is re-read to be passed to 
scx_bpf_sub_dispatch().

Because qa.sub_sched_ctxs can be concurrently modified by qmap_sub_detach() 
without locks, could the value become 0 between the condition check and the 
function call, causing scx_bpf_sub_dispatch() to be invoked with an invalid 
cgroup ID?

[ ... ]
> @@ -1219,15 +1831,37 @@ void BPF_STRUCT_OPS(qmap_sub_detach, struct scx_sub_detach_args *args)
>  	s32 i;
>  
>  	for (i = 0; i < MAX_SUB_SCHEDS; i++) {
> -		if (qa.sub_sched_cgroup_ids[i] == args->ops->sub_cgroup_id) {
> -			qa.sub_sched_cgroup_ids[i] = 0;
> -			bpf_printk("detaching sub-sched[%d] on %s",
> -				   i, args->cgroup_path);
> -			break;
> -		}
> +		if (qa.sub_sched_ctxs[i].cgroup_id != args->ops->sub_cgroup_id)
> +			continue;
> +
> +		qa.sub_sched_ctxs[i].cgroup_id = 0;
> +		qa.sub_sched_ctxs[i].weight = 100;
> +		cmask_init(&qa.sub_sched_ctxs[i].granted_cids.mask, 0, qa.nr_cids);
> +		qa.nr_sub_scheds--;
> +		bpf_printk("detaching sub-sched[%d] on %s", i, args->cgroup_path);
> +		redistribute();
> +		break;
>  	}
>  }

[Severity: Medium]
During qmap_sub_detach() and qmap_sub_attach(), the global array 
qa.sub_sched_ctxs is modified directly (clearing cgroup_id and zeroing 
granted_cids.mask via cmask_init). 

These modifications occur without acquiring the part_try_start() / 
part_end() synchronization guard used in apply_partition() and rr_advance(). 

If apply_partition() runs concurrently from the timer callback or sys_bpf 
calls, can this cause a data race that corrupts the partition state tracking 
masks?

> diff --git a/tools/sched_ext/scx_qmap.c b/tools/sched_ext/scx_qmap.c
> index 9124183bffecc..1efffaaa8fe85 100644
> --- a/tools/sched_ext/scx_qmap.c
> +++ b/tools/sched_ext/scx_qmap.c
[ ... ]
> @@ -62,6 +92,213 @@ static void sigint_handler(int dummy)
[ ... ]
> +/* read each direct child's cpu.weight into the arena, true if any changed */
> +static bool feed_weights(struct qmap_arena *qa)
> +{
> +	bool changed = false;
> +	int i;
> +
> +	for (i = 0; i < MAX_SUB_SCHEDS; i++) {
> +		u64 cgid = qa->sub_sched_ctxs[i].cgroup_id;
> +		u32 w;
> +
> +		if (!cgid)
> +			continue;
> +		w = read_cgroup_weight(cgid);
> +		if (w && w != qa->sub_sched_ctxs[i].weight) {
> +			qa->sub_sched_ctxs[i].weight = w;
> +			changed = true;
> +		}
> +	}
> +	return changed;
> +}

[Severity: Medium]
In feed_weights(), userspace reads the cgroup_id from the BPF arena memory 
and then performs a blocking sysfs read via read_cgroup_weight().

During this file I/O operation, the original child cgroup could detach and a 
new one could attach to the same slot. Will the userspace daemon then 
blindly overwrite the newly attached child's qa->sub_sched_ctxs[i].weight 
with the stale weight read from the previous child's sysfs file?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260708212429.3405787-1-tj@kernel.org?part=39

  reply	other threads:[~2026-07-08 22:03 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-08 21:23 [PATCHSET v4 sched_ext/for-7.3] sched_ext: Capability-based CPU delegation for sub-schedulers Tejun Heo
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 01/40] sched_ext: Record an error on errno-only sub-enable failure Tejun Heo
2026-07-09 20:37   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 02/40] sched_ext: Fix premature ops->priv publication in scx_alloc_and_add_sched() Tejun Heo
2026-07-09 20:38   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 03/40] tools/sched_ext: scx - Fix cmask_subset(), cmask_equal() and cmask_weight() Tejun Heo
2026-07-09 20:39   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 04/40] sched_ext: Use READ_ONCE/WRITE_ONCE in cmask word ops and drop _RACY variants Tejun Heo
2026-07-09 20:39   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 05/40] sched_ext: Add SCX_CALL_CID_OP_TASK() for cid-form op dispatch Tejun Heo
2026-07-09 20:41   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 06/40] sched_ext: Rename extra_enq_flags to remote_activate_enq_flags Tejun Heo
2026-07-09 20:41   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 07/40] tools/sched_ext: scx_qmap - Use bare u64/u32/s32 integer types Tejun Heo
2026-07-09 20:42   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 08/40] sched_ext: Reject direct slice and dsq_vtime writes for cid-form schedulers Tejun Heo
2026-07-08 21:41   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-09 20:56   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 09/40] sched_ext: Make scx_bpf_kick_cid() return void Tejun Heo
2026-07-09 20:57   ` Andrea Righi
2026-07-08 21:23 ` [PATCH v4 sched_ext/for-7.3 10/40] sched_ext: Make the kick machinery per-sched Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 11/40] sched_ext: Add ops.init_cids() to finalize the cid layout before init Tejun Heo
2026-07-08 21:54   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 12/40] sched_ext: Add CID sharding Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 13/40] sched_ext: Add shard boundaries to scx_bpf_cid_override() Tejun Heo
2026-07-08 21:47   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 14/40] sched_ext: Defer scx_sched kobj sysfs add into the enable workfns Tejun Heo
2026-07-08 21:47   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 15/40] sched_ext: Add per-shard scx_sched storage scaffolding Tejun Heo
2026-07-08 21:44   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 16/40] sched_ext: Add scx_cmask_ref for validated arena cmask access Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 17/40] sched_ext: Build the set_cmask scratch from trusted geometry Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 18/40] sched_ext: RCU-protect the sub-sched tree's children/sibling lists Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 19/40] sched_ext: Add scx_skip_subtree_pre() Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 20/40] sched_ext: Stop resolving a disabled scheduler's programs Tejun Heo
2026-07-08 21:55   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 21/40] sched_ext: Add per-shard cap delegation for sub-schedulers Tejun Heo
2026-07-08 22:00   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 22/40] sched_ext: Add coalescing sub_caps_updated() notifier " Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 23/40] sched_ext: Maintain per-cpu effective cap copies for single-read checks Tejun Heo
2026-07-08 22:03   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 24/40] sched_ext: Add sub_ecaps_updated() effective-cap change notifier Tejun Heo
2026-07-08 22:02   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 25/40] sched_ext: Generalize local-DSQ handling to rq-owned DSQs Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 26/40] sched_ext: Add reject DSQ for cap-rejected dispatches Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 27/40] sched_ext: Add the SCX_CAP_ENQ_IMMED cap Tejun Heo
2026-07-08 21:56   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 28/40] sched_ext: Assign a unique id to each scheduler instance Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 29/40] sched_ext: Route task slice writes through set_task_slice() Tejun Heo
2026-07-08 21:53   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 30/40] sched_ext: Track the cpu a task is runnable on Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 31/40] sched_ext: Tie cpu occupancy to SCX_CAP_BASE through the task slice Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 32/40] sched_ext: Add the SCX_CAP_ENQ cap Tejun Heo
2026-07-08 22:00   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 33/40] sched_ext: Gate kicks on SCX_CAP_BASE and preemption on SCX_CAP_PREEMPT Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 34/40] sched_ext: Authorize remote-move inserts against the placing scheduler Tejun Heo
2026-07-08 22:04   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-09 20:09   ` Andrea Righi
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 35/40] sched_ext: Route ops.update_idle() to sub-schedulers and re-notify owed scheds Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 36/40] sched_ext: Replay ecaps notifications suppressed by bypass Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 37/40] sched_ext: Add scx_bpf_sub_kill() to evict a child sub-scheduler Tejun Heo
2026-07-08 22:11   ` sashiko-bot
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 38/40] tools/sched_ext: Add three-mask cmask intersection iterator Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 39/40] tools/sched_ext: scx_qmap - Expand hierarchical sub-scheduling Tejun Heo
2026-07-08 22:03   ` sashiko-bot [this message]
2026-07-09 22:28     ` Tejun Heo
2026-07-08 21:24 ` [PATCH v4 sched_ext/for-7.3 40/40] tools/sched_ext: scx_qmap - Add sub-sched cap fault injection Tejun Heo
2026-07-09 21:18 ` [PATCHSET v4 sched_ext/for-7.3] sched_ext: Capability-based CPU delegation for sub-schedulers Tejun Heo
2026-07-09 22:13 ` 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=20260708220353.392CD1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=sched-ext@lists.linux.dev \
    --cc=tj@kernel.org \
    /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.