[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250424100437.27477-1-xieyuanbin1@huawei.com>
Date: Thu, 24 Apr 2025 18:04:37 +0800
From: xieyuanbin1 <xieyuanbin1@...wei.com>
To: <linux@...linux.org.uk>, <sfr@...b.auug.org.au>,
<rmk+kernel@...linux.org.uk>, <xieyuanbin1@...wei.com>
CC: <linux-arm-kernel@...ts.infradead.org>, <linux-kernel@...r.kernel.org>,
<will@...nel.org>, <nixiaoming@...wei.com>, <liaohua4@...wei.com>,
<wangbing6@...wei.com>, <lincheng8@...wei.com>, <wangfangpeng1@...wei.com>
Subject: [PATCH] ARM: spectre-v2: fix unstable cpu get
From: Xie Yuanbin <xieyuanbin1@...wei.com>
When a user program accesses the kernel address,
a segment fault will be triggered.
For the latest kernel, with arm's multi_v7_defconfig, and set
CONFIG_PREEMPT=y, CONFIG_DEBUG_PREEMPT=y, CONFIG_ARM_LPAE=y,
if a user program try to accesses a valid kernel address, for example:
```c
static void han(int x)
{
while (1);
}
int main(void)
{
signal(SIGSEGV, han);
/* 0xc0331fd4 is just a kernel address in kernel .text section */
__asm__ volatile (""::"r"(*(int *)(uintptr_t)0xc0331fd4):"memory");
while (1);
return 0;
}
```
, the following WARN will be triggered:
[ 1.089103] BUG: using smp_processor_id() in preemptible [00000000] code: init/1
[ 1.093367] caller is __do_user_fault+0x20/0x6c
[ 1.094355] CPU: 0 UID: 0 PID: 1 Comm: init Not tainted 6.14.3 #7
[ 1.094585] Hardware name: Generic DT based system
[ 1.094706] Call trace:
[ 1.095211] unwind_backtrace from show_stack+0x10/0x14
[ 1.095329] show_stack from dump_stack_lvl+0x50/0x5c
[ 1.095352] dump_stack_lvl from check_preemption_disabled+0x104/0x108
[ 1.095448] check_preemption_disabled from __do_user_fault+0x20/0x6c
[ 1.095459] __do_user_fault from do_page_fault+0x334/0x3dc
[ 1.095505] do_page_fault from do_DataAbort+0x30/0xa8
[ 1.095528] do_DataAbort from __dabt_usr+0x54/0x60
[ 1.095570] Exception stack(0xf0825fb0 to 0xf0825ff8)
[ 1.095706] 5fa0: 00000000 befe9c64 00000000 c0331000
[ 1.095737] 5fc0: 00000002 0006dd68 00000001 befe9f04 befe9f0c 00070010 00000002 00073770
[ 1.095746] 5fe0: befe9d94 befe9da8 00010953 00010250 600d0030 ffffffff
In this case, the hook func in do_DataAbort `inf->fn` is `do_page_fault`,
`do_page_fault` enables the irq, so it is preemptible here.
Inside `harden_branch_predictor`, if we just obtains the hook function `fn`
of this CPU, then the task is scheduled to another CPU.
The previous function is still executed, which is dangerous.
Use get_cpu() and put_cpu() to fix it.
Fixes: f5fe12b1eaee ("ARM: spectre-v2: harden user aborts in kernel space")
Signed-off-by: Xie Yuanbin <xieyuanbin1@...wei.com>
---
arch/arm/include/asm/system_misc.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
index 98b373403..93cad3d50 100644
--- a/arch/arm/include/asm/system_misc.h
+++ b/arch/arm/include/asm/system_misc.h
@@ -18,15 +18,16 @@ extern void (*arm_pm_idle)(void);
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
typedef void (*harden_branch_predictor_fn_t)(void);
DECLARE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn);
static inline void harden_branch_predictor(void)
{
harden_branch_predictor_fn_t fn = per_cpu(harden_branch_predictor_fn,
- smp_processor_id());
+ get_cpu());
if (fn)
fn();
+ put_cpu();
}
#else
#define harden_branch_predictor() do { } while (0)
#endif
#define UDBG_UNDEFINED (1 << 0)
--
2.48.1
Powered by blists - more mailing lists