> This is the first demonstration of a mitigation against SROP.
> 
> This is SROP:  http://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf

Here is a better diff, which reduces change of the amd64 ABI.

Index: arch/alpha/alpha/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/alpha/alpha/locore.s,v
retrieving revision 1.43
diff -u -p -u -r1.43 locore.s
--- arch/alpha/alpha/locore.s   20 Jul 2015 07:45:23 -0000      1.43
+++ arch/alpha/alpha/locore.s   8 May 2016 19:02:24 -0000
@@ -273,6 +273,8 @@ NESTED(sigcode,0,0,ra,0,0)
        ldq     a0, 0(sp)               /* get the sigcontext pointer */
        lda     sp, 16(sp)
        CALLSYS_NOERROR(sigreturn)      /* and call sigreturn() with it. */
+       .globl  sigcoderet
+sigcoderet:
        mov     v0, a0                  /* if that failed, get error code */
        CALLSYS_NOERROR(exit)           /* and call exit() with it. */
 XNESTED(esigcode,0)
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  9 May 2016 15:01:45 -0000
@@ -1477,9 +1477,7 @@ sendsig(catcher, sig, mask, code, type, 
        } else
                sip = NULL;
 
-       /*
-        * copy the frame out to userland.
-        */
+       ksc.sc_cookie = (long)scp ^ p->p_p->ps_sigcookie;
        if (copyout((caddr_t)&ksc, (caddr_t)scp, kscsize) != 0) {
 trash:
 #ifdef DEBUG
@@ -1542,9 +1540,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 +1548,29 @@ sys_sigreturn(p, v, retval)
            printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
 #endif
 
+       if (PROC_PC(p) != (long)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%lx tramp 
0x%lx]\n",
+                   p->p_comm, p->p_pid, PROC_PC(p),
+                   (long)p->p_p->ps_sigcode +
+                   (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode));
+               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)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 ^ p->p_p->ps_sigcookie);
+               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 17:14:33 -0000
@@ -47,8 +47,8 @@ typedef int   sig_atomic_t;
  * representations of 'struct reg' and 'struct fpreg', respectively.
  */
 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 */
        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   8 May 2016 19:01:31 -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  8 May 2016 16:06:10 -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,32 @@ 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 ^ p->p_p->ps_sigcookie);
+               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 9 May 2016 16:33:33 -0000
@@ -83,6 +83,7 @@ struct sigcontext {
        struct fxsave64 *sc_fpstate;
        int     __sc_unused;
        int     sc_mask;
+       long    sc_cookie;
 };
 #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */
 #endif /* !_MACHINE_SIGNAL_H_ */
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  9 May 2016 15:24:35 -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) != (long)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      8 May 2016 15:43:48 -0000
@@ -52,6 +52,8 @@ ENTRY_NP(sigcode)
        add     r0, sp, #SIGF_SC
        ldr     r12, =SYS_sigreturn
        swi     SYS_sigreturn
+       .globl  _C_LABEL(sigcoderet)
+_C_LABEL(sigcoderet):
 
 /* 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   8 May 2016 15:29:46 -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     8 May 2016 19:40:02 -0000
@@ -3042,6 +3042,8 @@ sigcode_call
        .call
        ble     4(sr7, r1)
        ldi     SYS_sigreturn, t1
+       .globl  sigcoderet
+sigcoderet:
 
        ldil    L%SYSCALLGATE, r1
        copy    ret0, arg0
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    9 May 2016 15:01:34 -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 = (long)scp ^ p->p_p->ps_sigcookie;
        if (copyout(&ksc, (void *)scp, sizeof(ksc)))
                sigexit(p, SIGILL);
 
@@ -1325,11 +1326,21 @@ 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);
+       if ((PROC_PC(p) & ~PAGE_MASK) !=
+           (((long)p->p_p->ps_sigcode +
+           (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode)) & 
~PAGE_MASK)) {
+               printf("%s(%d): sigreturn not from sigtramp [pc 0x%lx tramp 
0x%lx]\n",
+                   p->p_comm, p->p_pid, PROC_PC(p),
+                   (long)p->p_p->ps_sigcode +
+                   (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode));
+               sigexit(p, SIGILL);
+               return (EPERM);
+       }
+
 #ifdef DEBUG
        if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
                printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
@@ -1340,6 +1351,19 @@ sys_sigreturn(struct proc *p, void *v, r
 
        if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc)))
                return (error);
+
+       if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
+               printf("%s(%d): cookie %lx should have been %lx\n",
+                   p->p_comm, p->p_pid, ksc.sc_cookie,
+                   (long)scp ^ p->p_p->ps_sigcookie);
+               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/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 19:55:05 -0000
@@ -47,15 +47,16 @@ 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];
+       unsigned long   __sc_unused;
+       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];
+       long    sc_cookie;
 };
 #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 8 May 2016 15:43:35 -0000
@@ -1968,6 +1968,8 @@ ENTRY(sigcode,0)
        depd    %r0, 31, 32, %r1
        copy    %r4, %arg0
        .call
+       .globl  _C_LABEL(sigcoderet)
+_C_LABEL(sigcoderet):
        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        8 May 2016 17:38:09 -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 = (long)scp ^ p->p_p->ps_sigcookie;
        if (copyout(&ksc, (void *)scp, sizeof(ksc)))
                sigexit(p, SIGILL);
 
@@ -922,21 +923,37 @@ 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) != (long)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%lx tramp 
0x%lx]\n",
+                   p->p_comm, p->p_pid, PROC_PC(p),
+                   (long)p->p_p->ps_sigcode +
+                   (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode));
+               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)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 15:29:46 -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     8 May 2016 15:42:20 -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(sigcoderet)
+_C_LABEL(sigcoderet):
        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    9 May 2016 15:24:27 -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 = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
        if (copyout(&frame, fp, sizeof(frame)) != 0) {
                /*
                 * Process has trashed its stack; give it an illegal
@@ -2479,18 +2480,33 @@ 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) != (long)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%u]\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 (context.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
+               printf("%s(%d): cookie %8lx should have been %8lx\n",
+                   p->p_comm, p->p_pid, context.sc_cookie,
+                   (long)scp ^ p->p_p->ps_sigcookie);
                return (EFAULT);
+       }
+
+       /* Prevent reuse of the sigcontext cookie */
+       context.sc_cookie = 0;
+       (void)copyout(&context.sc_cookie, (caddr_t)scp +
+           offsetof(struct sigcontext, sc_cookie),
+           sizeof (context.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  8 May 2016 15:29:46 -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        9 May 2016 15:24:21 -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) != (long)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       8 May 2016 15:43:30 -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(sigcoderet)
+_C_LABEL(sigcoderet):
        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 8 May 2016 15:43:25 -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(sigcoderet)
+_C_LABEL(sigcoderet):
        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        8 May 2016 16:45:16 -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.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
        if (copyout(&frame, fp, sizeof frame) != 0)
                sigexit(p, SIGILL);
 
@@ -508,12 +509,36 @@ sys_sigreturn(struct proc *p, void *v, r
        struct sys_sigreturn_args /* {
                syscallarg(struct sigcontext *) sigcntxp;
        } */ *uap = v;
-       struct sigcontext sc;
+       struct sigcontext sc, *scp = SCARG(uap, sigcntxp);
        struct trapframe *tf;
        int error;
 
-       if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)))
+       if (PROC_PC(p) != (long)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%x, tramp 
0x%lx]\n",
+                   p->p_comm, p->p_pid, PROC_PC(p),
+                   (long)p->p_p->ps_sigcode +
+                   (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode));
+               sigexit(p, SIGILL);
+               return (EPERM);
+       }
+
+       if ((error = copyin(scp, &sc, sizeof sc)))
                return error;
+
+       if (sc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
+               printf("%s(%d): cookie %8lx should have been %8lx\n",
+                   p->p_comm, p->p_pid, sc.sc_cookie,
+                   (long)scp ^ p->p_p->ps_sigcookie);
+               return (EFAULT);
+       }
+
+       /* Prevent reuse of the sigcontext cookie */
+       sc.sc_cookie = 0;
+       (void)copyout(&sc.sc_cookie, (caddr_t)scp +
+           offsetof(struct sigcontext, sc_cookie),
+           sizeof (sc.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 15:29:46 -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   8 May 2016 15:43:20 -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(sigcoderet)
+_C_LABEL(sigcoderet):
        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        9 May 2016 15:01:21 -0000
@@ -164,6 +164,7 @@ sendsig(catcher, sig, mask, code, type, 
                        goto bail;
        }
 
+       ksc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
        if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
 bail:
                /*
@@ -215,34 +216,47 @@ 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) != (long)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%lx tramp 
0x%lx]\n",
+                   p->p_comm, p->p_pid, PROC_PC(p),
+                   (long)p->p_p->ps_sigcode +
+                   (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode));
+               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       8 May 2016 15:29:46 -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 15:29:46 -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    8 May 2016 15:43:15 -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(sigcoderet)
+_C_LABEL(sigcoderet):
        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     9 May 2016 15:24:12 -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) != (long)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 8 May 2016 15:43:10 -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(sigcoderet)
+_C_LABEL(sigcoderet):
        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        9 May 2016 15:24:07 -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) != (long)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 8 May 2016 15:29:46 -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  9 May 2016 15:23:55 -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) != (long)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       8 May 2016 15:29:46 -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/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/sparc64/locore.s,v
retrieving revision 1.181
diff -u -p -u -r1.181 locore.s
--- arch/sparc64/sparc64/locore.s       28 Aug 2015 23:28:39 -0000      1.181
+++ arch/sparc64/sparc64/locore.s       8 May 2016 20:36:57 -0000
@@ -5429,6 +5429,8 @@ _C_LABEL(sigcode):
        restore %g0, SYS_sigreturn, %g1 ! get registers back & set syscall #
        add     %sp, BIAS + 128 + 16, %o0       ! compute scp
 !      andn    %o0, 0x0f, %o0
+       .globl  _C_LABEL(sigcoderet)
+_C_LABEL(sigcoderet):
        t       ST_SYSCALL              ! sigreturn(scp)
        ! sigreturn does not return unless it fails
        mov     SYS_exit, %g1           ! exit(errno)
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      8 May 2016 20:50:17 -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 = (long)&fp->sf_sc ^ 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,20 @@ 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) != (long)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%llx 
0x%lx]\n",
+                   p->p_comm, p->p_pid, PROC_PC(p),
+                   (long)p->p_p->ps_sigcode +
+                   (p->p_p->ps_emul->e_esigret - p->p_p->ps_emul->e_sigcode));
+               sigexit(p, SIGILL);
+               return (EPERM);
+       }
+
        /* First ensure consistent stack state (see sendsig). */
        write_user_windows();
 
@@ -558,15 +568,26 @@ 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)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 ^ p->p_p->ps_sigcookie);
+               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;
        /*
@@ -574,12 +595,12 @@ sys_sigreturn(p, v, retval)
         * verified.  pc and npc must be multiples of 4.  This is all
         * that is required; if it holds, just do it.
         */
-       if (((sc.sc_pc | sc.sc_npc) & 3) != 0 ||
-           (sc.sc_pc == 0) || (sc.sc_npc == 0)) {
+       if (((ksc.sc_pc | ksc.sc_npc) & 3) != 0 ||
+           (ksc.sc_pc == 0) || (ksc.sc_npc == 0)) {
 #ifdef DEBUG
                printf("sigreturn: pc %p or npc %p invalid\n",
-                  (void *)(unsigned long)sc.sc_pc,
-                  (void *)(unsigned long)sc.sc_npc);
+                  (void *)(unsigned long)ksc.sc_pc,
+                  (void *)(unsigned long)ksc.sc_npc);
 #endif
                return (EINVAL);
        }
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     8 May 2016 15:29:46 -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 15:29:46 -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    8 May 2016 15:29:46 -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: kern/kern_sig.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sig.c,v
retrieving revision 1.196
diff -u -p -u -r1.196 kern_sig.c
--- kern/kern_sig.c     29 Mar 2016 08:46:08 -0000      1.196
+++ kern/kern_sig.c     8 May 2016 15:29:46 -0000
@@ -1498,7 +1498,7 @@ sigexit(struct proc *p, int signum)
                if (P_HASSIBLING(p))
                        single_thread_set(p, SINGLE_SUSPEND, 0);
 
-               if (coredump(p) == 0)
+               if (coredump(p, signum) == 0)
                        signum |= WCOREFLAG;
        }
        exit1(p, W_EXITCODE(0, signum), EXIT_NORMAL);
@@ -1519,7 +1519,7 @@ struct coredump_iostate {
  * setuid/setgid.
  */
 int
-coredump(struct proc *p)
+coredump(struct proc *p, int signum)
 {
 #ifdef SMALL_KERNEL
        return EPERM;
@@ -1539,6 +1539,24 @@ coredump(struct proc *p)
                return (EINVAL);
 
        pr->ps_flags |= PS_COREDUMP;
+
+       switch (signum) {
+       case SIGSEGV:
+       case SIGBUS:
+       case SIGILL:
+       case SIGTRAP:
+       case SIGABRT:
+       case SIGEMT:
+       case SIGFPE:
+       case SIGSYS:
+       case SIGXCPU:
+               if ((pr->ps_flags & PS_SUGID) &&
+                   VOP_GETATTR(pr->ps_textvp, &vattr, p->p_ucred, p) == 0 &&
+                   vattr.va_uid == 0)
+                       log(LOG_ERR, "crash of %s(%u) signal %d\n", p->p_comm,
+                           p->p_pid, signum);
+               break;
+       }
 
        /*
         * If the process has inconsistant uids, nosuidcoredump
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  8 May 2016 16:01:10 -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;
+       u_long  ps_sigcookie;
        u_long  ps_kbind_addr;
 
 /* End area that is copied on creation. */
Index: sys/signalvar.h
===================================================================
RCS file: /cvs/src/sys/sys/signalvar.h,v
retrieving revision 1.28
diff -u -p -u -r1.28 signalvar.h
--- sys/signalvar.h     5 May 2015 02:13:46 -0000       1.28
+++ sys/signalvar.h     8 May 2016 15:29:46 -0000
@@ -145,7 +145,7 @@ enum signal_type { SPROCESS, STHREAD, SP
 /*
  * Machine-independent functions:
  */
-int    coredump(struct proc *p);
+int    coredump(struct proc *p, int signum);
 void   execsigs(struct proc *p);
 void   gsignal(int pgid, int sig);
 void   csignal(pid_t pgid, int signum, uid_t uid, uid_t euid);

Reply via email to