stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: stable@vger.kernel.org
Cc: linus.walleij@linaro.org, rmk+kernel@armlinux.org.uk,
	Ard Biesheuvel <ardb@kernel.org>
Subject: [PATCH for-stable-4.4 24/50] ARM: spectre-v2: harden user aborts in kernel space
Date: Fri,  8 Nov 2019 13:35:28 +0100	[thread overview]
Message-ID: <20191108123554.29004-25-ardb@kernel.org> (raw)
In-Reply-To: <20191108123554.29004-1-ardb@kernel.org>

From: Russell King <rmk+kernel@armlinux.org.uk>

Commit f5fe12b1eaee220ce62ff9afb8b90929c396595f upstream.

In order to prevent aliasing attacks on the branch predictor,
invalidate the BTB or instruction cache on CPUs that are known to be
affected when taking an abort on a address that is outside of a user
task limit:

Cortex A8, A9, A12, A17, A73, A75: flush BTB.
Cortex A15, Brahma B15: invalidate icache.

If the IBE bit is not set, then there is little point to enabling the
workaround.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Boot-tested-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: David A. Long <dave.long@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/cp15.h        |  3 +
 arch/arm/include/asm/system_misc.h | 15 ++++
 arch/arm/mm/fault.c                |  3 +
 arch/arm/mm/proc-v7-bugs.c         | 73 ++++++++++++++++++--
 arch/arm/mm/proc-v7.S              |  8 ++-
 5 files changed, 94 insertions(+), 8 deletions(-)

diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
index dbdbce1b3a72..b74b174ac9fc 100644
--- a/arch/arm/include/asm/cp15.h
+++ b/arch/arm/include/asm/cp15.h
@@ -64,6 +64,9 @@
 #define __write_sysreg(v, r, w, c, t)	asm volatile(w " " c : : "r" ((t)(v)))
 #define write_sysreg(v, ...)		__write_sysreg(v, __VA_ARGS__)
 
+#define BPIALL				__ACCESS_CP15(c7, 0, c5, 6)
+#define ICIALLU				__ACCESS_CP15(c7, 0, c5, 0)
+
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
 static inline unsigned long get_cr(void)
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
index a3d61ad984af..1fed41440af9 100644
--- a/arch/arm/include/asm/system_misc.h
+++ b/arch/arm/include/asm/system_misc.h
@@ -7,6 +7,7 @@
 #include <linux/linkage.h>
 #include <linux/irqflags.h>
 #include <linux/reboot.h>
+#include <linux/percpu.h>
 
 extern void cpu_init(void);
 
@@ -14,6 +15,20 @@ void soft_restart(unsigned long);
 extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
 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());
+	if (fn)
+		fn();
+}
+#else
+#define harden_branch_predictor() do { } while (0)
+#endif
+
 #define UDBG_UNDEFINED	(1 << 0)
 #define UDBG_SYSCALL	(1 << 1)
 #define UDBG_BADABORT	(1 << 2)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 702a5542b11a..20172b6fa773 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
 {
 	struct siginfo si;
 
+	if (addr > TASK_SIZE)
+		harden_branch_predictor();
+
 #ifdef CONFIG_DEBUG_USER
 	if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
 	    ((user_debug & UDBG_BUS)  && (sig == SIGBUS))) {
diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c
index e46557db6446..85a2e3d6263c 100644
--- a/arch/arm/mm/proc-v7-bugs.c
+++ b/arch/arm/mm/proc-v7-bugs.c
@@ -2,7 +2,61 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 
-static __maybe_unused void cpu_v7_check_auxcr_set(bool *warned,
+#include <asm/cp15.h>
+#include <asm/cputype.h>
+#include <asm/system_misc.h>
+
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+DEFINE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn);
+
+static void harden_branch_predictor_bpiall(void)
+{
+	write_sysreg(0, BPIALL);
+}
+
+static void harden_branch_predictor_iciallu(void)
+{
+	write_sysreg(0, ICIALLU);
+}
+
+static void cpu_v7_spectre_init(void)
+{
+	const char *spectre_v2_method = NULL;
+	int cpu = smp_processor_id();
+
+	if (per_cpu(harden_branch_predictor_fn, cpu))
+		return;
+
+	switch (read_cpuid_part()) {
+	case ARM_CPU_PART_CORTEX_A8:
+	case ARM_CPU_PART_CORTEX_A9:
+	case ARM_CPU_PART_CORTEX_A12:
+	case ARM_CPU_PART_CORTEX_A17:
+	case ARM_CPU_PART_CORTEX_A73:
+	case ARM_CPU_PART_CORTEX_A75:
+		per_cpu(harden_branch_predictor_fn, cpu) =
+			harden_branch_predictor_bpiall;
+		spectre_v2_method = "BPIALL";
+		break;
+
+	case ARM_CPU_PART_CORTEX_A15:
+	case ARM_CPU_PART_BRAHMA_B15:
+		per_cpu(harden_branch_predictor_fn, cpu) =
+			harden_branch_predictor_iciallu;
+		spectre_v2_method = "ICIALLU";
+		break;
+	}
+	if (spectre_v2_method)
+		pr_info("CPU%u: Spectre v2: using %s workaround\n",
+			smp_processor_id(), spectre_v2_method);
+}
+#else
+static void cpu_v7_spectre_init(void)
+{
+}
+#endif
+
+static __maybe_unused bool cpu_v7_check_auxcr_set(bool *warned,
 						  u32 mask, const char *msg)
 {
 	u32 aux_cr;
@@ -13,24 +67,33 @@ static __maybe_unused void cpu_v7_check_auxcr_set(bool *warned,
 		if (!*warned)
 			pr_err("CPU%u: %s", smp_processor_id(), msg);
 		*warned = true;
+		return false;
 	}
+	return true;
 }
 
 static DEFINE_PER_CPU(bool, spectre_warned);
 
-static void check_spectre_auxcr(bool *warned, u32 bit)
+static bool check_spectre_auxcr(bool *warned, u32 bit)
 {
-	if (IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR) &&
+	return IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR) &&
 		cpu_v7_check_auxcr_set(warned, bit,
 				       "Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable\n");
 }
 
 void cpu_v7_ca8_ibe(void)
 {
-	check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6));
+	if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6)))
+		cpu_v7_spectre_init();
 }
 
 void cpu_v7_ca15_ibe(void)
 {
-	check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0));
+	if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0)))
+		cpu_v7_spectre_init();
+}
+
+void cpu_v7_bugs_init(void)
+{
+	cpu_v7_spectre_init();
 }
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 1436ad424f2a..f6a4589b4fd2 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -474,8 +474,10 @@ __v7_setup_stack:
 
 	__INITDATA
 
+	.weak cpu_v7_bugs_init
+
 	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
-	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init
 
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 	@ generic v7 bpiall on context switch
@@ -490,7 +492,7 @@ __v7_setup_stack:
 	globl_equ	cpu_v7_bpiall_do_suspend,	cpu_v7_do_suspend
 	globl_equ	cpu_v7_bpiall_do_resume,	cpu_v7_do_resume
 #endif
-	define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+	define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init
 
 #define HARDENED_BPIALL_PROCESSOR_FUNCTIONS v7_bpiall_processor_functions
 #else
@@ -526,7 +528,7 @@ __v7_setup_stack:
 	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_switch_mm
 #endif
 	globl_equ	cpu_ca9mp_set_pte_ext,	cpu_v7_set_pte_ext
-	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init
 #endif
 
 	@ Cortex-A15 - needs iciallu switch_mm for hardening
-- 
2.20.1


  parent reply	other threads:[~2019-11-08 12:36 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-08 12:35 [PATCH for-stable-4.4 00/50] ARM: spectre v1/v2 mitigations Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 01/50] ARM: 8051/1: put_user: fix possible data corruption in put_user Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 02/50] ARM: 8478/2: arm/arm64: add arm-smccc Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 03/50] ARM: 8479/2: add implementation for arm-smccc Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 04/50] ARM: 8480/2: arm64: " Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 05/50] ARM: 8481/2: drivers: psci: replace psci firmware calls Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 06/50] ARM: uaccess: remove put_user() code duplication Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 07/50] ARM: Move system register accessors to asm/cp15.h Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 08/50] arm/arm64: KVM: Advertise SMCCC v1.1 Ard Biesheuvel
2019-11-08 13:11   ` Greg KH
2019-11-08 13:29     ` Ard Biesheuvel
2019-11-08 13:39       ` Greg KH
2019-11-08 13:39     ` Russell King - ARM Linux admin
2019-11-08 13:48       ` Mark Rutland
2019-11-08 12:35 ` [PATCH for-stable-4.4 09/50] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 10/50] firmware/psci: Expose PSCI conduit Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 11/50] firmware/psci: Expose SMCCC version through psci_ops Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 12/50] arm/arm64: smccc: Make function identifiers an unsigned quantity Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 13/50] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 14/50] arm/arm64: smccc: Add SMCCC-specific return codes Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 15/50] arm/arm64: smccc-1.1: Make return values unsigned long Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 16/50] arm/arm64: smccc-1.1: Handle function result as parameters Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 17/50] ARM: add more CPU part numbers for Cortex and Brahma B15 CPUs Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 18/50] ARM: bugs: prepare processor bug infrastructure Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 19/50] ARM: bugs: hook processor bug checking into SMP and suspend paths Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 20/50] ARM: bugs: add support for per-processor bug checking Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 21/50] ARM: spectre: add Kconfig symbol for CPUs vulnerable to Spectre Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 22/50] ARM: spectre-v2: harden branch predictor on context switches Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 23/50] ARM: spectre-v2: add Cortex A8 and A15 validation of the IBE bit Ard Biesheuvel
2019-11-08 12:35 ` Ard Biesheuvel [this message]
2019-11-08 12:35 ` [PATCH for-stable-4.4 25/50] ARM: spectre-v2: add firmware based hardening Ard Biesheuvel
2019-11-08 13:13   ` Greg KH
2019-11-08 12:35 ` [PATCH for-stable-4.4 26/50] ARM: spectre-v2: warn about incorrect context switching functions Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 27/50] ARM: spectre-v1: add speculation barrier (csdb) macros Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 28/50] ARM: spectre-v1: add array_index_mask_nospec() implementation Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 29/50] ARM: spectre-v1: fix syscall entry Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 30/50] ARM: signal: copy registers using __copy_from_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 31/50] ARM: vfp: use __copy_from_user() when restoring VFP state Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 32/50] ARM: oabi-compat: copy semops using __copy_from_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 33/50] ARM: use __inttype() in get_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 34/50] ARM: spectre-v1: use get_user() for __get_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 35/50] ARM: spectre-v1: mitigate user accesses Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 36/50] ARM: 8789/1: signal: copy registers using __copy_to_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 37/50] ARM: 8791/1: vfp: use __copy_to_user() when saving VFP state Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 38/50] ARM: 8792/1: oabi-compat: copy oabi events using __copy_to_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 39/50] ARM: 8793/1: signal: replace __put_user_error with __put_user Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 40/50] ARM: 8794/1: uaccess: Prevent speculative use of the current addr_limit Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 41/50] ARM: 8795/1: spectre-v1.1: use put_user() for __put_user() Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 42/50] ARM: 8796/1: spectre-v1,v1.1: provide helpers for address sanitization Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 43/50] ARM: 8810/1: vfp: Fix wrong assignement to ufp_exc Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 44/50] ARM: make lookup_processor_type() non-__init Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 45/50] ARM: split out processor lookup Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 46/50] ARM: clean up per-processor check_bugs method call Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 47/50] ARM: add PROC_VTABLE and PROC_TABLE macros Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 48/50] ARM: spectre-v2: per-CPU vtables to work around big.Little systems Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 49/50] ARM: ensure that processor vtables is not lost after boot Ard Biesheuvel
2019-11-08 12:35 ` [PATCH for-stable-4.4 50/50] ARM: fix the cockup in the previous patch Ard Biesheuvel
2019-11-08 13:15 ` [PATCH for-stable-4.4 00/50] ARM: spectre v1/v2 mitigations Greg KH
2019-11-08 15:43 ` Linus Walleij

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191108123554.29004-25-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=linus.walleij@linaro.org \
    --cc=rmk+kernel@armlinux.org.uk \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).