summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Gortmaker <paul.gortmaker@windriver.com>2019-09-18 09:04:06 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2019-09-18 09:04:06 -0400
commit9d80690f6ac166e50c399f4ccc7470adbb7e7bd2 (patch)
treef208beaf8b07317d0024a8a92a987ae9275f0ce5
parentb0801e806010c1f6a6c1b1dc57ac4a40af1bd8cb (diff)
downloadlongterm-queue-4.18-9d80690f6ac166e50c399f4ccc7470adbb7e7bd2.tar.gz
ppc: add CVE-2019-15031 commit
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r--queue/powerpc-tm-Fix-restoring-FP-VMX-facility-incorrectly.patch132
-rw-r--r--queue/series1
2 files changed, 133 insertions, 0 deletions
diff --git a/queue/powerpc-tm-Fix-restoring-FP-VMX-facility-incorrectly.patch b/queue/powerpc-tm-Fix-restoring-FP-VMX-facility-incorrectly.patch
new file mode 100644
index 0000000..e07c3dd
--- /dev/null
+++ b/queue/powerpc-tm-Fix-restoring-FP-VMX-facility-incorrectly.patch
@@ -0,0 +1,132 @@
+From a8318c13e79badb92bc6640704a64cc022a6eb97 Mon Sep 17 00:00:00 2001
+From: Gustavo Romero <gromero@linux.ibm.com>
+Date: Wed, 4 Sep 2019 00:55:28 -0400
+Subject: [PATCH] powerpc/tm: Fix restoring FP/VMX facility incorrectly on
+ interrupts
+
+commit a8318c13e79badb92bc6640704a64cc022a6eb97 upstream.
+
+When in userspace and MSR FP=0 the hardware FP state is unrelated to
+the current process. This is extended for transactions where if tbegin
+is run with FP=0, the hardware checkpoint FP state will also be
+unrelated to the current process. Due to this, we need to ensure this
+hardware checkpoint is updated with the correct state before we enable
+FP for this process.
+
+Unfortunately we get this wrong when returning to a process from a
+hardware interrupt. A process that starts a transaction with FP=0 can
+take an interrupt. When the kernel returns back to that process, we
+change to FP=1 but with hardware checkpoint FP state not updated. If
+this transaction is then rolled back, the FP registers now contain the
+wrong state.
+
+The process looks like this:
+ Userspace: Kernel
+
+ Start userspace
+ with MSR FP=0 TM=1
+ < -----
+ ...
+ tbegin
+ bne
+ Hardware interrupt
+ ---- >
+ <do_IRQ...>
+ ....
+ ret_from_except
+ restore_math()
+ /* sees FP=0 */
+ restore_fp()
+ tm_active_with_fp()
+ /* sees FP=1 (Incorrect) */
+ load_fp_state()
+ FP = 0 -> 1
+ < -----
+ Return to userspace
+ with MSR TM=1 FP=1
+ with junk in the FP TM checkpoint
+ TM rollback
+ reads FP junk
+
+When returning from the hardware exception, tm_active_with_fp() is
+incorrectly making restore_fp() call load_fp_state() which is setting
+FP=1.
+
+The fix is to remove tm_active_with_fp().
+
+tm_active_with_fp() is attempting to handle the case where FP state
+has been changed inside a transaction. In this case the checkpointed
+and transactional FP state is different and hence we must restore the
+FP state (ie. we can't do lazy FP restore inside a transaction that's
+used FP). It's safe to remove tm_active_with_fp() as this case is
+handled by restore_tm_state(). restore_tm_state() detects if FP has
+been using inside a transaction and will set load_fp and call
+restore_math() to ensure the FP state (checkpoint and transaction) is
+restored.
+
+This is a data integrity problem for the current process as the FP
+registers are corrupted. It's also a security problem as the FP
+registers from one process may be leaked to another.
+
+Similarly for VMX.
+
+A simple testcase to replicate this will be posted to
+tools/testing/selftests/powerpc/tm/tm-poison.c
+
+This fixes CVE-2019-15031.
+
+Fixes: a7771176b439 ("powerpc: Don't enable FP/Altivec if not checkpointed")
+Cc: stable@vger.kernel.org # 4.15+
+Signed-off-by: Gustavo Romero <gromero@linux.ibm.com>
+Signed-off-by: Michael Neuling <mikey@neuling.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20190904045529.23002-2-gromero@linux.vnet.ibm.com
+
+diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
+index 437b57068cf8..7a84c9f1778e 100644
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -101,21 +101,8 @@ static void check_if_tm_restore_required(struct task_struct *tsk)
+ }
+ }
+
+-static bool tm_active_with_fp(struct task_struct *tsk)
+-{
+- return MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
+- (tsk->thread.ckpt_regs.msr & MSR_FP);
+-}
+-
+-static bool tm_active_with_altivec(struct task_struct *tsk)
+-{
+- return MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
+- (tsk->thread.ckpt_regs.msr & MSR_VEC);
+-}
+ #else
+ static inline void check_if_tm_restore_required(struct task_struct *tsk) { }
+-static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; }
+-static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; }
+ #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
+ bool strict_msr_control;
+@@ -252,7 +239,7 @@ EXPORT_SYMBOL(enable_kernel_fp);
+
+ static int restore_fp(struct task_struct *tsk)
+ {
+- if (tsk->thread.load_fp || tm_active_with_fp(tsk)) {
++ if (tsk->thread.load_fp) {
+ load_fp_state(&current->thread.fp_state);
+ current->thread.load_fp++;
+ return 1;
+@@ -334,8 +321,7 @@ EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
+
+ static int restore_altivec(struct task_struct *tsk)
+ {
+- if (cpu_has_feature(CPU_FTR_ALTIVEC) &&
+- (tsk->thread.load_vec || tm_active_with_altivec(tsk))) {
++ if (cpu_has_feature(CPU_FTR_ALTIVEC) && (tsk->thread.load_vec)) {
+ load_vr_state(&tsk->thread.vr_state);
+ tsk->thread.used_vr = 1;
+ tsk->thread.load_vec++;
+--
+2.7.4
+
diff --git a/queue/series b/queue/series
index d190feb..0c0fe29 100644
--- a/queue/series
+++ b/queue/series
@@ -6,3 +6,4 @@ x86-entry-64-Use-JMP-instead-of-JMPQ.patch
x86-speculation-swapgs-Exclude-ATOMs-from-speculatio.patch
Documentation-Add-swapgs-description-to-the-Spectre-.patch
powerpc-tm-Fix-FP-VMX-unavailable-exceptions-inside-.patch
+powerpc-tm-Fix-restoring-FP-VMX-facility-incorrectly.patch