[tip: smp/core] smp: Alloc percpu csd data in smpcfd_prepare_cpu() only once

tip-bot2 for Chuyi Zhou posted 1 patch 1 day, 11 hours ago
kernel/smp.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
[tip: smp/core] smp: Alloc percpu csd data in smpcfd_prepare_cpu() only once
Posted by tip-bot2 for Chuyi Zhou 1 day, 11 hours ago
The following commit has been merged into the smp/core branch of tip:

Commit-ID:     9f483e5b2f1263f7fad20bcc5b09d01d2da57f1f
Gitweb:        https://git.kernel.org/tip/9f483e5b2f1263f7fad20bcc5b09d01d2da57f1f
Author:        Chuyi Zhou <zhouchuyi@bytedance.com>
AuthorDate:    Thu, 09 Jul 2026 20:29:24 +08:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Thu, 16 Jul 2026 09:24:55 +02:00

smp: Alloc percpu csd data in smpcfd_prepare_cpu() only once

smp_call_function_many_cond() uses per-CPU CSD objects when queueing
callbacks to remote CPUs, and the wait path later dereferences those CSDs
from csd_lock_wait().

Making the wait path preemptible allows the initiating task to be
preempted or migrated before it waits for completion. A target CPU can be
offlined in that window. If smpcfd_dead_cpu() frees the target CPU's
per-CPU CSD storage, csd_lock_wait() can later dereference freed memory.

One way to protect the CSD storage is to free it via RCU or after a
synchronization step in the CPU offline path, but that would add
unnecessary complexity and can delay CPU shutdown.

Allocate the per-CPU CSD storage the first time a CPU comes up and keep
it allocated when the CPU is offlined. This allows csd_lock_wait() to
access the CSD even when the target CPU is offlined after preemption is
re-enabled and before the wait is invoked.

Signed-off-by: Chuyi Zhou <zhouchuyi@bytedance.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Paul E. McKenney <paulmck@kernel.org>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Muchun Song <muchun.song@linux.dev>
Link: https://patch.msgid.link/20260709122933.4021501-6-zhouchuyi@bytedance.com
---
 kernel/smp.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/kernel/smp.c b/kernel/smp.c
index 19fdee6..e6c1d83 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -64,7 +64,14 @@ int smpcfd_prepare_cpu(unsigned int cpu)
 		free_cpumask_var(cfd->cpumask);
 		return -ENOMEM;
 	}
-	cfd->csd = alloc_percpu(call_single_data_t);
+
+	/*
+	 * Allocate the per-CPU CSD the first time a CPU comes up. It is
+	 * not freed when the CPU is offlined, so csd_lock_wait() can access
+	 * it even when the CPU was offlined after preemption was re-enabled.
+	 */
+	if (!cfd->csd)
+		cfd->csd = alloc_percpu(call_single_data_t);
 	if (!cfd->csd) {
 		free_cpumask_var(cfd->cpumask);
 		free_cpumask_var(cfd->cpumask_ipi);
@@ -80,7 +87,6 @@ int smpcfd_dead_cpu(unsigned int cpu)
 
 	free_cpumask_var(cfd->cpumask);
 	free_cpumask_var(cfd->cpumask_ipi);
-	free_percpu(cfd->csd);
 	return 0;
 }