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 v2 sched_ext/for-7.3 16/36] sched_ext: Build the set_cmask scratch from trusted geometry
Date: Mon, 06 Jul 2026 01:59:26 +0000	[thread overview]
Message-ID: <20260706015927.2C4C81F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260706014058.439853-17-tj@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] A concurrent BPF write to `alloc_words` triggers a kernel panic via the `__counted_by` compiler-inserted bounds check.
- [High] A BPF scheduler of cid-form can trigger a NULL pointer dereference (with per-cpu offset) and arbitrary memory corruption by defining `set_cmask` without providing an arena map.
--

commit dc47d369970061036c6652d545aa537ea7f9145d
Author: Tejun Heo <tj@kernel.org>

sched_ext: Build the set_cmask scratch from trusted geometry

This commit modifies scx_call_op_set_cpumask() to build the per-cpu cmask
from trusted kernel geometry rather than reading the BPF-writable arena
header. This prevents potential out-of-bounds writes if a concurrent BPF
program modifies the header.

> diff --git a/kernel/sched/ext/cid.c b/kernel/sched/ext/cid.c
> index 42fc8348b3b4c..465e4e7b06197 100644
> --- a/kernel/sched/ext/cid.c
> +++ b/kernel/sched/ext/cid.c

[ ... ]

> @@ -1029,6 +1061,44 @@ void scx_cmask_ref_copy(const struct scx_cmask_ref *ref, const struct scx_cmask
>  		       src->bits, src->base, src->nr_cids, CMASK_OP2_REF_COPY);
>  }
>  
> +/**
> + * scx_cmask_ref_from_cpumask - Populate @ref's arena cmask from a cpumask
> + * @ref: kern-bound ref, see scx_cmask_ref_init_kern()
> + * @cpumask: cpus to translate into cids
> + *
> + * Write @ref's active range one word at a time, setting each cid's bit when
> + * its cpu is in @cpumask. Offsets and length come from @ref's trusted geometry
> + * and stores use WRITE_ONCE since BPF may read concurrently, so the arena
> + * header is never read.
> + */
> +void scx_cmask_ref_from_cpumask(const struct scx_cmask_ref *ref,
> +				const struct cpumask *cpumask)
> +{
> +	struct scx_cmask *m = ref->src;
> +	u32 base = ref->base, nr_cids = ref->nr_cids;
> +	u32 wi, nr_words;
> +
> +	if (!nr_cids)
> +		return;
> +
> +	nr_words = (base + nr_cids - 1) / 64 - base / 64 + 1;
> +	for (wi = 0; wi < nr_words; wi++) {
> +		u32 word_first_cid = (base / 64 + wi) * 64;
> +		u64 word = 0;
> +		u32 bit;
> +
> +		for (bit = 0; bit < 64; bit++) {
> +			u32 cid = word_first_cid + bit;
> +
> +			if (cid < base || cid >= base + nr_cids)
> +				continue;
> +			if (cpumask_test_cpu(__scx_cid_to_cpu(cid), cpumask))
> +				word |= BIT_U64(bit);
> +		}
> +		WRITE_ONCE(m->bits[wi], word);

[Severity: High]
This isn't a bug introduced by this patch, but does this write still
implicitly read the BPF-writable arena header due to the __counted_by
attribute on the bits array in struct scx_cmask?

The struct scx_cmask definition in kernel/sched/ext/types.h is:
    struct scx_cmask {
        u32 base;
        u32 nr_cids;
        u32 alloc_words;
        u64 bits[] __counted_by(alloc_words);
    };

The __counted_by annotation instructs the compiler to insert runtime bounds
checks. Doesn't this mean the compiler will implicitly read m->alloc_words
during the WRITE_ONCE access?

If a concurrent BPF program modifies m->alloc_words to 0 in its BPF arena
while the kernel executes scx_cmask_ref_from_cpumask(), could this trigger a
kernel panic via the compiler-inserted bounds check?

> +	}
> +}
> +

[ ... ]

> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index a5e782147bf40..8ee980f822aac 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -412,12 +412,15 @@ static inline void scx_call_op_set_cpumask(struct scx_sched *sch, struct rq *rq,
>  {
>  	if (scx_is_cid_type()) {
>  		struct scx_cmask *kern_va = *this_cpu_ptr(sch->set_cmask_scratch);

[Severity: High]
This isn't a bug introduced by this patch, but can this dereference a NULL
pointer with a per-cpu offset if a BPF scheduler defines the set_cmask
callback without providing an arena map?

In scx_set_cmask_scratch_alloc(), if the arena pool is missing:
    if (!sch->is_cid_type || !sch->arena_pool)
        return 0;

This leaves sch->set_cmask_scratch as NULL instead of returning an error.

When scx_call_op_set_cpumask() calls this_cpu_ptr() on a NULL pointer, it
resolves to the raw per_cpu_offset, leading to reading a garbage pointer
which is then passed to scx_cmask_ref_init_kern() causing memory corruption.

Should the scheduler validate the presence of the arena map?

> +		struct scx_cmask_ref ref;
> +
>  		/*
> -		 * Build the per-CPU arena cmask and hand BPF its arena address.
> -		 * Caller holds the rq lock with IRQs disabled, which makes us
> -		 * the sole user of the scratch area.
> +		 * Build the per-cpu arena cmask from kernel geometry via @ref,
> +		 * never reading its BPF-writable header, and hand BPF the arena
> +		 * address. The rq lock makes this cpu the sole kernel writer.
>  		 */
> -		scx_cpumask_to_cmask(cpumask, kern_va);
> +		scx_cmask_ref_init_kern(sch, kern_va, 0, num_possible_cpus(), &ref);
> +		scx_cmask_ref_from_cpumask(&ref, cpumask);
>  		SCX_CALL_CID_OP_TASK(sch, set_cmask, rq, task,
>  				     scx_kaddr_to_arena(sch, kern_va));
>  	} else {

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

  reply	other threads:[~2026-07-06  1:59 UTC|newest]

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