diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-06-21 00:57:00 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-06-21 00:57:00 +0000 |
commit | 867c8588faf5fba418fc7c3a85aa2bd4c3327e01 (patch) | |
tree | e98c388fcdff4a138a38722ee463c1b12f6c133a /sys/arch | |
parent | 28222fd1268ab97426703666e99f70ed942e847b (diff) |
__tfork() needs to set the stack address of the new thread in the kernel,
so that it can't get a signal while still running on the parent thread's
stack. Also, pass in sizeof(struct __tfork) to provide forward compat
when more members are added. This is an ABI change, so switch syscall
numbers and bump lib majors this time.
ok deraadt@ matthew@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/hppa/hppa/machdep.c | 41 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/vm_machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/hppa/include/frame.h | 7 | ||||
-rw-r--r-- | sys/arch/hppa64/hppa64/machdep.c | 46 | ||||
-rw-r--r-- | sys/arch/hppa64/hppa64/vm_machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/vm_machdep.c | 18 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/vm_machdep.c | 12 |
7 files changed, 82 insertions, 50 deletions
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c index f38055b2363..2cc1d6ee24d 100644 --- a/sys/arch/hppa/hppa/machdep.c +++ b/sys/arch/hppa/hppa/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.205 2011/09/20 09:49:38 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.206 2012/06/21 00:56:59 guenther Exp $ */ /* * Copyright (c) 1999-2003 Michael Shalayeff @@ -1133,6 +1133,25 @@ copyout(const void *src, void *dst, size_t size) } /* + * Set up tf_sp and tf_r3 (the frame pointer) and copy out the + * frame marker and the old r3 + */ +int +setstack(struct trapframe *tf, u_long stack, register_t old_r3) +{ + static const register_t zero = 0; + int err; + + tf->tf_r3 = stack; + err = copyout(&old_r3, (caddr_t)stack, sizeof(register_t)); + + tf->tf_sp = stack += HPPA_FRAME_SIZE; + return (copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP), + sizeof(register_t)) || err); +} + + +/* * Set registers on exec. */ void @@ -1141,7 +1160,6 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, { struct trapframe *tf = p->p_md.md_regs; struct pcb *pcb = &p->p_addr->u_pcb; - register_t zero; tf->tf_flags = TFF_SYS|TFF_LAST; tf->tf_iioq_tail = 4 + @@ -1151,12 +1169,7 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */ /* setup terminal stack frame */ - stack = (stack + 0x1f) & ~0x1f; - tf->tf_r3 = stack; - tf->tf_sp = stack += HPPA_FRAME_SIZE; - zero = 0; - copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t)); - copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP), sizeof(register_t)); + setstack(tf, (stack + 0x1f) & ~0x1f, 0); /* reset any of the pending FPU exceptions */ fpu_proc_flush(p); @@ -1261,12 +1274,13 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, bcopy(&p->p_addr->u_pcb.pcb_fpstate->hfp_regs, ksc.sc_fpregs, sizeof(ksc.sc_fpregs)); - sss += HPPA_FRAME_SIZE; + if (setstack(tf, scp + sss, tf->tf_r3)) + sigexit(p, SIGILL); + tf->tf_arg0 = sig; tf->tf_arg1 = sip; tf->tf_arg2 = tf->tf_r4 = scp; tf->tf_arg3 = (register_t)catcher; - tf->tf_sp = scp + sss; tf->tf_ipsw &= ~(PSL_N|PSL_B|PSL_T); tf->tf_iioq_head = HPPA_PC_PRIV_USER | p->p_sigcode; tf->tf_iioq_tail = tf->tf_iioq_head + 4; @@ -1276,7 +1290,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n", - p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss); + p->p_pid, sig, scp, ksc.sc_fp, tf->tf_sp); #endif if (copyout(&ksc, (void *)scp, sizeof(ksc))) @@ -1288,11 +1302,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, sigexit(p, SIGILL); } - if (copyout(&tf->tf_r3, (caddr_t)(tf->tf_sp - HPPA_FRAME_SIZE), - sizeof(register_t))) - sigexit(p, SIGILL); - tf->tf_r3 = tf->tf_sp - HPPA_FRAME_SIZE; - #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sendsig(%d): pc 0x%x catcher 0x%x\n", p->p_pid, diff --git a/sys/arch/hppa/hppa/vm_machdep.c b/sys/arch/hppa/hppa/vm_machdep.c index 3d6154beebf..9642cf0da5b 100644 --- a/sys/arch/hppa/hppa/vm_machdep.c +++ b/sys/arch/hppa/hppa/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.75 2011/09/20 21:46:08 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.76 2012/06/21 00:56:59 guenther Exp $ */ /* * Copyright (c) 1999-2004 Michael Shalayeff @@ -147,7 +147,7 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, * If specified, give the child a different stack. */ if (stack != NULL) - tf->tf_sp = (register_t)stack; + setstack(tf, (u_long)stack, 0); /* XXX ignore error? */ /* * Build stack frames for the cpu_switchto & co. diff --git a/sys/arch/hppa/include/frame.h b/sys/arch/hppa/include/frame.h index 09b289e476f..28810732471 100644 --- a/sys/arch/hppa/include/frame.h +++ b/sys/arch/hppa/include/frame.h @@ -1,4 +1,4 @@ -/* $OpenBSD: frame.h,v 1.18 2011/11/14 14:29:53 deraadt Exp $ */ +/* $OpenBSD: frame.h,v 1.19 2012/06/21 00:56:59 guenther Exp $ */ /* * Copyright (c) 1999-2004 Michael Shalayeff @@ -135,6 +135,11 @@ struct trapframe { unsigned long tf_pad[3]; /* pad to 256 bytes */ }; + +#ifdef _KERNEL +int setstack(struct trapframe *, u_long, register_t); +#endif /* _KERNEL */ + #endif /* !_LOCORE */ #endif /* !_MACHINE_FRAME_H_ */ diff --git a/sys/arch/hppa64/hppa64/machdep.c b/sys/arch/hppa64/hppa64/machdep.c index 8634c3e40a0..f701dddc6a7 100644 --- a/sys/arch/hppa64/hppa64/machdep.c +++ b/sys/arch/hppa64/hppa64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.45 2011/09/22 21:48:34 jsing Exp $ */ +/* $OpenBSD: machdep.c,v 1.46 2012/06/21 00:56:59 guenther Exp $ */ /* * Copyright (c) 2005 Michael Shalayeff @@ -777,6 +777,26 @@ copyout(const void *src, void *dst, size_t size) } /* + * Set up tf_sp and tf_r3 (the frame pointer) and copy out the + * frame marker and the old r3. + * XXX old_r3 is always zero on hppa64? It's non-zero on hppa in sendsig() + * XXX Set up tf_ret1 (aka "ap") too? + */ +int +setstack(struct trapframe *tf, u_long stack, register_t old_r3) +{ + static const register_t zero = 0; + int err; + + tf->tf_r3 = stack; + err = copyout(&old_r3, (caddr_t)stack, sizeof(register_t)); + + tf->tf_sp = stack += HPPA_FRAME_SIZE; + return (copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP), + sizeof(register_t)) || err); +} + +/* * Set registers on exec. */ void @@ -785,7 +805,6 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, { struct trapframe *tf = p->p_md.md_regs; struct pcb *pcb = &p->p_addr->u_pcb; - register_t zero; tf->tf_flags = TFF_SYS|TFF_LAST; tf->tf_iioq[1] = 4 + @@ -795,13 +814,8 @@ setregs(struct proc *p, struct exec_package *pack, u_long stack, tf->tf_args[1] = tf->tf_args[2] = 0; /* XXX dynload stuff */ /* setup terminal stack frame */ - stack = (stack + 0x1f) & ~0x1f; - tf->tf_r3 = stack; - tf->tf_sp = stack += HPPA_FRAME_SIZE; - tf->tf_ret1 = stack - 16; /* ap */ - zero = 0; - copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t)); - copyout(&zero, (caddr_t)(stack + HPPA_FRAME_RP), sizeof(register_t)); + setstack(tf, (stack + 0x1f) & ~0x1f, 0); + tf->tf_ret1 = tf->tf_sp - 16; /* ap */ /* reset any of the pending FPU exceptions */ fpu_proc_flush(p); @@ -827,7 +841,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, struct sigacts *psp = p->p_sigacts; struct sigcontext ksc; siginfo_t ksi; - register_t scp, sip, zero; + register_t scp, sip; int sss; #ifdef DEBUG @@ -874,12 +888,13 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, bcopy(&p->p_addr->u_pcb.pcb_fpstate->hfp_regs, ksc.sc_fpregs, sizeof(ksc.sc_fpregs)); - sss += HPPA_FRAME_SIZE; + if (setstack(tf, scp + sss, 0)) + sigexit(p, SIGILL); + tf->tf_args[0] = sig; tf->tf_args[1] = sip; tf->tf_args[2] = tf->tf_r4 = scp; tf->tf_args[3] = (register_t)catcher; - tf->tf_sp = scp + sss; tf->tf_ipsw &= ~(PSL_N|PSL_B|PSL_T); tf->tf_iioq[0] = HPPA_PC_PRIV_USER | p->p_sigcode; tf->tf_iioq[1] = tf->tf_iioq[0] + 4; @@ -889,7 +904,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n", - p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss); + p->p_pid, sig, scp, ksc.sc_fp, tf->tf_sp); #endif if (copyout(&ksc, (void *)scp, sizeof(ksc))) @@ -901,11 +916,6 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, sigexit(p, SIGILL); } - zero = 0; - if (copyout(&zero, (caddr_t)scp + sss - HPPA_FRAME_SIZE, - sizeof(register_t))) - sigexit(p, SIGILL); - #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid, diff --git a/sys/arch/hppa64/hppa64/vm_machdep.c b/sys/arch/hppa64/hppa64/vm_machdep.c index e0ab2e49822..2facb90e8c3 100644 --- a/sys/arch/hppa64/hppa64/vm_machdep.c +++ b/sys/arch/hppa64/hppa64/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.17 2011/09/22 13:50:30 deraadt Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.18 2012/06/21 00:56:59 guenther Exp $ */ /* * Copyright (c) 2005 Michael Shalayeff @@ -136,7 +136,7 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, * If specified, give the child a different stack. */ if (stack != NULL) - tf->tf_sp = (register_t)stack; + setstack(tf, (u_long)stack, 0); /* XXX ignore error? */ /* * Build stack frames for the cpu_switchto & co. diff --git a/sys/arch/sparc/sparc/vm_machdep.c b/sys/arch/sparc/sparc/vm_machdep.c index 80b24f37955..8f28e16bd3f 100644 --- a/sys/arch/sparc/sparc/vm_machdep.c +++ b/sys/arch/sparc/sparc/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.54 2011/04/07 15:30:16 miod Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.55 2012/06/21 00:56:59 guenther Exp $ */ /* $NetBSD: vm_machdep.c,v 1.30 1997/03/10 23:55:40 pk Exp $ */ /* @@ -407,12 +407,6 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) /* Copy parent's trapframe */ *tf2 = *(struct trapframe *)((int)opcb + USPACE - sizeof(*tf2)); - /* - * If specified, give the child a different stack. - */ - if (stack != NULL) - tf2->tf_out[6] = (u_int)stack + stacksize; - /* Duplicate efforts of syscall(), but slightly differently */ if (tf2->tf_global[1] & SYSCALL_G2RFLAG) { /* jmp %g2 (or %g7, deprecated) on success */ @@ -439,6 +433,16 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) rp->rw_local[0] = (int)func; /* Function to call */ rp->rw_local[1] = (int)arg; /* and its argument */ + /* + * If specified, give the child a different stack, with space + * reserved for the frame, and zero the frame pointer. + */ + if (stack != NULL) { + tf2->tf_out[6] = (u_int)stack + stacksize + - sizeof(struct frame); + rp->rw_in[6] = 0; + } + npcb->pcb_pc = (int)proc_trampoline - 8; npcb->pcb_sp = (int)rp; npcb->pcb_psr &= ~PSR_CWP; /* Run in window #0 */ diff --git a/sys/arch/sparc64/sparc64/vm_machdep.c b/sys/arch/sparc64/sparc64/vm_machdep.c index 0e7b07d4c20..c3a454f3d30 100644 --- a/sys/arch/sparc64/sparc64/vm_machdep.c +++ b/sys/arch/sparc64/sparc64/vm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm_machdep.c,v 1.27 2011/01/13 21:19:42 kettenis Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.28 2012/06/21 00:56:59 guenther Exp $ */ /* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */ /* @@ -241,10 +241,14 @@ cpu_fork(p1, p2, stack, stacksize, func, arg) *tf2 = *(struct trapframe *)((long)opcb + USPACE - sizeof(*tf2)); /* - * If specified, give the child a different stack. + * If specified, give the child a different stack, offset and + * with space reserved for the frame, and zero the frame pointer. */ - if (stack != NULL) - tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize; + if (stack != NULL) { + tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize + - (BIAS + CC64FSZ); + tf2->tf_in[6] = 0; + } /* Duplicate efforts of syscall(), but slightly differently */ if (tf2->tf_global[1] & SYSCALL_G2RFLAG) { |