From nobody Sat Sep 26 08:38:29 2026 Received: from mailgw.kylinos.cn (mailgw.kylinos.cn [124.126.103.232]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE0C3345EA7 for ; Thu, 3 Sep 2026 03:57:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=124.126.103.232 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788407851; cv=none; b=K7XAVUkN2lj7HZ4Rfmkn6k+pWnblwq6bNSzYokW322+qkzki9Vdz6nOwh8Me5E3SHEhkNO1BrWZ0kZCySuIhLp4DWCyvf+WW+dUS2u6yXBuShFnuPxEvhFsJM7KGu542UkaEp8znYBdElef/ZcGthi05Au5VvoavdZQrc9OMcq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788407851; c=relaxed/simple; bh=R8MCB0fZPp2kqpX8SMDkl8QbZkpnPzGATyB+nbfhggY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=a//McO2rRACYvOwdzR1UYs8iQNq/hPr14JFc9YvCmsYwIIs3VSsw7O2pi6aTHLWaSYz9NZs/dS8tcJ1Gzxn8Tdmb3kmCdx9OC56TuIWdRNQK1++vjq+AcMHMrrSDsD8J0YGsNxRdyJvJAe5Zm8loVmFyKHF4F0nvx2GN1Qe4Ei0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=kylinos.cn; arc=none smtp.client-ip=124.126.103.232 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kylinos.cn X-UUID: 91e76e82a74b11f19a56ed5b684f684d-20260903 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.3.19,REQID:155ee8e6-6ac1-4a87-8f4c-bfc556ebb13e,IP:0,U RL:0,TC:0,Content:0,EDM:25,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION :release,TS:25 X-CID-META: VersionHash:7db8b62,CLOUDID:585e62760e82be758c00727469015eda,BulkI D:nil,BulkQuantity:0,SF:81|82|102|865|898,TC:nil,Content:0|15|50,EDM:5,IP: nil,URL:99|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV: 0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 2,SSN|SDN X-CID-BAS: 2,SSN|SDN,0,_ X-CID-FACTOR: TF_CID_SPAM_ULS,TF_CID_SPAM_SNR X-CID-RHF: D41D8CD98F00B204E9800998ECF8427E X-UUID: 91e76e82a74b11f19a56ed5b684f684d-20260903 X-User: liwanwu@kylinos.cn Received: from kylinos.cn [(10.44.16.150)] by mailgw.kylinos.cn (envelope-from ) (Generic MTA with TLSv1.3 TLS_AES_256_GCM_SHA384 256/256) with ESMTP id 1093751082; Thu, 03 Sep 2026 11:57:23 +0800 From: Wanwu Li To: tj@kernel.org Cc: arighi@nvidia.com, void@manifault.com, changwoo@igalia.com, emil@etsalapatis.com, sched-ext@lists.linux.dev, linux-kernel@vger.kernel.org, liwanwu@kylinos.cn Subject: [PATCH 1/2] sched_ext: Make scx_locked_rq() return NULL from NMI Date: Thu, 3 Sep 2026 11:57:19 +0800 Message-Id: <20260903035719.721445-1-liwanwu@kylinos.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260903032953.659847-1-liwanwu@kylinos.cn> References: <20260903032953.659847-1-liwanwu@kylinos.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" scx_locked_rq() reads the per-CPU scx_locked_rq_state, which tracks the rq locked by the context running on the CPU. Tracing progs can call kfuncs from NMI, and an NMI interrupts - rather than replaces - the context that set scx_locked_rq_state, so a non-NULL read from NMI falsely tells the caller that it holds the interrupted context's rq lock. Three "any"-category kfuncs read scx_locked_rq() on their success path and take an unsafe fast path on a non-NULL return: - scx_bpf_task_set_slice() writes p->scx.slice directly, racing update_curr_scx()'s non-atomic read-modify-write of the same field. - scx_bpf_dsq_nr_queued() resolves %SCX_DSQ_LOCAL to (scx_locked_rq() ?: this_rq()) and can report the interrupted context's local DSQ length instead of the caller's. - scx_bpf_locked_rq() hands the interrupted context's rq to the BPF program, which may then operate on it as if it owned the rq lock. Make scx_locked_rq() return NULL from NMI so that all three take their unlocked paths: scx_bpf_task_set_slice() stashes the request into the atomic p->scx.slice_oob for application under the rq lock, scx_bpf_dsq_nr_queued() falls back to this_rq(), and scx_bpf_locked_rq() reports an error and aborts the scheduler through the NMI-safe exit path. The kfuncs that take scheduler locks reject NMI calls through scx_kf_allowed_ctx() before reaching scx_locked_rq(), and the internal callers only run from struct_ops callbacks, which never run in NMI, so no other caller is affected. Suggested-by: Tejun Heo Link: https://lore.kernel.org/r/d84b31727f04e1ed0d40042ba1c09e61@kernel.org Signed-off-by: Wanwu Li --- kernel/sched/ext/internal.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/sched/ext/internal.h b/kernel/sched/ext/internal.h index a67277b0fee6..809e0ee0fd5f 100644 --- a/kernel/sched/ext/internal.h +++ b/kernel/sched/ext/internal.h @@ -2218,6 +2218,15 @@ static inline void scx_schedule_reenq_local(struct r= q *rq, u64 reenq_flags) */ static inline struct rq *scx_locked_rq(void) { + /* + * Tracing progs can call kfuncs from NMI. scx_locked_rq_state tracks + * the rq locked by the interrupted context, so a non-NULL read from + * NMI would falsely claim its lock. Return NULL from NMI so that + * callers take their unlocked paths. + */ + if (unlikely(in_nmi())) + return NULL; + return __this_cpu_read(scx_locked_rq_state); } =20 --=20 2.25.1 From nobody Sat Sep 26 08:38:29 2026 Received: from mailgw.kylinos.cn (mailgw.kylinos.cn [124.126.103.232]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FF9E2110E for ; Thu, 3 Sep 2026 03:58:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=124.126.103.232 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788407889; cv=none; b=UgF3ZKZ+w7GsHxjxw/bqGW3CQ7c90ftPl0JYsL7x5LNK7tSKjHnMUqSHrnmcXke5g92mH7sWjCb1rzqAx6NeplQN3er/HSOL7/GaGKBSbUm8nb7cInMVcFaMkZwkYvYuRhXIQGukWwJlN7+kENhY41OI511/v0Z6XvAwWWX9dgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788407889; c=relaxed/simple; bh=CXlpF52qtVFzAMuM4dYkQpB+SckVdivvQaN7BnrTPG8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YUqMB/uSxAVDe6Eu0cNYIT/Qo5oFLdyGpHzlFTOkqS6AyDOa4FiGKT0NIMU6BFiYCTcKCM89uOR/wOXQ0yBWAsS4QOk1AxfHiJ/14L+/8UHSKPpYeqwNJ9EXnm/s0iKJt7lXu/yIV7BkCvmjPQPya1tiO8zg/h7acg0FG70OxxQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn; spf=pass smtp.mailfrom=kylinos.cn; arc=none smtp.client-ip=124.126.103.232 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=kylinos.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=kylinos.cn X-UUID: a8fdb6c6a74b11f19a56ed5b684f684d-20260903 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.3.19,REQID:dc4f8f8e-66d5-42d7-889a-9c2ea0254c99,IP:0,U RL:0,TC:0,Content:-25,EDM:25,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:7db8b62,CLOUDID:015b5d99587a44c40abb399a106145f7,BulkI D:nil,BulkQuantity:0,SF:81|82|102|865|898,TC:nil,Content:0|15|50,EDM:5,IP: nil,URL:99|1,File:nil,RT:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV: 0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0 X-CID-BVR: 2,SSN|SDN X-CID-BAS: 2,SSN|SDN,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULS X-CID-RHF: D41D8CD98F00B204E9800998ECF8427E X-UUID: a8fdb6c6a74b11f19a56ed5b684f684d-20260903 X-User: liwanwu@kylinos.cn Received: from kylinos.cn [(10.44.16.150)] by mailgw.kylinos.cn (envelope-from ) (Generic MTA with TLSv1.3 TLS_AES_256_GCM_SHA384 256/256) with ESMTP id 1298296529; Thu, 03 Sep 2026 11:58:02 +0800 From: Wanwu Li To: tj@kernel.org Cc: arighi@nvidia.com, void@manifault.com, changwoo@igalia.com, emil@etsalapatis.com, sched-ext@lists.linux.dev, linux-kernel@vger.kernel.org, liwanwu@kylinos.cn Subject: [PATCH 2/2] sched_ext: Protect the idle-search scratch nodemask with irqsave Date: Thu, 3 Sep 2026 11:57:54 +0800 Message-Id: <20260903035754.722451-1-liwanwu@kylinos.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260903032953.659847-1-liwanwu@kylinos.cn> References: <20260903032953.659847-1-liwanwu@kylinos.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" pick_idle_cpu_from_online_nodes() uses the per-CPU per_cpu_unvisited nodemask as scratch while walking the online nodes, protected only by preempt_disable(). preempt_disable() does not mask IRQs and the idle kfuncs are callable from IRQ-enabled contexts, so a nested invocation on the same CPU can overwrite the mask with nodes_copy() while the interrupted invocation is still iterating it, leading to a wrong node traversal and a wrong idle CPU pick. Switch to irqsave so a nested invocation can't run on the same CPU. A stack-allocated nodemask would also close the race, but that would enlarge the diff to fix a race that is already rare (per-node idle, CONFIG_NUMA and a cross-node search all at once); irqsave is the minimal fix for the context that actually triggers it. The NMI case is deliberately not addressed: there is no legitimate reason to call pick_idle from NMI and doing so poses no crash risk, so such a caller is on its own. Suggested-by: Tejun Heo Link: https://lore.kernel.org/r/d84b31727f04e1ed0d40042ba1c09e61@kernel.org Signed-off-by: Wanwu Li --- kernel/sched/ext/idle.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/sched/ext/idle.c b/kernel/sched/ext/idle.c index d2973fb3af6d..93e2e0b2d1f8 100644 --- a/kernel/sched/ext/idle.c +++ b/kernel/sched/ext/idle.c @@ -153,7 +153,18 @@ static s32 pick_idle_cpu_from_online_nodes(const struc= t cpumask *cpus_allowed, i nodemask_t *unvisited; s32 cpu =3D -EBUSY; =20 - preempt_disable(); + /* + * @per_cpu_unvisited is per-CPU scratch and the idle kfuncs can be + * called from IRQ-enabled contexts, so mask IRQs to keep a nested + * invocation from clobbering the mask an outer invocation is still + * iterating. + * + * NMI nesting is not handled: there is no legitimate reason to call + * pick_idle from NMI and doing so poses no crash risk, so such a + * caller is on its own. + */ + guard(irqsave)(); + unvisited =3D this_cpu_ptr(&per_cpu_unvisited); =20 /* @@ -183,7 +194,6 @@ static s32 pick_idle_cpu_from_online_nodes(const struct= cpumask *cpus_allowed, i if (cpu >=3D 0) break; } - preempt_enable(); =20 return cpu; } --=20 2.25.1