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