powerpc/tm: Block signal return setting invalid MSR state
Currently we allow both the MSR T and S bits to be set by userspace on
a signal return. Unfortunately this is a reserved configuration and
will cause a TM Bad Thing exception if attempted (via rfid).
This patch checks for this case in both the 32 and 64 bit signals
code. If both T and S are set, we mark the context as invalid.
Found using a syscall fuzzer.
Fixes: 2b0a576d15
("powerpc: Add new transactional memory state to the signal context")
Cc: stable@vger.kernel.org # v3.9+
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:

committed by
Michael Ellerman

parent
1ec218373b
commit
d2b9d2a5ad
@@ -875,6 +875,15 @@ static long restore_tm_user_regs(struct pt_regs *regs,
|
||||
return 1;
|
||||
#endif /* CONFIG_SPE */
|
||||
|
||||
/* Get the top half of the MSR from the user context */
|
||||
if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
|
||||
return 1;
|
||||
msr_hi <<= 32;
|
||||
/* If TM bits are set to the reserved value, it's an invalid context */
|
||||
if (MSR_TM_RESV(msr_hi))
|
||||
return 1;
|
||||
/* Pull in the MSR TM bits from the user context */
|
||||
regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK);
|
||||
/* Now, recheckpoint. This loads up all of the checkpointed (older)
|
||||
* registers, including FP and V[S]Rs. After recheckpointing, the
|
||||
* transactional versions should be loaded.
|
||||
@@ -884,11 +893,6 @@ static long restore_tm_user_regs(struct pt_regs *regs,
|
||||
current->thread.tm_texasr |= TEXASR_FS;
|
||||
/* This loads the checkpointed FP/VEC state, if used */
|
||||
tm_recheckpoint(¤t->thread, msr);
|
||||
/* Get the top half of the MSR */
|
||||
if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
|
||||
return 1;
|
||||
/* Pull in MSR TM from user context */
|
||||
regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK);
|
||||
|
||||
/* This loads the speculative FP/VEC state, if used */
|
||||
if (msr & MSR_FP) {
|
||||
|
@@ -438,6 +438,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
|
||||
|
||||
/* get MSR separately, transfer the LE bit if doing signal return */
|
||||
err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
|
||||
/* Don't allow reserved mode. */
|
||||
if (MSR_TM_RESV(msr))
|
||||
return -EINVAL;
|
||||
|
||||
/* pull in MSR TM from user context */
|
||||
regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
|
||||
|
||||
|
Reference in New Issue
Block a user