lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ