|
Michal Suchanek |
dd997a |
From 8ec7791bae1327b1c279c5cd6e929c3b12daaf0a Mon Sep 17 00:00:00 2001
|
|
Michal Suchanek |
dd997a |
From: Michael Ellerman <mpe@ellerman.id.au>
|
|
Michal Suchanek |
dd997a |
Date: Thu, 6 May 2021 14:49:58 +1000
|
|
Michal Suchanek |
dd997a |
Subject: [PATCH] powerpc/64s: Fix crashes when toggling stf barrier
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
70f4fd |
References: bsc#1087082 git-fixes bsc#1186460 ltc#192531
|
|
Michal Suchanek |
dd997a |
Patch-mainline: v5.13-rc2
|
|
Michal Suchanek |
dd997a |
Git-commit: 8ec7791bae1327b1c279c5cd6e929c3b12daaf0a
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
The STF (store-to-load forwarding) barrier mitigation can be
|
|
Michal Suchanek |
dd997a |
enabled/disabled at runtime via a debugfs file (stf_barrier), which
|
|
Michal Suchanek |
dd997a |
causes the kernel to patch itself to enable/disable the relevant
|
|
Michal Suchanek |
dd997a |
mitigations.
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
However depending on which mitigation we're using, it may not be safe to
|
|
Michal Suchanek |
dd997a |
do that patching while other CPUs are active. For example the following
|
|
Michal Suchanek |
dd997a |
crash:
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
User access of kernel address (c00000003fff5af0) - exploit attempt? (uid: 0)
|
|
Michal Suchanek |
dd997a |
segfault (11) at c00000003fff5af0 nip 7fff8ad12198 lr 7fff8ad121f8 code 1
|
|
Michal Suchanek |
dd997a |
code: 40820128 e93c00d0 e9290058 7c292840 40810058 38600000 4bfd9a81 e8410018
|
|
Michal Suchanek |
dd997a |
code: 2c030006 41810154 3860ffb6 e9210098 <e94d8ff0> 7d295279 39400000 40820a3c
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
Shows that we returned to userspace without restoring the user r13
|
|
Michal Suchanek |
dd997a |
value, due to executing the partially patched STF exit code.
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
Fix it by doing the patching under stop machine. The CPUs that aren't
|
|
Michal Suchanek |
dd997a |
doing the patching will be spinning in the core of the stop machine
|
|
Michal Suchanek |
dd997a |
logic. That is currently sufficient for our purposes, because none of
|
|
Michal Suchanek |
dd997a |
the patching we do is to that code or anywhere in the vicinity.
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
Fixes: a048a07d7f45 ("powerpc/64s: Add support for a store forwarding barrier at kernel entry/exit")
|
|
Michal Suchanek |
dd997a |
Cc: stable@vger.kernel.org # v4.17+
|
|
Michal Suchanek |
dd997a |
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
|
Michal Suchanek |
dd997a |
Link: https://lore.kernel.org/r/20210506044959.1298123-1-mpe@ellerman.id.au
|
|
Michal Suchanek |
dd997a |
Acked-by: Michal Suchanek <msuchanek@suse.de>
|
|
Michal Suchanek |
dd997a |
---
|
|
Michal Suchanek |
dd997a |
arch/powerpc/lib/feature-fixups.c | 19 +++++++++++++++++--
|
|
Michal Suchanek |
dd997a |
1 file changed, 17 insertions(+), 2 deletions(-)
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
|
|
Michal Suchanek |
dd997a |
index 1fd31b4b0e13..10083add8b33 100644
|
|
Michal Suchanek |
dd997a |
--- a/arch/powerpc/lib/feature-fixups.c
|
|
Michal Suchanek |
dd997a |
+++ b/arch/powerpc/lib/feature-fixups.c
|
|
Michal Suchanek |
dd997a |
@@ -14,6 +14,7 @@
|
|
Michal Suchanek |
dd997a |
#include <linux/string.h>
|
|
Michal Suchanek |
dd997a |
#include <linux/init.h>
|
|
Michal Suchanek |
dd997a |
#include <linux/sched/mm.h>
|
|
Michal Suchanek |
dd997a |
+#include <linux/stop_machine.h>
|
|
Michal Suchanek |
dd997a |
#include <asm/cputable.h>
|
|
Michal Suchanek |
dd997a |
#include <asm/code-patching.h>
|
|
Michal Suchanek |
dd997a |
#include <asm/page.h>
|
|
Michal Suchanek |
dd997a |
@@ -227,11 +228,25 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
|
|
Michal Suchanek |
dd997a |
: "unknown");
|
|
Michal Suchanek |
dd997a |
}
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
+static int __do_stf_barrier_fixups(void *data)
|
|
Michal Suchanek |
dd997a |
+{
|
|
Michal Suchanek |
dd997a |
+ enum stf_barrier_type *types = data;
|
|
Michal Suchanek |
dd997a |
+
|
|
Michal Suchanek |
dd997a |
+ do_stf_entry_barrier_fixups(*types);
|
|
Michal Suchanek |
dd997a |
+ do_stf_exit_barrier_fixups(*types);
|
|
Michal Suchanek |
dd997a |
+
|
|
Michal Suchanek |
dd997a |
+ return 0;
|
|
Michal Suchanek |
dd997a |
+}
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
void do_stf_barrier_fixups(enum stf_barrier_type types)
|
|
Michal Suchanek |
dd997a |
{
|
|
Michal Suchanek |
dd997a |
- do_stf_entry_barrier_fixups(types);
|
|
Michal Suchanek |
dd997a |
- do_stf_exit_barrier_fixups(types);
|
|
Michal Suchanek |
dd997a |
+ /*
|
|
Michal Suchanek |
dd997a |
+ * The call to the fallback entry flush, and the fallback/sync-ori exit
|
|
Michal Suchanek |
dd997a |
+ * flush can not be safely patched in/out while other CPUs are executing
|
|
Michal Suchanek |
dd997a |
+ * them. So call __do_stf_barrier_fixups() on one CPU while all other CPUs
|
|
Michal Suchanek |
dd997a |
+ * spin in the stop machine core with interrupts hard disabled.
|
|
Michal Suchanek |
dd997a |
+ */
|
|
Michal Suchanek |
dd997a |
+ stop_machine(__do_stf_barrier_fixups, &types, NULL);
|
|
Michal Suchanek |
dd997a |
}
|
|
Michal Suchanek |
dd997a |
|
|
Michal Suchanek |
dd997a |
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
|
Michal Suchanek |
dd997a |
--
|
|
Michal Suchanek |
dd997a |
2.26.2
|
|
Michal Suchanek |
dd997a |
|