Do not restore the register holding the TLS pointer when doing various

usermode context switches (long jumps and ucontext operations). If these
are used across threads, multiple threads can end up with the same TLS base.
Madness will then result.

This makes behavior on PPC match that on x86 systems and on Linux.

MFC after:	10 days
This commit is contained in:
nwhitehorn 2012-04-11 00:00:40 +00:00
parent f0d73b6741
commit 5ff92b1d9c
7 changed files with 12 additions and 8 deletions

View File

@ -63,7 +63,6 @@ ENTRY(_longjmp)
lmw %r9,20(%r3)
mtlr %r11
mtcr %r12
mr %r2,%r9
mr %r1,%r10
or. %r3,%r4,%r4
bnelr

View File

@ -75,7 +75,6 @@ ENTRY(__longjmp)
mr %r6,%r4 /* save val param */
mtlr %r11 /* r11 -> link reg */
mtcr %r12 /* r12 -> condition reg */
mr %r2,%r9 /* r9 -> global ptr */
mr %r1,%r10 /* r10 -> stackptr */
mr %r4,%r3
li %r3,3 /* SIG_SETMASK */

View File

@ -80,7 +80,6 @@ ENTRY(siglongjmp)
mr %r6,%r4
mtlr %r11
mtcr %r12
mr %r2,%r9
mr %r1,%r10
or. %r7,%r7,%r7
beq 1f

View File

@ -86,7 +86,6 @@ ENTRY(_longjmp)
ld %r10,40 + 1*8(%r3)
ld %r11,40 + 2*8(%r3)
ld %r12,40 + 3*8(%r3)
ld %r13,40 + 4*8(%r3)
ld %r14,40 + 5*8(%r3)
ld %r15,40 + 6*8(%r3)
ld %r16,40 + 7*8(%r3)

View File

@ -99,7 +99,6 @@ ENTRY(__longjmp)
ld %r10,40 + 1*8(%r3)
ld %r11,40 + 2*8(%r3)
ld %r12,40 + 3*8(%r3)
ld %r13,40 + 4*8(%r3)
ld %r14,40 + 5*8(%r3)
ld %r15,40 + 6*8(%r3)
ld %r16,40 + 7*8(%r3)

View File

@ -103,7 +103,6 @@ ENTRY(siglongjmp)
ld %r10,40 + 1*8(%r3)
ld %r11,40 + 2*8(%r3)
ld %r12,40 + 3*8(%r3)
ld %r13,40 + 4*8(%r3)
ld %r14,40 + 5*8(%r3)
ld %r15,40 + 6*8(%r3)
ld %r16,40 + 7*8(%r3)

View File

@ -441,6 +441,7 @@ set_mcontext(struct thread *td, const mcontext_t *mcp)
{
struct pcb *pcb;
struct trapframe *tf;
register_t tls;
pcb = td->td_pcb;
tf = td->td_frame;
@ -448,16 +449,25 @@ set_mcontext(struct thread *td, const mcontext_t *mcp)
if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
return (EINVAL);
#ifdef AIM
#ifdef AIM
/*
* Don't let the user set privileged MSR bits
*/
if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
return (EINVAL);
}
#endif
#endif
/* Copy trapframe, preserving TLS pointer across context change */
if (SV_PROC_FLAG(td->td_proc, SV_LP64))
tls = tf->fixreg[13];
else
tls = tf->fixreg[2];
memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
if (SV_PROC_FLAG(td->td_proc, SV_LP64))
tf->fixreg[13] = tls;
else
tf->fixreg[2] = tls;
#ifdef AIM
if (mcp->mc_flags & _MC_FP_VALID) {