On Mon, 2018-11-19 at 10:44 -0200, Breno Leitao wrote: > On a signal handler return, the user could set a context with MSR[TS] bits > set, and these bits would be copied to task regs->msr. > > At restore_tm_sigcontexts(), after current task regs->msr[TS] bits are set, > several __get_user() are called and then a recheckpoint is executed.
Do we have the same problem on the entry side? There are a bunch of copy_from_user() before we do a tm_reclaim() (ie when still transactional). Is there some chance of the same problem there? > This is a problem since a page fault (in kernel space) could happen when > calling __get_user(). If it happens, the process MSR[TS] bits were > already set, but recheckpoint was not executed, and SPRs are still invalid. > > The page fault can cause the current process to be de-scheduled, with > MSR[TS] active and without tm_recheckpoint() being called. More > importantly, without TEXAR[FS] bit set also. This patch is great and should go in ASAP > Since TEXASR might not have the FS bit set, and when the process is > scheduled back, it will try to reclaim, which will be aborted because of > the CPU is not in the suspended state, and, then, recheckpoint. This > recheckpoint will restore thread->texasr into TEXASR SPR, which might be > zero, hitting a BUG_ON(). > > [ 2181.457997] kernel BUG at arch/powerpc/kernel/tm.S:446! Can you put more of the backtrace here? Can be useful for people searching for a similar problem. > This patch simply delays the MSR[TS] set, so, if there is any page fault in > the __get_user() section, it does not have regs->msr[TS] set, since the TM > structures are still invalid, thus avoiding doing TM operations for > in-kernel exceptions and possible process reschedule. Can you put a comment in the code what says after the MSR[TS] setting, there can be no get/put_user before the recheckpoint? Also, it looks like the 32bit signals case is safe, but please add a comment in there too. > With this patch, the MSR[TS] will only be set just before recheckpointing > and setting TEXASR[FS] = 1, thus avoiding an interrupt with TM registers in > invalid state. > > It is not possible to move tm_recheckpoint to happen earlier, because it is > required to get the checkpointed registers from userspace, with > __get_user(), thus, the only way to avoid this undesired behavior is > delaying the MSR[TS] set, as done in this patch. > > Fixes: 87b4e5393af7 ("powerpc/tm: Fix return of active 64bit signals") > Cc: sta...@vger.kernel.org (v3.9+) > Signed-off-by: Breno Leitao <lei...@debian.org> > --- > arch/powerpc/kernel/signal_64.c | 29 +++++++++++++++-------------- > 1 file changed, 15 insertions(+), 14 deletions(-) > > diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c > index 83d51bf586c7..15b153bdd826 100644 > --- a/arch/powerpc/kernel/signal_64.c > +++ b/arch/powerpc/kernel/signal_64.c > @@ -467,20 +467,6 @@ static long restore_tm_sigcontexts(struct task_struct > *tsk, > if (MSR_TM_RESV(msr)) > return -EINVAL; > > - /* pull in MSR TS bits from user context */ > - regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK); > - > - /* > - * Ensure that TM is enabled in regs->msr before we leave the signal > - * handler. It could be the case that (a) user disabled the TM bit > - * through the manipulation of the MSR bits in uc_mcontext or (b) the > - * TM bit was disabled because a sufficient number of context switches > - * happened whilst in the signal handler and load_tm overflowed, > - * disabling the TM bit. In either case we can end up with an illegal > - * TM state leading to a TM Bad Thing when we return to userspace. > - */ > - regs->msr |= MSR_TM; > - > /* pull in MSR LE from user context */ > regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); > > @@ -572,6 +558,21 @@ static long restore_tm_sigcontexts(struct task_struct > *tsk, > tm_enable(); > /* Make sure the transaction is marked as failed */ > tsk->thread.tm_texasr |= TEXASR_FS; > + > + /* pull in MSR TS bits from user context */ > + regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK); > + > + /* > + * Ensure that TM is enabled in regs->msr before we leave the signal > + * handler. It could be the case that (a) user disabled the TM bit > + * through the manipulation of ararararthe MSR bits in uc_mcontext or > (b) the > + * TM bit was disabled because a sufficient number of context switches > + * happened whilst in the signal handler and load_tm overflowed, > + * disabling the TM bit. In either case we can end up with an illegal > + * TM state leading to a TM Bad Thing when we return to userspace. > + */ > + regs->msr |= MSR_TM; > + > /* This loads the checkpointed FP/VEC state, if used */ > tm_recheckpoint(&tsk->thread); >