Commit 71411c5f authored by Sergey Matyukevich's avatar Sergey Matyukevich Committed by Yongqiang Liu
Browse files

riscv: prevent pt_regs corruption for secondary idle threads

mainline inclusion
from mainline-v6.10-rc2
commit a638b0461b58aa3205cd9d5f14d6f703d795b4af
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IA7YKL
CVE: CVE-2024-38667

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a638b0461b58aa3205cd9d5f14d6f703d795b4af



-------------------------------------------------

Top of the kernel thread stack should be reserved for pt_regs. However
this is not the case for the idle threads of the secondary boot harts.
Their stacks overlap with their pt_regs, so both may get corrupted.

Similar issue has been fixed for the primary hart, see c7cdd96e
("riscv: prevent stack corruption by reserving task_pt_regs(p) early").
However that fix was not propagated to the secondary harts. The problem
has been noticed in some CPU hotplug tests with V enabled. The function
smp_callin stored several registers on stack, corrupting top of pt_regs
structure including status field. As a result, kernel attempted to save
or restore inexistent V context.

Fixes: 9a2451f1 ("RISC-V: Avoid using per cpu array for ordered booting")
Fixes: 2875fe05 ("RISC-V: Add cpu_ops and modify default booting method")
Signed-off-by: default avatarSergey Matyukevich <sergey.matyukevich@syntacore.com>
Reviewed-by: default avatarAlexandre Ghiti <alexghiti@rivosinc.com>
Link: https://lore.kernel.org/r/20240523084327.2013211-1-geomatsi@gmail.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
Conflicts:
	arch/riscv/kernel/cpu_ops_sbi.c
	arch/riscv/kernel/cpu_ops.c
	arch/riscv/kernel/cpu_ops_spinwait.c
[There is only one part of functions affected by this issue, so we
just do the partial fix]
Signed-off-by: default avatarZhang Zekun <zhangzekun11@huawei.com>
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent 4cebfb91
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -28,8 +28,7 @@ void cpu_update_secondary_bootdata(unsigned int cpuid,

	/* Make sure tidle is updated */
	smp_mb();
	WRITE_ONCE(__cpu_up_stack_pointer[hartid],
		   task_stack_page(tidle) + THREAD_SIZE);
	WRITE_ONCE(__cpu_up_stack_pointer[hartid], task_pt_regs(tidle));
	WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
}