]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
smp: Avoid invalid per-CPU CSD lookup with CSD lock debug
authorChuyi Zhou <zhouchuyi@bytedance.com>
Thu, 16 Jul 2026 00:45:38 +0000 (17:45 -0700)
committerThomas Gleixner <tglx@kernel.org>
Wed, 22 Jul 2026 18:57:07 +0000 (20:57 +0200)
Commit b0473dcd4b1d ("smp: Improve smp_call_function_single()
CSD-lock diagnostics") made smp_call_function_single() use the destination
CPU's csd_data when CSD lock debugging is enabled. That lets the debug code
associate a stuck CSD lock with the target CPU, but it also means the CPU
argument is used in per_cpu_ptr() before generic_exec_single() has a chance
to validate it.

This becomes unsafe when smp_call_function_any() cannot find an online CPU
in the supplied mask. In that case the selected CPU can be nr_cpu_ids, and
the !wait path calls get_single_csd_data(cpu) before generic_exec_single()
returns -ENXIO. With csdlock_debug_enabled set, that indexes the per-CPU
offset array with an invalid CPU number.

Use the destination CPU's csd_data only when the CPU number is within
nr_cpu_ids. For invalid CPU numbers, fall back to the local CPU's csd_data
and let generic_exec_single() perform the existing validation and return
-ENXIO.

Fixes: b0473dcd4b1d ("smp: Improve smp_call_function_single() CSD-lock diagnostics")
Signed-off-by: Chuyi Zhou <zhouchuyi@bytedance.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
Acked-by: Muchun Song <muchun.song@linux.dev>
Link: https://patch.msgid.link/20260716004539.13983-1-paulmck@kernel.org
kernel/smp.c

index a0bb56bd8ddadba77e76550bcd7299c4b0c609a1..dc6582bb35d084ad3517305ec224299f99189c35 100644 (file)
@@ -380,7 +380,8 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data);
 #ifdef CONFIG_CSD_LOCK_WAIT_DEBUG
 static call_single_data_t *get_single_csd_data(int cpu)
 {
-       if (static_branch_unlikely(&csdlock_debug_enabled))
+       if (static_branch_unlikely(&csdlock_debug_enabled) &&
+           (unsigned int)cpu < nr_cpu_ids)
                return per_cpu_ptr(&csd_data, cpu);
        return this_cpu_ptr(&csd_data);
 }