80 lines
3.4 KiB
Diff
80 lines
3.4 KiB
Diff
From: Cyril Bur <cyrilbur@gmail.com>
|
|
Date: Thu, 17 Aug 2017 20:42:26 +1000
|
|
Subject: powerpc/64s: Use emergency stack for kernel TM Bad Thing program
|
|
checks
|
|
Origin: https://git.kernel.org/linus/265e60a170d0a0ecfc2d20490134ed2c48dd45ab
|
|
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-1000255
|
|
|
|
When using transactional memory (TM), the CPU can be in one of six
|
|
states as far as TM is concerned, encoded in the Machine State
|
|
Register (MSR). Certain state transitions are illegal and if attempted
|
|
trigger a "TM Bad Thing" type program check exception.
|
|
|
|
If we ever hit one of these exceptions it's treated as a bug, ie. we
|
|
oops, and kill the process and/or panic, depending on configuration.
|
|
|
|
One case where we can trigger a TM Bad Thing, is when returning to
|
|
userspace after a system call or interrupt, using RFID. When this
|
|
happens the CPU first restores the user register state, in particular
|
|
r1 (the stack pointer) and then attempts to update the MSR. However
|
|
the MSR update is not allowed and so we take the program check with
|
|
the user register state, but the kernel MSR.
|
|
|
|
This tricks the exception entry code into thinking we have a bad
|
|
kernel stack pointer, because the MSR says we're coming from the
|
|
kernel, but r1 is pointing to userspace.
|
|
|
|
To avoid this we instead always switch to the emergency stack if we
|
|
take a TM Bad Thing from the kernel. That way none of the user
|
|
register values are used, other than for printing in the oops message.
|
|
|
|
This is the fix for CVE-2017-1000255.
|
|
|
|
Fixes: 5d176f751ee3 ("powerpc: tm: Enable transactional memory (TM) lazily for userspace")
|
|
Cc: stable@vger.kernel.org # v4.9+
|
|
Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
|
|
[mpe: Rewrite change log & comments, tweak asm slightly]
|
|
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
|
---
|
|
arch/powerpc/kernel/exceptions-64s.S | 24 +++++++++++++++++++++++-
|
|
1 file changed, 23 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
|
|
index 48da0f5d2f7f..b82586c53560 100644
|
|
--- a/arch/powerpc/kernel/exceptions-64s.S
|
|
+++ b/arch/powerpc/kernel/exceptions-64s.S
|
|
@@ -734,7 +734,29 @@ EXC_REAL(program_check, 0x700, 0x100)
|
|
EXC_VIRT(program_check, 0x4700, 0x100, 0x700)
|
|
TRAMP_KVM(PACA_EXGEN, 0x700)
|
|
EXC_COMMON_BEGIN(program_check_common)
|
|
- EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
|
|
+ /*
|
|
+ * It's possible to receive a TM Bad Thing type program check with
|
|
+ * userspace register values (in particular r1), but with SRR1 reporting
|
|
+ * that we came from the kernel. Normally that would confuse the bad
|
|
+ * stack logic, and we would report a bad kernel stack pointer. Instead
|
|
+ * we switch to the emergency stack if we're taking a TM Bad Thing from
|
|
+ * the kernel.
|
|
+ */
|
|
+ li r10,MSR_PR /* Build a mask of MSR_PR .. */
|
|
+ oris r10,r10,0x200000@h /* .. and SRR1_PROGTM */
|
|
+ and r10,r10,r12 /* Mask SRR1 with that. */
|
|
+ srdi r10,r10,8 /* Shift it so we can compare */
|
|
+ cmpldi r10,(0x200000 >> 8) /* .. with an immediate. */
|
|
+ bne 1f /* If != go to normal path. */
|
|
+
|
|
+ /* SRR1 had PR=0 and SRR1_PROGTM=1, so use the emergency stack */
|
|
+ andi. r10,r12,MSR_PR; /* Set CR0 correctly for label */
|
|
+ /* 3 in EXCEPTION_PROLOG_COMMON */
|
|
+ mr r10,r1 /* Save r1 */
|
|
+ ld r1,PACAEMERGSP(r13) /* Use emergency stack */
|
|
+ subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */
|
|
+ b 3f /* Jump into the macro !! */
|
|
+1: EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
|
|
bl save_nvgprs
|
|
RECONCILE_IRQ_STATE(r10, r11)
|
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
|
--
|
|
2.11.0
|
|
|