diff mbox

[3/5] powerpc/tm: Fix restoration of MSR on 32bit signal return

Message ID 1370601390-29065-3-git-send-email-mikey@neuling.org (mailing list archive)
State Superseded
Headers show

Commit Message

Michael Neuling June 7, 2013, 10:36 a.m. UTC
Currently we clear out the MSR TM bits on signal return assuming that the
signal should never return to an active transaction.

This is bogus as the user may do this.  It's most likely the transaction will
be doomed due to a treclaim but that's a problem for the HW not the kernel.

This removes the stripping of these MSR TM bits.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
 arch/powerpc/kernel/signal_32.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Benjamin Herrenschmidt June 9, 2013, 7:27 a.m. UTC | #1
On Fri, 2013-06-07 at 20:36 +1000, Michael Neuling wrote:
> Currently we clear out the MSR TM bits on signal return assuming that the
> signal should never return to an active transaction.
> 
> This is bogus as the user may do this.  It's most likely the transaction will
> be doomed due to a treclaim but that's a problem for the HW not the kernel.
> 
> This removes the stripping of these MSR TM bits.
> 
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> ---

> @@ -859,8 +860,10 @@ static long restore_tm_user_regs(struct pt_regs *regs,
>  	tm_enable();
>  	/* This loads the checkpointed FP/VEC state, if used */
>  	tm_recheckpoint(&current->thread, msr);
> -	/* The task has moved into TM state S, so ensure MSR reflects this */
> -	regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S;
> +	/* Retore the top half of the MSR */
> +	if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
> +		return 1;
> +	regs->msr = (regs->msr | (((unsigned long)msr_hi) << 32));

What kind of damage can I do by calling sigreturn with a cooked
frame with random MSR bits set ? You should probably filter
what bits you allow to come from the frame.

Additionally, I would also make sure I only do that if the CPU
features say TM is supported in case that MSR bit means something else
on a different/older CPU...

Cheers,
Ben.
Michael Neuling June 9, 2013, 9:56 a.m. UTC | #2
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Fri, 2013-06-07 at 20:36 +1000, Michael Neuling wrote:
> > Currently we clear out the MSR TM bits on signal return assuming that the
> > signal should never return to an active transaction.
> > 
> > This is bogus as the user may do this.  It's most likely the transaction will
> > be doomed due to a treclaim but that's a problem for the HW not the kernel.
> > 
> > This removes the stripping of these MSR TM bits.
> > 
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> > ---
> 
> > @@ -859,8 +860,10 @@ static long restore_tm_user_regs(struct pt_regs *regs,
> >  	tm_enable();
> >  	/* This loads the checkpointed FP/VEC state, if used */
> >  	tm_recheckpoint(&current->thread, msr);
> > -	/* The task has moved into TM state S, so ensure MSR reflects this */
> > -	regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S;
> > +	/* Retore the top half of the MSR */
> > +	if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
> > +		return 1;
> > +	regs->msr = (regs->msr | (((unsigned long)msr_hi) << 32));
> 
> What kind of damage can I do by calling sigreturn with a cooked
> frame with random MSR bits set ? You should probably filter
> what bits you allow to come from the frame.

Lots of damage.. good, point.  

We do that in the 64 bit version of this.  I'll update to do the same.

> Additionally, I would also make sure I only do that if the CPU
> features say TM is supported in case that MSR bit means something else
> on a different/older CPU...

Ok, I'll add that also.

Mikey
diff mbox

Patch

diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 5b0fbe2..b8279b3 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -755,6 +755,7 @@  static long restore_tm_user_regs(struct pt_regs *regs,
 {
 	long err;
 	unsigned long msr;
+	__u32 msr_hi;
 #ifdef CONFIG_VSX
 	int i;
 #endif
@@ -859,8 +860,10 @@  static long restore_tm_user_regs(struct pt_regs *regs,
 	tm_enable();
 	/* This loads the checkpointed FP/VEC state, if used */
 	tm_recheckpoint(&current->thread, msr);
-	/* The task has moved into TM state S, so ensure MSR reflects this */
-	regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S;
+	/* Retore the top half of the MSR */
+	if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
+		return 1;
+	regs->msr = (regs->msr | (((unsigned long)msr_hi) << 32));
 
 	/* This loads the speculative FP/VEC state, if used */
 	if (msr & MSR_FP) {