* [PATCH v2] sched/mmcid: Synchronize exec MM teardown with affinity updates
@ 2026-11-08 13:26 Weiming Shi
2026-11-08 13:33 ` Mathieu Desnoyers
0 siblings, 1 reply; 3+ messages in thread
From: Weiming Shi @ 2026-11-08 13:26 UTC (permalink / raw)
To: Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot,
Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
Valentin Schneider, K Prateek Nayak
Cc: linux-kernel, Marco Elver, Mathieu Desnoyers,
co+cab19e2ebe4d535a, Xiang Mei, Weiming Shi, stable
set_cpus_allowed_common() passes a remote task's p->mm to
mm_update_cpus_allowed(), but the scheduler locks do not stabilize that
pointer against exec. A same-owner sched_setaffinity() can race the target
replacing and freeing its old mm. Current kernels are only incidentally
serialized by futex_exec_done() taking p->pi_lock when CONFIG_FUTEX=y;
valid CONFIG_FUTEX=n builds remain vulnerable.
BUG: KASAN: slab-use-after-free in set_cpus_allowed_common (kernel/sched/core.c:10835 kernel/sched/core.c:2829)
Read of size 4 at addr ffff88810991b04c by task poc/5127
Call Trace:
set_cpus_allowed_common (kernel/sched/core.c:10835 kernel/sched/core.c:2829)
set_cpus_allowed_fair (kernel/sched/fair.c:10046)
__set_cpus_allowed_ptr_locked (kernel/sched/core.c:2842 kernel/sched/core.c:3224)
__set_cpus_allowed_ptr (kernel/sched/core.c:3258)
__sched_setaffinity (kernel/sched/syscalls.c:1161)
sched_setaffinity (kernel/sched/syscalls.c:1239)
__x64_sys_sched_setaffinity (kernel/sched/syscalls.c:1275)
do_syscall_64 (arch/x86/entry/syscall_64.c:84)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
Freed by task 5128:
kmem_cache_free (mm/slub.c:6757)
__mmput (kernel/fork.c:1204)
mmput (kernel/fork.c:1215)
setup_new_exec (fs/exec.c:1395)
load_elf_binary (fs/binfmt_elf.c:1024)
bprm_execve (fs/exec.c:1865)
do_execveat_common.isra.0 (fs/exec.c:1963)
__x64_sys_execve (fs/exec.c:2036)
do_syscall_64 (arch/x86/entry/syscall_64.c:84)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
After exec publishes the new p->mm, acquire and release the task's runqueue
lock before the old mm can be dropped. Affinity updates already hold that
lock across set_cpus_allowed_common(), so the barrier waits for any update
that loaded the old mm. Updates that start afterwards observe the new mm.
This keeps allowed-mask updates synchronous, including transient affinity
expansions, without changing the MM-CID fork, exit, or scheduling paths.
This change was developed with assistance from an LLM.
Fixes: 7e019dcc470f ("sched: Improve cache locality of RSEQ concurrency IDs for intermittent workloads")
Cc: stable@vger.kernel.org
Reported-by: <co+cab19e2ebe4d535a@bugs.sh>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
Changes in v2:
- Replace the schedule-in deferral with an exec-side runqueue-lock barrier.
- Keep affinity expansions synchronous, including expansions narrowed before
the next schedule-in.
- Avoid changes to the MM-CID fork, exit, and scheduling state machine.
fs/exec.c | 1 +
include/linux/sched.h | 2 ++
kernel/sched/core.c | 6 ++++++
3 files changed, 9 insertions(+)
diff --git a/fs/exec.c b/fs/exec.c
index 8d2b14e1d455..2e1cac6a3de7 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -905,6 +905,7 @@ static int exec_mmap(struct linux_binprm *bprm)
BUG_ON(active_mm != old_mm);
/* Defer teardown to setup_new_exec(), outside the exec locks. */
bprm->old_mm = old_mm;
+ sched_mm_cid_exec_mmap(tsk);
} else {
mmdrop_lazy_tlb(active_mm);
}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1c93da75226e..9b3d4d609273 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2358,6 +2358,7 @@ static __always_inline void alloc_tag_restore(struct alloc_tag *tag, struct allo
#ifdef CONFIG_SCHED_MM_CID
void sched_mm_cid_before_execve(struct task_struct *t);
void sched_mm_cid_after_execve(struct task_struct *t);
+void sched_mm_cid_exec_mmap(struct task_struct *t);
void sched_mm_cid_exit(struct task_struct *t);
static __always_inline int task_mm_cid(struct task_struct *t)
{
@@ -2366,6 +2367,7 @@ static __always_inline int task_mm_cid(struct task_struct *t)
#else
static inline void sched_mm_cid_before_execve(struct task_struct *t) { }
static inline void sched_mm_cid_after_execve(struct task_struct *t) { }
+static inline void sched_mm_cid_exec_mmap(struct task_struct *t) { }
static inline void sched_mm_cid_exit(struct task_struct *t) { }
static __always_inline int task_mm_cid(struct task_struct *t)
{
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 04b62c16fa8c..c9fc8c1cd46f 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -11128,6 +11128,12 @@ void sched_mm_cid_after_execve(struct task_struct *t)
sched_mm_cid_fork(t);
}
+/* Wait for affinity updates that may still be using the old MM. */
+void sched_mm_cid_exec_mmap(struct task_struct *t)
+{
+ guard(task_rq_lock)(t);
+}
+
static void mm_cid_work_fn(struct work_struct *work)
{
struct mm_struct *mm = container_of(work, struct mm_struct, mm_cid.work);
--
2.56.0
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH v2] sched/mmcid: Synchronize exec MM teardown with affinity updates
2026-11-08 13:26 [PATCH v2] sched/mmcid: Synchronize exec MM teardown with affinity updates Weiming Shi
@ 2026-11-08 13:33 ` Mathieu Desnoyers
2026-11-08 14:23 ` Weiming Shi
0 siblings, 1 reply; 3+ messages in thread
From: Mathieu Desnoyers @ 2026-11-08 13:33 UTC (permalink / raw)
To: Weiming Shi, Ingo Molnar, Peter Zijlstra, Juri Lelli,
Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
Mel Gorman, Valentin Schneider, K Prateek Nayak
Cc: linux-kernel, Marco Elver, co+cab19e2ebe4d535a, Xiang Mei, stable
On 2026-11-08 08:26, Weiming Shi wrote:
> set_cpus_allowed_common() passes a remote task's p->mm to
> mm_update_cpus_allowed(), but the scheduler locks do not stabilize that
> pointer against exec. A same-owner sched_setaffinity() can race the target
> replacing and freeing its old mm. Current kernels are only incidentally
> serialized by futex_exec_done() taking p->pi_lock when CONFIG_FUTEX=y;
> valid CONFIG_FUTEX=n builds remain vulnerable.
>
> BUG: KASAN: slab-use-after-free in set_cpus_allowed_common (kernel/sched/core.c:10835 kernel/sched/core.c:2829)
> Read of size 4 at addr ffff88810991b04c by task poc/5127
> Call Trace:
> set_cpus_allowed_common (kernel/sched/core.c:10835 kernel/sched/core.c:2829)
> set_cpus_allowed_fair (kernel/sched/fair.c:10046)
> __set_cpus_allowed_ptr_locked (kernel/sched/core.c:2842 kernel/sched/core.c:3224)
> __set_cpus_allowed_ptr (kernel/sched/core.c:3258)
> __sched_setaffinity (kernel/sched/syscalls.c:1161)
> sched_setaffinity (kernel/sched/syscalls.c:1239)
> __x64_sys_sched_setaffinity (kernel/sched/syscalls.c:1275)
> do_syscall_64 (arch/x86/entry/syscall_64.c:84)
> entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
>
> Freed by task 5128:
> kmem_cache_free (mm/slub.c:6757)
> __mmput (kernel/fork.c:1204)
> mmput (kernel/fork.c:1215)
> setup_new_exec (fs/exec.c:1395)
> load_elf_binary (fs/binfmt_elf.c:1024)
> bprm_execve (fs/exec.c:1865)
> do_execveat_common.isra.0 (fs/exec.c:1963)
> __x64_sys_execve (fs/exec.c:2036)
> do_syscall_64 (arch/x86/entry/syscall_64.c:84)
> entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
>
> After exec publishes the new p->mm, acquire and release the task's runqueue
> lock before the old mm can be dropped. Affinity updates already hold that
> lock across set_cpus_allowed_common(), so the barrier waits for any update
> that loaded the old mm. Updates that start afterwards observe the new mm.
>
> This keeps allowed-mask updates synchronous, including transient affinity
> expansions, without changing the MM-CID fork, exit, or scheduling paths.
>
> This change was developed with assistance from an LLM.
>
> Fixes: 7e019dcc470f ("sched: Improve cache locality of RSEQ concurrency IDs for intermittent workloads")
> Cc: stable@vger.kernel.org
> Reported-by: <co+cab19e2ebe4d535a@bugs.sh>
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> ---
> Changes in v2:
> - Replace the schedule-in deferral with an exec-side runqueue-lock barrier.
> - Keep affinity expansions synchronous, including expansions narrowed before
> the next schedule-in.
> - Avoid changes to the MM-CID fork, exit, and scheduling state machine.
>
> fs/exec.c | 1 +
> include/linux/sched.h | 2 ++
> kernel/sched/core.c | 6 ++++++
> 3 files changed, 9 insertions(+)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index 8d2b14e1d455..2e1cac6a3de7 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -905,6 +905,7 @@ static int exec_mmap(struct linux_binprm *bprm)
> BUG_ON(active_mm != old_mm);
> /* Defer teardown to setup_new_exec(), outside the exec locks. */
> bprm->old_mm = old_mm;
> + sched_mm_cid_exec_mmap(tsk);
> } else {
> mmdrop_lazy_tlb(active_mm);
> }
[...]
>
> +/* Wait for affinity updates that may still be using the old MM. */
> +void sched_mm_cid_exec_mmap(struct task_struct *t)
> +{
> + guard(task_rq_lock)(t);
> +}
Using a lock side-effect as synchronization of what sits _outside_
of the lock is an interesting synchronization pattern. If this actually
works, it should be thoroughly documented.
It should come with at least one sequence diagram explaining why this
works, along with acquire-release MO explanation.
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH v2] sched/mmcid: Synchronize exec MM teardown with affinity updates
2026-11-08 13:33 ` Mathieu Desnoyers
@ 2026-11-08 14:23 ` Weiming Shi
0 siblings, 0 replies; 3+ messages in thread
From: Weiming Shi @ 2026-11-08 14:23 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot,
Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
Valentin Schneider, K Prateek Nayak, linux-kernel, Marco Elver,
co+cab19e2ebe4d535a, Xiang Mei, stable
Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 于2026年11月8日周日 05:33写道:
>
> On 2026-11-08 08:26, Weiming Shi wrote:
> > set_cpus_allowed_common() passes a remote task's p->mm to
> > mm_update_cpus_allowed(), but the scheduler locks do not stabilize that
> > pointer against exec. A same-owner sched_setaffinity() can race the target
> > replacing and freeing its old mm. Current kernels are only incidentally
> > serialized by futex_exec_done() taking p->pi_lock when CONFIG_FUTEX=y;
> > valid CONFIG_FUTEX=n builds remain vulnerable.
> >
> > BUG: KASAN: slab-use-after-free in set_cpus_allowed_common (kernel/sched/core.c:10835 kernel/sched/core.c:2829)
> > Read of size 4 at addr ffff88810991b04c by task poc/5127
> > Call Trace:
> > set_cpus_allowed_common (kernel/sched/core.c:10835 kernel/sched/core.c:2829)
> > set_cpus_allowed_fair (kernel/sched/fair.c:10046)
> > __set_cpus_allowed_ptr_locked (kernel/sched/core.c:2842 kernel/sched/core.c:3224)
> > __set_cpus_allowed_ptr (kernel/sched/core.c:3258)
> > __sched_setaffinity (kernel/sched/syscalls.c:1161)
> > sched_setaffinity (kernel/sched/syscalls.c:1239)
> > __x64_sys_sched_setaffinity (kernel/sched/syscalls.c:1275)
> > do_syscall_64 (arch/x86/entry/syscall_64.c:84)
> > entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> >
> > Freed by task 5128:
> > kmem_cache_free (mm/slub.c:6757)
> > __mmput (kernel/fork.c:1204)
> > mmput (kernel/fork.c:1215)
> > setup_new_exec (fs/exec.c:1395)
> > load_elf_binary (fs/binfmt_elf.c:1024)
> > bprm_execve (fs/exec.c:1865)
> > do_execveat_common.isra.0 (fs/exec.c:1963)
> > __x64_sys_execve (fs/exec.c:2036)
> > do_syscall_64 (arch/x86/entry/syscall_64.c:84)
> > entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> >
> > After exec publishes the new p->mm, acquire and release the task's runqueue
> > lock before the old mm can be dropped. Affinity updates already hold that
> > lock across set_cpus_allowed_common(), so the barrier waits for any update
> > that loaded the old mm. Updates that start afterwards observe the new mm.
> >
> > This keeps allowed-mask updates synchronous, including transient affinity
> > expansions, without changing the MM-CID fork, exit, or scheduling paths.
> >
> > This change was developed with assistance from an LLM.
> >
> > Fixes: 7e019dcc470f ("sched: Improve cache locality of RSEQ concurrency IDs for intermittent workloads")
> > Cc: stable@vger.kernel.org
> > Reported-by: <co+cab19e2ebe4d535a@bugs.sh>
> > Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> > ---
> > Changes in v2:
> > - Replace the schedule-in deferral with an exec-side runqueue-lock barrier.
> > - Keep affinity expansions synchronous, including expansions narrowed before
> > the next schedule-in.
> > - Avoid changes to the MM-CID fork, exit, and scheduling state machine.
> >
> > fs/exec.c | 1 +
> > include/linux/sched.h | 2 ++
> > kernel/sched/core.c | 6 ++++++
> > 3 files changed, 9 insertions(+)
> >
> > diff --git a/fs/exec.c b/fs/exec.c
> > index 8d2b14e1d455..2e1cac6a3de7 100644
> > --- a/fs/exec.c
> > +++ b/fs/exec.c
> > @@ -905,6 +905,7 @@ static int exec_mmap(struct linux_binprm *bprm)
> > BUG_ON(active_mm != old_mm);
> > /* Defer teardown to setup_new_exec(), outside the exec locks. */
> > bprm->old_mm = old_mm;
> > + sched_mm_cid_exec_mmap(tsk);
> > } else {
> > mmdrop_lazy_tlb(active_mm);
> > }
> [...]
> >
> > +/* Wait for affinity updates that may still be using the old MM. */
> > +void sched_mm_cid_exec_mmap(struct task_struct *t)
> > +{
> > + guard(task_rq_lock)(t);
> > +}
>
> Using a lock side-effect as synchronization of what sits _outside_
> of the lock is an interesting synchronization pattern. If this actually
> works, it should be thoroughly documented.
>
> It should come with at least one sequence diagram explaining why this
> works, along with acquire-release MO explanation.
>
> Thanks,
>
> Mathieu
>
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> https://www.efficios.com
Hi Mathieu,
Thanks for the feedback.
I will include the requested documentation, sequence diagram,
acquire-release memory order explanation, and reproduction code in v3.
Best regards,
Weiming Shi
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-08 14:24 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-08 13:26 [PATCH v2] sched/mmcid: Synchronize exec MM teardown with affinity updates Weiming Shi
2026-11-08 13:33 ` Mathieu Desnoyers
2026-11-08 14:23 ` Weiming Shi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®