This is the first demonstration of a mitigation against SROP. This is SROP: http://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf
A solution for Linux was attempted (https://lwn.net/Articles/674861), but that proposal appears to have run lightly into the ABI wall, and seems to not be integrated. Antoine did some experimental ports builds using diffs I provided during p2k16. As a result, I eventually realized how far we can push things for now (and what we could do later). Early on (like the lwn article above), I though a HMAC-like construct would be needed; but it appears it is not. Utilizing a trick from kbind(2), the kernel now only accepts signal returns from the PC address of the sigreturn(2) syscall in the signal trampoline. Since the signal trampoline page is randomized placed per process, it is only known by directly returning from a signal handler. As well, the sigcontext provided to sigreturn(2) now contains a magic cookie constructed from a per-process cookie XOR'd against the address of the signal context. That part is similar to the LWN discussion mentioned above. I came to the same conclusion semi-independently as a result of Antoine's ports builds, which identified all the parts of the application software ecosystem I had to study. Woe is me! These two changes together make it largely impossible for a sigcontext to be constructed manually, and then passed to the kernel to act upon. sigreturn(2) becomes a highly difficult gadget to use; the setup required to utilize it means the attacker probably already has sufficient codeflow control that they don't need to utilize sigreturn(2). To make the PC tracking trick work, sigreturn() provision from libc will die. This is not a standard-mandated function, it is simply a back-end piece of code to make signals actually work right. A few longjmp-style routines in libc on some architectures abused sigreturn() have been fixed. syscall(SYS_sigreturn) also becomes illegal. The process is killed if either the cookie or the PC are wrong. So far, this is running on amd64 i386 macppc sparc64 hppa sgi loongson and alpha. On sparc64, alpha, and mips64 machines, make sure your libc and static binaries are up-to-date with a very new snapshot. This is just a draft. Index: arch/alpha/alpha/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/alpha/alpha/machdep.c,v retrieving revision 1.171 diff -u -p -u -r1.171 machdep.c --- arch/alpha/alpha/machdep.c 21 Oct 2015 07:59:17 -0000 1.171 +++ arch/alpha/alpha/machdep.c 29 Apr 2016 13:17:40 -0000 @@ -1477,6 +1477,7 @@ sendsig(catcher, sig, mask, code, type, } else sip = NULL; + ksc.sc_cookie = scp ^ p->p_p->ps_sigcookie; /* * copy the frame out to userland. */ @@ -1542,9 +1543,7 @@ sys_sigreturn(p, v, retval) } */ *uap = v; struct sigcontext ksc; struct fpreg *fpregs = (struct fpreg *)&ksc.sc_fpregs; -#ifdef DEBUG - struct sigcontext *scp; -#endif + struct sigcontext *scp = SCARG(uap, sigcntxp); int error; #ifdef DEBUG @@ -1552,12 +1551,32 @@ sys_sigreturn(p, v, retval) printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); #endif + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + /* * Test and fetch the context structure. * We grab it all at once for speed. */ - if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0) + if ((error = copyin(scp, &ksc, sizeof(ksc))) != 0) return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */ return (EINVAL); Index: arch/alpha/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/alpha/include/signal.h,v retrieving revision 1.9 diff -u -p -u -r1.9 signal.h --- arch/alpha/include/signal.h 7 Nov 2015 19:06:05 -0000 1.9 +++ arch/alpha/include/signal.h 8 May 2016 14:05:16 -0000 @@ -48,7 +48,7 @@ typedef int sig_atomic_t; */ struct sigcontext { long __sc_unused; - long sc_mask; /* signal mask to restore */ + long sc_mask; /* signal mask to restore XXX should be int */ long sc_pc; /* pc to restore */ long sc_ps; /* ps to restore */ unsigned long sc_regs[32]; /* integer register set (see above) */ Index: arch/amd64/amd64/locore.S =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/locore.S,v retrieving revision 1.76 diff -u -p -u -r1.76 locore.S --- arch/amd64/amd64/locore.S 26 Feb 2016 02:23:07 -0000 1.76 +++ arch/amd64/amd64/locore.S 29 Apr 2016 11:30:11 -0000 @@ -763,6 +763,8 @@ NENTRY(sigcode) pushq %rdi /* fake return address */ movq $SYS_sigreturn,%rax syscall + .globl _C_LABEL(sigcoderet) +_C_LABEL(sigcoderet): movq $SYS_exit,%rax syscall .globl _C_LABEL(esigcode) Index: arch/amd64/amd64/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/machdep.c,v retrieving revision 1.218 diff -u -p -u -r1.218 machdep.c --- arch/amd64/amd64/machdep.c 3 Apr 2016 17:48:33 -0000 1.218 +++ arch/amd64/amd64/machdep.c 29 Apr 2016 13:24:11 -0000 @@ -571,6 +571,7 @@ sendsig(sig_t catcher, int sig, int mask } scp = sp - sss; + ksc.sc_cookie = scp ^ p->p_p->ps_sigcookie; if (copyout(&ksc, (void *)scp, sizeof(ksc))) sigexit(p, SIGILL); @@ -611,17 +612,31 @@ sys_sigreturn(struct proc *p, void *v, r struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp, ksc; + struct sigcontext *scp = SCARG(uap, sigcntxp), ksc; struct trapframe *tf = p->p_md.md_regs; int error; - scp = SCARG(uap, sigcntxp); -#ifdef DEBUG - if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) - printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); -#endif + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcoderet) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + if ((error = copyin((caddr_t)scp, &ksc, sizeof ksc))) return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); if (((ksc.sc_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 || !USERMODE(ksc.sc_cs, ksc.sc_eflags)) Index: arch/amd64/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/signal.h,v retrieving revision 1.8 diff -u -p -u -r1.8 signal.h --- arch/amd64/include/signal.h 1 Apr 2013 17:18:19 -0000 1.8 +++ arch/amd64/include/signal.h 8 May 2016 14:02:07 -0000 @@ -81,7 +81,7 @@ struct sigcontext { long sc_ss; struct fxsave64 *sc_fpstate; - int __sc_unused; + long sc_cookie; int sc_mask; }; #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ Index: arch/arm/arm/sig_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/sig_machdep.c,v retrieving revision 1.12 diff -u -p -u -r1.12 sig_machdep.c --- arch/arm/arm/sig_machdep.c 31 Jan 2016 00:14:50 -0000 1.12 +++ arch/arm/arm/sig_machdep.c 29 Apr 2016 13:06:47 -0000 @@ -136,6 +136,7 @@ sendsig(sig_t catcher, int sig, int retu initsiginfo(&frame.sf_si, sig, code, type, val); } + frame.sf_sc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal @@ -182,23 +183,31 @@ sys_sigreturn(struct proc *p, void *v, r struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp, context; + struct sigcontext *scp = SCARG(uap, sigcntxp), context; struct trapframe *tf; - /* - * we do a rather scary test in userland - */ - if (v == NULL) - return (EFAULT); - - /* - * The trampoline code hands us the context. - * It is unsafe to keep track of it ourselves, in the event that a - * program jumps out of a signal handler. - */ - scp = SCARG(uap, sigcntxp); + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) return (EFAULT); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); /* * Make sure the processor mode has not been tampered with and Index: arch/arm/arm/sigcode.S =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/sigcode.S,v retrieving revision 1.2 diff -u -p -u -r1.2 sigcode.S --- arch/arm/arm/sigcode.S 27 Dec 2006 17:49:26 -0000 1.2 +++ arch/arm/arm/sigcode.S 29 Apr 2016 09:42:45 -0000 @@ -52,6 +52,8 @@ ENTRY_NP(sigcode) add r0, sp, #SIGF_SC ldr r12, =SYS_sigreturn swi SYS_sigreturn + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): /* Well if that failed we better exit quick ! */ Index: arch/arm/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/arm/include/signal.h,v retrieving revision 1.8 diff -u -p -u -r1.8 signal.h --- arch/arm/include/signal.h 2 Dec 2012 07:03:31 -0000 1.8 +++ arch/arm/include/signal.h 29 Apr 2016 08:38:34 -0000 @@ -61,8 +61,8 @@ typedef int sig_atomic_t; * a non-standard exit is performed. */ struct sigcontext { - int __sc_unused; - int sc_mask; /* signal mask to restore (old style) */ + long sc_cookie; + int sc_mask; /* signal mask to restore */ unsigned int sc_spsr; unsigned int sc_r0; Index: arch/hppa/hppa/locore.S =================================================================== RCS file: /cvs/src/sys/arch/hppa/hppa/locore.S,v retrieving revision 1.193 diff -u -p -u -r1.193 locore.S --- arch/hppa/hppa/locore.S 23 Oct 2014 16:57:45 -0000 1.193 +++ arch/hppa/hppa/locore.S 29 Apr 2016 09:42:33 -0000 @@ -3040,6 +3040,8 @@ sigcode_call ldil L%SYSCALLGATE, r1 copy r4, arg0 .call + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): ble 4(sr7, r1) ldi SYS_sigreturn, t1 Index: arch/hppa/hppa/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/hppa/hppa/machdep.c,v retrieving revision 1.243 diff -u -p -u -r1.243 machdep.c --- arch/hppa/hppa/machdep.c 20 Apr 2016 23:52:04 -0000 1.243 +++ arch/hppa/hppa/machdep.c 29 Apr 2016 12:56:01 -0000 @@ -1303,6 +1303,7 @@ sendsig(sig_t catcher, int sig, int mask p->p_pid, sig, scp, ksc.sc_fp, tf->tf_sp); #endif + ksc.sc_cookie = scp ^ p->p_p->ps_sigcookie; if (copyout(&ksc, (void *)scp, sizeof(ksc))) sigexit(p, SIGILL); @@ -1329,11 +1330,31 @@ sys_sigreturn(struct proc *p, void *v, r struct trapframe *tf = p->p_md.md_regs; int error; + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + scp = SCARG(uap, sigcntxp); #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); #endif + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); /* Flush the FPU context first. */ fpu_proc_flush(p); Index: arch/hppa/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/hppa/include/signal.h,v retrieving revision 1.11 diff -u -p -u -r1.11 signal.h --- arch/hppa/include/signal.h 1 Apr 2013 17:18:20 -0000 1.11 +++ arch/hppa/include/signal.h 8 May 2016 14:04:42 -0000 @@ -47,15 +47,15 @@ typedef int sig_atomic_t; * a non-standard exit is performed. */ struct sigcontext { - unsigned long __sc_unused; - unsigned long sc_mask; /* signal mask to restore */ - unsigned long sc_ps; /* psl to restore */ - unsigned long sc_fp; /* fp to restore */ - unsigned long sc_pcoqh; /* pc offset queue (head) to restore */ - unsigned long sc_pcoqt; /* pc offset queue (tail) to restore */ - unsigned long sc_resv[2]; - unsigned long sc_regs[32]; - unsigned long sc_fpregs[64]; + long sc_cookie; + long sc_mask; /* signal mask to restore XXX should be int */ + u_long sc_ps; /* psl to restore */ + u_long sc_fp; /* fp to restore */ + u_long sc_pcoqh; /* pc offset queue (head) to restore */ + u_long sc_pcoqt; /* pc offset queue (tail) to restore */ + u_long sc_resv[2]; + u_long sc_regs[32]; + u_long sc_fpregs[64]; }; #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ #endif /* !_MACHINE_SIGNAL_H_ */ Index: arch/hppa64/hppa64/locore.S =================================================================== RCS file: /cvs/src/sys/arch/hppa64/hppa64/locore.S,v retrieving revision 1.41 diff -u -p -u -r1.41 locore.S --- arch/hppa64/hppa64/locore.S 12 Oct 2011 18:30:09 -0000 1.41 +++ arch/hppa64/hppa64/locore.S 29 Apr 2016 09:42:29 -0000 @@ -1968,6 +1968,8 @@ ENTRY(sigcode,0) depd %r0, 31, 32, %r1 copy %r4, %arg0 .call + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): ble 4(%sr7, %r1) ldi SYS_sigreturn, %r1 Index: arch/hppa64/hppa64/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/hppa64/hppa64/machdep.c,v retrieving revision 1.79 diff -u -p -u -r1.79 machdep.c --- arch/hppa64/hppa64/machdep.c 20 Apr 2016 23:52:04 -0000 1.79 +++ arch/hppa64/hppa64/machdep.c 29 Apr 2016 13:04:16 -0000 @@ -900,6 +900,7 @@ sendsig(sig_t catcher, int sig, int mask p->p_pid, sig, scp, ksc.sc_fp, tf->tf_sp); #endif + ksc.sc_cookie = scp ^ p->p_p->ps_sigcookie; if (copyout(&ksc, (void *)scp, sizeof(ksc))) sigexit(p, SIGILL); @@ -922,21 +923,35 @@ sys_sigreturn(struct proc *p, void *v, r struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp, ksc; + struct sigcontext *scp = SCARG(uap, sigcntxp), ksc; struct trapframe *tf = p->p_md.md_regs; int error; - scp = SCARG(uap, sigcntxp); -#ifdef DEBUG - if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) - printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); -#endif + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } /* flush the FPU ctx first */ fpu_proc_flush(p); if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))) return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); #define PSL_MBS (PSL_C|PSL_Q|PSL_P|PSL_D|PSL_I) #define PSL_MBZ (PSL_Y|PSL_Z|PSL_S|PSL_X|PSL_M|PSL_R) Index: arch/hppa64/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/hppa64/include/signal.h,v retrieving revision 1.6 diff -u -p -u -r1.6 signal.h --- arch/hppa64/include/signal.h 1 Apr 2013 17:18:20 -0000 1.6 +++ arch/hppa64/include/signal.h 8 May 2016 14:04:20 -0000 @@ -47,8 +47,8 @@ typedef int sig_atomic_t; * a non-standard exit is performed. */ struct sigcontext { - unsigned long __sc_unused; - unsigned long sc_mask; /* signal mask to restore */ + long sc_cookie; + long sc_mask; /* signal mask to restore XXX should be int */ unsigned long sc_ps; /* psl to restore */ unsigned long sc_fp; /* fp to restore */ unsigned long sc_pcoqh; /* pc offset queue (head) to restore */ Index: arch/i386/i386/locore.s =================================================================== RCS file: /cvs/src/sys/arch/i386/i386/locore.s,v retrieving revision 1.167 diff -u -p -u -r1.167 locore.s --- arch/i386/i386/locore.s 15 Mar 2016 03:17:51 -0000 1.167 +++ arch/i386/i386/locore.s 28 Apr 2016 13:11:24 -0000 @@ -697,6 +697,8 @@ NENTRY(sigcode) pushl %eax # junk to fake return address movl $SYS_sigreturn,%eax int $0x80 # enter kernel with args on stack + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): movl $SYS_exit,%eax int $0x80 # exit if sigreturn fails .globl _C_LABEL(esigcode) Index: arch/i386/i386/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/i386/i386/machdep.c,v retrieving revision 1.583 diff -u -p -u -r1.583 machdep.c --- arch/i386/i386/machdep.c 24 Mar 2016 04:56:08 -0000 1.583 +++ arch/i386/i386/machdep.c 29 Apr 2016 13:03:21 -0000 @@ -2440,6 +2440,7 @@ sendsig(sig_t catcher, int sig, int mask } /* XXX don't copyout siginfo if not needed? */ + frame.sf_sc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal @@ -2479,18 +2480,32 @@ sys_sigreturn(struct proc *p, void *v, r struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp, context; + struct sigcontext *scp = SCARG(uap, sigcntxp), context; struct trapframe *tf = p->p_md.md_regs; int error; - /* - * The trampoline code hands us the context. - * It is unsafe to keep track of it ourselves, in the event that a - * program jumps out of a signal handler. - */ - scp = SCARG(uap, sigcntxp); - if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) + if (PROC_PC(p) != (u_int32_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn from non-tramp location [pc 0x%lu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + + if (error = copyin((caddr_t)scp, &context, sizeof(*scp))) + return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); /* * Restore signal context. Index: arch/i386/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/i386/include/signal.h,v retrieving revision 1.10 diff -u -p -u -r1.10 signal.h --- arch/i386/include/signal.h 1 Apr 2013 17:18:20 -0000 1.10 +++ arch/i386/include/signal.h 29 Apr 2016 08:34:59 -0000 @@ -70,7 +70,7 @@ struct sigcontext { int sc_esp; int sc_ss; - int __sc_unused; + long sc_cookie; int sc_mask; /* signal mask to restore */ int sc_trapno; /* XXX should be above */ Index: arch/m88k/m88k/sig_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/m88k/m88k/sig_machdep.c,v retrieving revision 1.23 diff -u -p -u -r1.23 sig_machdep.c --- arch/m88k/m88k/sig_machdep.c 9 Feb 2015 08:48:23 -0000 1.23 +++ arch/m88k/m88k/sig_machdep.c 29 Apr 2016 13:02:27 -0000 @@ -207,18 +207,34 @@ sys_sigreturn(struct proc *p, void *v, r struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp; + struct sigcontext *scp = SCARG(uap, sigcntxp); struct trapframe *tf; struct sigcontext ksc; - scp = (struct sigcontext *)SCARG(uap, sigcntxp); -#ifdef DEBUG - if (sigdebug & SDB_FOLLOW) - printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); -#endif - if (((vaddr_t)scp & 3) != 0 || - copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(struct sigcontext))) + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + + if (((vaddr_t)scp & 3) != 0) return (EINVAL); + if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(*scp)))) + return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); tf = p->p_md.md_tf; scp = &ksc; Index: arch/m88k/m88k/subr.S =================================================================== RCS file: /cvs/src/sys/arch/m88k/m88k/subr.S,v retrieving revision 1.24 diff -u -p -u -r1.24 subr.S --- arch/m88k/m88k/subr.S 8 Jun 2014 13:20:39 -0000 1.24 +++ arch/m88k/m88k/subr.S 29 Apr 2016 09:42:18 -0000 @@ -1087,6 +1087,8 @@ ENTRY(sigcode) /* r31 points to sigfra ld %r2, %r31, 0 /* pick sigcontext* */ or %r13, %r0, SYS_sigreturn tb0 0, %r0, 450 /* syscall trap, calling sigreturn */ + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): NOP | failure return #ifdef dontbother /* sigreturn will not return unless it fails */ NOP | success return Index: arch/macppc/macppc/locore.S =================================================================== RCS file: /cvs/src/sys/arch/macppc/macppc/locore.S,v retrieving revision 1.53 diff -u -p -u -r1.53 locore.S --- arch/macppc/macppc/locore.S 25 Apr 2016 07:58:14 -0000 1.53 +++ arch/macppc/macppc/locore.S 29 Apr 2016 09:41:53 -0000 @@ -1250,6 +1250,8 @@ _C_LABEL(sigcode): addi %r3,%r1,((16+FPSIG_SIZEOF+15)&~0xf)+SF_SC /* compute &sf_sc */ li %r0,SYS_sigreturn sc /* sigreturn(scp) */ + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): li %r0,SYS_exit sc /* exit(errno) */ _C_LABEL(esigcode): Index: arch/macppc/macppc/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/macppc/machdep.c,v retrieving revision 1.173 diff -u -p -u -r1.173 machdep.c --- arch/macppc/macppc/machdep.c 20 Apr 2016 23:52:04 -0000 1.173 +++ arch/macppc/macppc/machdep.c 29 Apr 2016 13:01:05 -0000 @@ -481,6 +481,7 @@ sendsig(sig_t catcher, int sig, int mask frame.sf_sip = &fp->sf_si; initsiginfo(&frame.sf_si, sig, code, type, val); } + frame.sc_sc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (copyout(&frame, fp, sizeof frame) != 0) sigexit(p, SIGILL); @@ -512,8 +513,29 @@ sys_sigreturn(struct proc *p, void *v, r struct trapframe *tf; int error; + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc))) return error; + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); + tf = trapframe(p); sc.sc_frame.srr1 &= ~PSL_VEC; sc.sc_frame.srr1 |= (tf->srr1 & PSL_VEC); Index: arch/mips64/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/mips64/include/signal.h,v retrieving revision 1.10 diff -u -p -u -r1.10 signal.h --- arch/mips64/include/signal.h 2 Dec 2012 07:03:31 -0000 1.10 +++ arch/mips64/include/signal.h 8 May 2016 14:03:47 -0000 @@ -56,8 +56,8 @@ typedef int sig_atomic_t; * a non-standard exit is performed. */ struct sigcontext { - long __sc_unused; - long sc_mask; /* signal mask to restore */ + long sc_cookie; + long sc_mask; /* signal mask to restore XXX should be int */ __register_t sc_pc; /* pc at time of signal */ __register_t sc_regs[32]; /* processor regs 0 to 31 */ __register_t mullo; /* mullo and mulhi registers... */ Index: arch/mips64/mips64/lcore_access.S =================================================================== RCS file: /cvs/src/sys/arch/mips64/mips64/lcore_access.S,v retrieving revision 1.24 diff -u -p -u -r1.24 lcore_access.S --- arch/mips64/mips64/lcore_access.S 3 Oct 2012 11:18:23 -0000 1.24 +++ arch/mips64/mips64/lcore_access.S 29 Apr 2016 09:41:47 -0000 @@ -77,6 +77,8 @@ sigcode: PTR_ADDU a0, sp, 4*REGSZ # address of sigcontext LI v0, SYS_sigreturn # sigreturn(scp) syscall + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): break 0 # just in case sigreturn fails .globl esigcode esigcode: Index: arch/mips64/mips64/sendsig.c =================================================================== RCS file: /cvs/src/sys/arch/mips64/mips64/sendsig.c,v retrieving revision 1.25 diff -u -p -u -r1.25 sendsig.c --- arch/mips64/mips64/sendsig.c 6 Mar 2016 19:42:27 -0000 1.25 +++ arch/mips64/mips64/sendsig.c 29 Apr 2016 13:00:16 -0000 @@ -164,6 +164,7 @@ sendsig(catcher, sig, mask, code, type, goto bail; } + sf.sf_sc.sc_cookie = (caddr_t)&fp->sf_sc ^ p->p_p->ps_sigcookie; if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) { bail: /* @@ -215,34 +216,45 @@ sys_sigreturn(p, v, retval) struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp; + struct sigcontext *scp = SCARG(uap, sigcntxp); struct trapframe *regs; struct sigcontext ksc; int error; - scp = SCARG(uap, sigcntxp); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); #endif regs = p->p_md.md_regs; + + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + /* * Test and fetch the context structure. * We grab it all at once for speed. */ error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc)); - if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) { -#ifdef DEBUG - if (!(sigdebug & SDB_FOLLOW)) - printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); - printf(" old sp %lx ra %lx pc %lx\n", - regs->sp, regs->ra, regs->pc); - printf(" new sp %lx ra %lx pc %lx err %d z %lx\n", - ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC], - error, ksc.sc_regs[ZERO]); -#endif - return (EINVAL); + if (error) + return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); + scp = &ksc; /* * Restore the user supplied information Index: arch/powerpc/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/powerpc/include/signal.h,v retrieving revision 1.8 diff -u -p -u -r1.8 signal.h --- arch/powerpc/include/signal.h 2 Dec 2012 07:03:31 -0000 1.8 +++ arch/powerpc/include/signal.h 29 Apr 2016 08:33:27 -0000 @@ -64,7 +64,7 @@ struct trapframe { }; struct sigcontext { - int __sc_unused; + long sc_cookie; int sc_mask; /* saved signal mask */ struct trapframe sc_frame; /* saved registers */ }; Index: arch/sh/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/sh/include/signal.h,v retrieving revision 1.6 diff -u -p -u -r1.6 signal.h --- arch/sh/include/signal.h 2 Dec 2012 07:03:31 -0000 1.6 +++ arch/sh/include/signal.h 8 May 2016 14:02:49 -0000 @@ -52,12 +52,12 @@ struct sigcontext { int sc_reg[21]; int sc_fpreg[34]; - int __sc_unused; + long sc_cookie; int sc_expevt; /* XXX should be above */ int sc_err; - unsigned int sc_mask; /* signal mask to restore */ + int sc_mask; /* signal mask to restore */ }; #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ Index: arch/sh/sh/locore_subr.S =================================================================== RCS file: /cvs/src/sys/arch/sh/sh/locore_subr.S,v retrieving revision 1.10 diff -u -p -u -r1.10 locore_subr.S --- arch/sh/sh/locore_subr.S 6 Sep 2010 08:00:31 -0000 1.10 +++ arch/sh/sh/locore_subr.S 29 Apr 2016 09:41:36 -0000 @@ -493,6 +493,8 @@ NENTRY(sigcode) mov r15, r4 /* get pointer to sigcontext */ mov.l .L_SYS_sigreturn, r0 trapa #0x80 /* and call sigreturn() */ + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): mov.l .L_SYS_exit, r0 trapa #0x80 /* exit if sigreturn fails */ /* NOTREACHED */ Index: arch/sh/sh/sh_machdep.c =================================================================== RCS file: /cvs/src/sys/arch/sh/sh/sh_machdep.c,v retrieving revision 1.42 diff -u -p -u -r1.42 sh_machdep.c --- arch/sh/sh/sh_machdep.c 5 Mar 2016 17:16:33 -0000 1.42 +++ arch/sh/sh/sh_machdep.c 29 Apr 2016 12:58:44 -0000 @@ -486,6 +486,7 @@ sendsig(sig_t catcher, int sig, int mask /* frame.sf_uc.sc_err = 0; */ frame.sf_uc.sc_mask = mask; + frame.sf_uc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal @@ -519,18 +520,32 @@ sys_sigreturn(struct proc *p, void *v, r struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext *scp, context; + struct sigcontext *scp = SCARG(uap, sigcntxp), context; struct trapframe *tf; int error; - /* - * The trampoline code hands us the context. - * It is unsafe to keep track of it ourselves, in the event that a - * program jumps out of a signal handler. - */ - scp = SCARG(uap, sigcntxp); + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + if ((error = copyin((caddr_t)scp, &context, sizeof(*scp))) != 0) return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); /* Restore signal context. */ tf = p->p_md.md_regs; Index: arch/socppc/socppc/locore.S =================================================================== RCS file: /cvs/src/sys/arch/socppc/socppc/locore.S,v retrieving revision 1.20 diff -u -p -u -r1.20 locore.S --- arch/socppc/socppc/locore.S 25 Apr 2016 07:58:14 -0000 1.20 +++ arch/socppc/socppc/locore.S 29 Apr 2016 09:41:28 -0000 @@ -1269,6 +1269,8 @@ _C_LABEL(sigcode): addi %r3,%r1,((16+FPSIG_SIZEOF+15)&~0xf)+SF_SC /* compute &sf_sc */ li %r0,SYS_sigreturn sc /* sigreturn(scp) */ + .globl _C_LABEL(sigcode_sigreturn) +_C_LABEL(sigcode_sigreturn): li %r0,SYS_exit sc /* exit(errno) */ _C_LABEL(esigcode): Index: arch/socppc/socppc/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/socppc/socppc/machdep.c,v retrieving revision 1.65 diff -u -p -u -r1.65 machdep.c --- arch/socppc/socppc/machdep.c 3 Mar 2016 02:42:16 -0000 1.65 +++ arch/socppc/socppc/machdep.c 29 Apr 2016 12:57:25 -0000 @@ -508,6 +508,7 @@ sendsig(sig_t catcher, int sig, int mask frame.sf_sip = &fp->sf_si; initsiginfo(&frame.sf_si, sig, code, type, val); } + frame.sf_sc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (copyout(&frame, fp, sizeof frame) != 0) sigexit(p, SIGILL); @@ -539,8 +540,30 @@ sys_sigreturn(struct proc *p, void *v, r struct trapframe *tf; int error; + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn not from sigtramp [pc 0x%llu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc))) return error; + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); + } + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); + + tf = trapframe(p); if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) return EINVAL; Index: arch/sparc/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/sparc/include/signal.h,v retrieving revision 1.11 diff -u -p -u -r1.11 signal.h --- arch/sparc/include/signal.h 1 Apr 2013 17:18:20 -0000 1.11 +++ arch/sparc/include/signal.h 29 Apr 2016 08:36:22 -0000 @@ -58,7 +58,7 @@ typedef int sig_atomic_t; * a non-standard exit is performed. */ struct sigcontext { - int __sc_unused; + long sc_cookie; int sc_mask; /* signal mask to restore */ /* begin machine dependent portion */ int sc_sp; /* %sp to restore */ Index: arch/sparc/sparc/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/sparc/sparc/machdep.c,v retrieving revision 1.175 diff -u -p -u -r1.175 machdep.c --- arch/sparc/sparc/machdep.c 21 Oct 2015 07:59:18 -0000 1.175 +++ arch/sparc/sparc/machdep.c 29 Apr 2016 12:55:39 -0000 @@ -432,7 +432,7 @@ sendsig(catcher, sig, mask, code, type, */ newsp = (int)fp - sizeof(struct rwindow); write_user_windows(); - /* XXX do not copyout siginfo if not needed */ + sf.sf_sc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || copyout(&oldsp, &((struct rwindow *)newsp)->rw_in[6], sizeof(register_t)) != 0) { @@ -499,6 +499,15 @@ sys_sigreturn(p, v, retval) printf("sigreturn: %s[%d], sigcntxp %p\n", p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); #endif + if (PROC_PC(p) != p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn from non-tramp location [pc 0x%lu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + + if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0) return (error); tf = p->p_md.md_tf; Index: arch/sparc64/include/signal.h =================================================================== RCS file: /cvs/src/sys/arch/sparc64/include/signal.h,v retrieving revision 1.11 diff -u -p -u -r1.11 signal.h --- arch/sparc64/include/signal.h 1 Apr 2013 17:18:20 -0000 1.11 +++ arch/sparc64/include/signal.h 29 Apr 2016 08:24:30 -0000 @@ -58,8 +58,7 @@ typedef int sig_atomic_t; * a non-standard exit is performed. */ struct sigcontext { - int __sc_unused; - int __sc_mask13; /* signal mask to restore (old style) */ + long sc_cookie; /* begin machine dependent portion */ long sc_sp; /* %sp to restore */ long sc_pc; /* pc to restore */ @@ -67,7 +66,7 @@ struct sigcontext { long sc_tstate; /* tstate to restore */ long sc_g1; /* %g1 to restore */ long sc_o0; /* %o0 to restore */ - int sc_mask; /* signal mask to restore (new style) */ + int sc_mask; /* signal mask to restore */ }; #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ #endif /* _LOCORE */ Index: arch/sparc64/sparc64/machdep.c =================================================================== RCS file: /cvs/src/sys/arch/sparc64/sparc64/machdep.c,v retrieving revision 1.175 diff -u -p -u -r1.175 machdep.c --- arch/sparc64/sparc64/machdep.c 7 Mar 2016 13:21:51 -0000 1.175 +++ arch/sparc64/sparc64/machdep.c 29 Apr 2016 13:30:40 -0000 @@ -492,7 +492,7 @@ sendsig(catcher, sig, mask, code, type, newsp = (vaddr_t)fp - sizeof(struct rwindow); write_user_windows(); - /* XXX do not copyout siginfo if not needed */ + sf.sf_sc.sc_cookie = fp ^ p->p_p->ps_sigcookie; if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || CPOUTREG(&(((struct rwindow *)newsp)->rw_in[6]), tf->tf_out[6])) { /* @@ -544,10 +544,18 @@ sys_sigreturn(p, v, retval) struct sys_sigreturn_args /* { syscallarg(struct sigcontext *) sigcntxp; } */ *uap = v; - struct sigcontext sc, *scp; + struct sigcontext *scp = SCARG(uap, sigcntxp), ksc; struct trapframe64 *tf; int error = EINVAL; + if (PROC_PC(p) != (u_int64_t)p->p_p->ps_sigcode + + (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) { + printf("%s(%d): sigreturn from non-tramp location [pc 0x%lu]\n", + p->p_comm, p->p_pid, PROC_PC(p)); + sigexit(p, SIGILL); + return (EPERM); + } + /* First ensure consistent stack state (see sendsig). */ write_user_windows(); @@ -558,15 +566,25 @@ sys_sigreturn(p, v, retval) #endif sigexit(p, SIGILL); } - scp = SCARG(uap, sigcntxp); - if ((vaddr_t)scp & 3 || - (error = copyin((caddr_t)scp, &sc, sizeof sc)) != 0) { -#ifdef DEBUG - printf("sigreturn: copyin failed: scp=%p\n", scp); -#endif + + if ((vaddr_t)scp & 3) + return (EINVAL); + if ((error = copyin((caddr_t)scp, &ksc, sizeof ksc))) return (error); + + if (ksc.sc_cookie != ((long long)scp ^ p->p_p->ps_sigcookie)) { + printf("%s(%d): cookie %8lx should have been %8lx\n", + p->p_comm, p->p_pid, ksc.sc_cookie, (long)scp); + return (EFAULT); } - scp = ≻ + + /* Prevent reuse of the sigcontext cookie */ + ksc.sc_cookie = 0; + (void)copyout(&ksc.sc_cookie, (caddr_t)scp + + offsetof(struct sigcontext, sc_cookie), + sizeof (ksc.sc_cookie)); + + scp = &ksc; tf = p->p_md.md_tf; /* Index: kern/exec_elf.c =================================================================== RCS file: /cvs/src/sys/kern/exec_elf.c,v retrieving revision 1.120 diff -u -p -u -r1.120 exec_elf.c --- kern/exec_elf.c 28 Feb 2016 15:46:18 -0000 1.120 +++ kern/exec_elf.c 29 Apr 2016 11:30:28 -0000 @@ -108,7 +108,7 @@ void ELFNAME(load_psection)(struct exec_ Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int); int ELFNAMEEND(coredump)(struct proc *, void *); -extern char sigcode[], esigcode[]; +extern char sigcode[], esigcode[], sigcoderet[]; #ifdef SYSCALL_DEBUG extern char *syscallnames[]; #endif @@ -145,6 +145,7 @@ struct emul ELFNAMEEND(emul) = { ELFNAMEEND(coredump), sigcode, esigcode, + sigcoderet, EMUL_ENABLED | EMUL_NATIVE, }; Index: kern/init_main.c =================================================================== RCS file: /cvs/src/sys/kern/init_main.c,v retrieving revision 1.250 diff -u -p -u -r1.250 init_main.c --- kern/init_main.c 3 May 2016 14:52:39 -0000 1.250 +++ kern/init_main.c 8 May 2016 14:07:04 -0000 @@ -144,7 +144,7 @@ void kqueue_init(void); void taskq_init(void); void pool_gc_pages(void *); -extern char sigcode[], esigcode[]; +extern char sigcode[], esigcode[], sigcoderet[]; #ifdef SYSCALL_DEBUG extern char *syscallnames[]; #endif @@ -168,6 +168,7 @@ struct emul emul_native = { NULL, /* coredump */ sigcode, esigcode, + sigcoderet, EMUL_ENABLED | EMUL_NATIVE, }; Index: kern/kern_exec.c =================================================================== RCS file: /cvs/src/sys/kern/kern_exec.c,v retrieving revision 1.176 diff -u -p -u -r1.176 kern_exec.c --- kern/kern_exec.c 25 Apr 2016 20:00:33 -0000 1.176 +++ kern/kern_exec.c 29 Apr 2016 13:24:54 -0000 @@ -498,6 +498,7 @@ sys_execve(struct proc *p, void *v, regi TCB_SET(p, NULL); /* reset the TCB address */ pr->ps_kbind_addr = 0; /* reset the kbind bits */ pr->ps_kbind_cookie = 0; + arc4random_buf(&pr->ps_sigcookie, sizeof pr->ps_sigcookie); /* set command name & other accounting info */ memset(p->p_comm, 0, sizeof(p->p_comm)); @@ -867,6 +868,8 @@ exec_sigcode_map(struct process *pr, str uao_detach(e->e_sigobject); return (ENOMEM); } + pr->ps_sigcoderet = pr->ps_sigcode + + (pr->ps_emul->e_esigret - pr->ps_emul->e_sigcode); return (0); } Index: sys/proc.h =================================================================== RCS file: /cvs/src/sys/sys/proc.h,v retrieving revision 1.219 diff -u -p -u -r1.219 proc.h --- sys/proc.h 25 Apr 2016 20:18:31 -0000 1.219 +++ sys/proc.h 29 Apr 2016 13:23:47 -0000 @@ -107,6 +107,7 @@ struct emul { int (*e_coredump)(struct proc *, void *cookie); char *e_sigcode; /* Start of sigcode */ char *e_esigcode; /* End of sigcode */ + char *e_esigret; /* sigaction RET position */ int e_flags; /* Flags, see below */ struct uvm_object *e_sigobject; /* shared sigcode object */ /* Per-process hooks */ @@ -200,6 +201,7 @@ struct process { vaddr_t ps_strings; /* User pointers to argv/env */ vaddr_t ps_stackgap; /* User pointer to the "stackgap" */ vaddr_t ps_sigcode; /* User pointer to the signal code */ + vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */ u_int ps_rtableid; /* Process routing table/domain. */ char ps_nice; /* Process "nice" value. */ @@ -216,6 +218,7 @@ struct process { struct whitepaths *ps_pledgepaths; int64_t ps_kbind_cookie; + int64_t ps_sigcookie; u_long ps_kbind_addr; /* End area that is copied on creation. */
