> 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);