]>
Commit | Line | Data |
---|---|---|
23865d24 GKH |
1 | From 044215d145a7a8a60ffa8fdc859d110a795fa6ea Mon Sep 17 00:00:00 2001 |
2 | From: Gustavo Romero <gromero@linux.vnet.ibm.com> | |
3 | Date: Tue, 22 Aug 2017 17:20:09 -0400 | |
4 | Subject: powerpc/tm: Fix illegal TM state in signal handler | |
5 | ||
6 | From: Gustavo Romero <gromero@linux.vnet.ibm.com> | |
7 | ||
8 | commit 044215d145a7a8a60ffa8fdc859d110a795fa6ea upstream. | |
9 | ||
10 | Currently it's possible that on returning from the signal handler | |
11 | through the restore_tm_sigcontexts() code path (e.g. from a signal | |
12 | caught due to a `trap` instruction executed in the middle of an HTM | |
13 | block, or a deliberately constructed sigframe) an illegal TM state | |
14 | (like TS=10 TM=0, i.e. "T0") is set in SRR1 and when `rfid` sets | |
15 | implicitly the MSR register from SRR1 register on return to userspace | |
16 | it causes a TM Bad Thing exception. | |
17 | ||
18 | That illegal state can be set (a) by a malicious user that disables | |
19 | the TM bit by tweaking the bits in uc_mcontext before returning from | |
20 | the signal handler or (b) by a sufficient number of context switches | |
21 | occurring such that the load_tm counter overflows and TM is disabled | |
22 | whilst in the signal handler. | |
23 | ||
24 | This commit fixes the illegal TM state by ensuring that TM bit is | |
25 | always enabled before we return from restore_tm_sigcontexts(). A small | |
26 | comment correction is made as well. | |
27 | ||
28 | Fixes: 5d176f751ee3 ("powerpc: tm: Enable transactional memory (TM) lazily for userspace") | |
29 | Signed-off-by: Gustavo Romero <gromero@linux.vnet.ibm.com> | |
30 | Signed-off-by: Breno Leitao <leitao@debian.org> | |
31 | Signed-off-by: Cyril Bur <cyrilbur@gmail.com> | |
32 | Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> | |
33 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
34 | ||
35 | --- | |
36 | arch/powerpc/kernel/signal_64.c | 13 ++++++++++++- | |
37 | 1 file changed, 12 insertions(+), 1 deletion(-) | |
38 | ||
39 | --- a/arch/powerpc/kernel/signal_64.c | |
40 | +++ b/arch/powerpc/kernel/signal_64.c | |
41 | @@ -452,9 +452,20 @@ static long restore_tm_sigcontexts(struc | |
42 | if (MSR_TM_RESV(msr)) | |
43 | return -EINVAL; | |
44 | ||
45 | - /* pull in MSR TM from user context */ | |
46 | + /* pull in MSR TS bits from user context */ | |
47 | regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK); | |
48 | ||
49 | + /* | |
50 | + * Ensure that TM is enabled in regs->msr before we leave the signal | |
51 | + * handler. It could be the case that (a) user disabled the TM bit | |
52 | + * through the manipulation of the MSR bits in uc_mcontext or (b) the | |
53 | + * TM bit was disabled because a sufficient number of context switches | |
54 | + * happened whilst in the signal handler and load_tm overflowed, | |
55 | + * disabling the TM bit. In either case we can end up with an illegal | |
56 | + * TM state leading to a TM Bad Thing when we return to userspace. | |
57 | + */ | |
58 | + regs->msr |= MSR_TM; | |
59 | + | |
60 | /* pull in MSR LE from user context */ | |
61 | regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); | |
62 |