summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2016-05-10 18:39:54 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2016-05-10 18:39:54 +0000
commit869ce5a1007a9d00bbac5121d825c80be70f9dde (patch)
tree26cd16954837176d7032fd1841853c34c5b32f99 /sys/arch
parent24ed245ec22671d3d288d52c91f39a81a24637bf (diff)
SROP mitigation. sendsig() stores a (per-process ^ &sigcontext) cookie
inside the sigcontext. sigreturn(2) checks syscall entry was from the exact PC addr in the (per-process ASLR) sigtramp, verifies the cookie, and clears it to prevent sigcontext reuse. not yet tested on landisk, sparc, *88k, socppc. ok kettenis
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/alpha/alpha/locore.s4
-rw-r--r--sys/arch/alpha/alpha/machdep.c27
-rw-r--r--sys/arch/alpha/include/signal.h6
-rw-r--r--sys/arch/amd64/amd64/locore.S4
-rw-r--r--sys/arch/amd64/amd64/machdep.c31
-rw-r--r--sys/arch/amd64/include/signal.h3
-rw-r--r--sys/arch/arm/arm/sig_machdep.c38
-rw-r--r--sys/arch/arm/arm/sigcode.S4
-rw-r--r--sys/arch/arm/include/signal.h6
-rw-r--r--sys/arch/hppa/hppa/locore.S4
-rw-r--r--sys/arch/hppa/hppa/machdep.c27
-rw-r--r--sys/arch/hppa/include/signal.h5
-rw-r--r--sys/arch/hppa64/hppa64/locore.S4
-rw-r--r--sys/arch/hppa64/hppa64/machdep.c30
-rw-r--r--sys/arch/hppa64/include/signal.h7
-rw-r--r--sys/arch/i386/i386/locore.s4
-rw-r--r--sys/arch/i386/i386/machdep.c34
-rw-r--r--sys/arch/i386/include/signal.h4
-rw-r--r--sys/arch/m88k/m88k/sig_machdep.c35
-rw-r--r--sys/arch/m88k/m88k/subr.S4
-rw-r--r--sys/arch/macppc/macppc/locore.S4
-rw-r--r--sys/arch/macppc/macppc/machdep.c29
-rw-r--r--sys/arch/mips64/include/signal.h6
-rw-r--r--sys/arch/mips64/mips64/lcore_access.S4
-rw-r--r--sys/arch/mips64/mips64/sendsig.c41
-rw-r--r--sys/arch/powerpc/include/signal.h4
-rw-r--r--sys/arch/sh/include/signal.h6
-rw-r--r--sys/arch/sh/sh/locore_subr.S4
-rw-r--r--sys/arch/sh/sh/sh_machdep.c35
-rw-r--r--sys/arch/socppc/socppc/locore.S4
-rw-r--r--sys/arch/socppc/socppc/machdep.c29
-rw-r--r--sys/arch/sparc/include/signal.h4
-rw-r--r--sys/arch/sparc/sparc/machdep.c30
-rw-r--r--sys/arch/sparc64/include/signal.h7
-rw-r--r--sys/arch/sparc64/sparc64/locore.s4
-rw-r--r--sys/arch/sparc64/sparc64/machdep.c48
36 files changed, 396 insertions, 144 deletions
diff --git a/sys/arch/alpha/alpha/locore.s b/sys/arch/alpha/alpha/locore.s
index 86d893c30fb..6d6354f079f 100644
--- a/sys/arch/alpha/alpha/locore.s
+++ b/sys/arch/alpha/alpha/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.43 2015/07/20 07:45:23 dlg Exp $ */
+/* $OpenBSD: locore.s,v 1.44 2016/05/10 18:39:40 deraadt Exp $ */
/* $NetBSD: locore.s,v 1.94 2001/04/26 03:10:44 ross Exp $ */
/*-
@@ -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)
diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c
index 8f38df9011f..944ae9705e7 100644
--- a/sys/arch/alpha/alpha/machdep.c
+++ b/sys/arch/alpha/alpha/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.171 2015/10/21 07:59:17 mpi Exp $ */
+/* $OpenBSD: machdep.c,v 1.172 2016/05/10 18:39:40 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */
/*-
@@ -1477,9 +1477,7 @@ sendsig(catcher, sig, mask, code, type, val)
} 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,13 +1548,28 @@ sys_sigreturn(p, v, retval)
printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
#endif
+ if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%lx 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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 %lx should have been %lx\n",
+ p->p_comm, p->p_pid, ksc.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
+ return (EFAULT);
+ }
+
if (ksc.sc_regs[R_ZERO] != 0xACEDBADE) /* magic number */
return (EINVAL);
/*
diff --git a/sys/arch/alpha/include/signal.h b/sys/arch/alpha/include/signal.h
index b79b2770689..b080e2553f8 100644
--- a/sys/arch/alpha/include/signal.h
+++ b/sys/arch/alpha/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.9 2015/11/07 19:06:05 miod Exp $ */
+/* $OpenBSD: signal.h,v 1.10 2016/05/10 18:39:42 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.2 1995/02/16 03:08:08 cgd Exp $ */
/*
@@ -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) */
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
index f66dc562df8..bad043377b4 100644
--- a/sys/arch/amd64/amd64/locore.S
+++ b/sys/arch/amd64/amd64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.77 2016/05/10 14:15:57 mikeb Exp $ */
+/* $OpenBSD: locore.S,v 1.78 2016/05/10 18:39:42 deraadt Exp $ */
/* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */
/*
@@ -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)
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 8d2db71e90d..d0a145ab3ee 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.218 2016/04/03 17:48:33 guenther Exp $ */
+/* $OpenBSD: machdep.c,v 1.219 2016/05/10 18:39:42 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -571,6 +571,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
}
scp = sp - sss;
+ ksc.sc_cookie = (long)scp ^ p->p_p->ps_sigcookie;
if (copyout(&ksc, (void *)scp, sizeof(ksc)))
sigexit(p, SIGILL);
@@ -611,18 +612,34 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%llx %lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ sigexit(p, SIGILL);
+ return (EPERM);
+ }
+
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 %lx should have been %lx\n",
+ p->p_comm, p->p_pid, ksc.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
+ 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))
return (EINVAL);
diff --git a/sys/arch/amd64/include/signal.h b/sys/arch/amd64/include/signal.h
index 527a220cf32..e5cffc53b1d 100644
--- a/sys/arch/amd64/include/signal.h
+++ b/sys/arch/amd64/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.8 2013/04/01 17:18:19 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:42 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.2 2003/04/28 23:16:17 bjh21 Exp $ */
/*
@@ -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_ */
diff --git a/sys/arch/arm/arm/sig_machdep.c b/sys/arch/arm/arm/sig_machdep.c
index abd1bd494a3..6f308d4cab7 100644
--- a/sys/arch/arm/arm/sig_machdep.c
+++ b/sys/arch/arm/arm/sig_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sig_machdep.c,v 1.12 2016/01/31 00:14:50 jsg Exp $ */
+/* $OpenBSD: sig_machdep.c,v 1.13 2016/05/10 18:39:43 deraadt Exp $ */
/* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */
/*
@@ -136,6 +136,7 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type,
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) {
/*
* Process has trashed its stack; give it an illegal
@@ -182,23 +183,32 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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)
+ if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%lx %lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ sigexit(p, SIGILL);
+ return (EPERM);
+ }
+
+ if (copyin(scp, &context, sizeof(*scp)) != 0)
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 (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
+
+ if (context.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, context.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
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));
/*
* Make sure the processor mode has not been tampered with and
diff --git a/sys/arch/arm/arm/sigcode.S b/sys/arch/arm/arm/sigcode.S
index c6c8412fc97..dc38068e482 100644
--- a/sys/arch/arm/arm/sigcode.S
+++ b/sys/arch/arm/arm/sigcode.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: sigcode.S,v 1.2 2006/12/27 17:49:26 drahn Exp $ */
+/* $OpenBSD: sigcode.S,v 1.3 2016/05/10 18:39:43 deraadt Exp $ */
/* $NetBSD: sigcode.S,v 1.6 2003/10/05 19:44:58 matt Exp $ */
/*
@@ -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 ! */
diff --git a/sys/arch/arm/include/signal.h b/sys/arch/arm/include/signal.h
index 564ea4f5bfc..773fdc89dc0 100644
--- a/sys/arch/arm/include/signal.h
+++ b/sys/arch/arm/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.8 2012/12/02 07:03:31 guenther Exp $ */
+/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:43 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.5 2003/10/18 17:57:21 briggs Exp $ */
/*
@@ -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;
diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S
index 3a47c461961..037e3b8e72a 100644
--- a/sys/arch/hppa/hppa/locore.S
+++ b/sys/arch/hppa/hppa/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.193 2014/10/23 16:57:45 miod Exp $ */
+/* $OpenBSD: locore.S,v 1.194 2016/05/10 18:39:44 deraadt Exp $ */
/*
* Copyright (c) 1998-2004 Michael Shalayeff
@@ -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
diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c
index a98fc8c4030..98578044850 100644
--- a/sys/arch/hppa/hppa/machdep.c
+++ b/sys/arch/hppa/hppa/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.243 2016/04/20 23:52:04 dlg Exp $ */
+/* $OpenBSD: machdep.c,v 1.244 2016/05/10 18:39:44 deraadt Exp $ */
/*
* Copyright (c) 1999-2003 Michael Shalayeff
@@ -1303,6 +1303,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
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,17 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%lx 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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);
@@ -1341,6 +1348,20 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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);
+ sigexit(p, SIGILL);
+ 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)
if ((ksc.sc_ps & (PSL_MBS|PSL_MBZ)) != PSL_MBS)
diff --git a/sys/arch/hppa/include/signal.h b/sys/arch/hppa/include/signal.h
index 629a9410d58..850e56accb3 100644
--- a/sys/arch/hppa/include/signal.h
+++ b/sys/arch/hppa/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.11 2013/04/01 17:18:20 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.12 2016/05/10 18:39:44 deraadt Exp $ */
/*
* Copyright (c) 1994, The University of Utah and
@@ -48,7 +48,7 @@ typedef int sig_atomic_t;
*/
struct sigcontext {
unsigned long __sc_unused;
- unsigned long sc_mask; /* signal mask to restore */
+ 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 */
@@ -56,6 +56,7 @@ struct sigcontext {
unsigned long sc_resv[2];
unsigned long sc_regs[32];
unsigned long sc_fpregs[64];
+ long sc_cookie;
};
#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */
#endif /* !_MACHINE_SIGNAL_H_ */
diff --git a/sys/arch/hppa64/hppa64/locore.S b/sys/arch/hppa64/hppa64/locore.S
index d6b28a6957f..4e4eb338529 100644
--- a/sys/arch/hppa64/hppa64/locore.S
+++ b/sys/arch/hppa64/hppa64/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.41 2011/10/12 18:30:09 miod Exp $ */
+/* $OpenBSD: locore.S,v 1.42 2016/05/10 18:39:44 deraadt Exp $ */
/*
* Copyright (c) 2005 Michael Shalayeff
@@ -1970,6 +1970,8 @@ ENTRY(sigcode,0)
.call
ble 4(%sr7, %r1)
ldi SYS_sigreturn, %r1
+ .globl sigcoderet
+sigcoderet:
ldil L%SYSCALLGATE, %r1
depd %r0, 31, 32, %r1
diff --git a/sys/arch/hppa64/hppa64/machdep.c b/sys/arch/hppa64/hppa64/machdep.c
index 005a9a20eae..fe2cdbaa294 100644
--- a/sys/arch/hppa64/hppa64/machdep.c
+++ b/sys/arch/hppa64/hppa64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.79 2016/04/20 23:52:04 dlg Exp $ */
+/* $OpenBSD: machdep.c,v 1.80 2016/05/10 18:39:44 deraadt Exp $ */
/*
* Copyright (c) 2005 Michael Shalayeff
@@ -900,6 +900,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
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,15 +923,16 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%lx 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ sigexit(p, SIGILL);
+ return (EPERM);
+ }
/* flush the FPU ctx first */
fpu_proc_flush(p);
@@ -938,6 +940,20 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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);
+ sigexit(p, SIGILL);
+ 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)
if ((ksc.sc_ps & (PSL_MBS|PSL_MBZ)) != PSL_MBS)
diff --git a/sys/arch/hppa64/include/signal.h b/sys/arch/hppa64/include/signal.h
index 31498706cef..536b464df5d 100644
--- a/sys/arch/hppa64/include/signal.h
+++ b/sys/arch/hppa64/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.6 2013/04/01 17:18:20 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.7 2016/05/10 18:39:44 deraadt Exp $ */
/*
* Copyright (c) 1994, The University of Utah and
@@ -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_unused;
+ 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 */
@@ -56,6 +56,7 @@ struct sigcontext {
unsigned long sc_resv[2];
unsigned long sc_regs[32];
unsigned long sc_fpregs[64];
+ long sc_cookie;
};
#endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */
#endif /* !_MACHINE_SIGNAL_H_ */
diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s
index 9581f32d310..f143d75008d 100644
--- a/sys/arch/i386/i386/locore.s
+++ b/sys/arch/i386/i386/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.167 2016/03/15 03:17:51 guenther Exp $ */
+/* $OpenBSD: locore.s,v 1.168 2016/05/10 18:39:45 deraadt Exp $ */
/* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */
/*-
@@ -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)
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index c7a8caa6b42..405af381a89 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.583 2016/03/24 04:56:08 guenther Exp $ */
+/* $OpenBSD: machdep.c,v 1.584 2016/05/10 18:39:45 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -2440,6 +2440,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
}
/* 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, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%x 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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 %lx should have been %lx\n",
+ p->p_comm, p->p_pid, context.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
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.
diff --git a/sys/arch/i386/include/signal.h b/sys/arch/i386/include/signal.h
index 790339eb264..e0ead34d9c9 100644
--- a/sys/arch/i386/include/signal.h
+++ b/sys/arch/i386/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.10 2013/04/01 17:18:20 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.11 2016/05/10 18:39:45 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.6 1996/01/08 13:51:43 mycroft Exp $ */
/*
@@ -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 */
diff --git a/sys/arch/m88k/m88k/sig_machdep.c b/sys/arch/m88k/m88k/sig_machdep.c
index d1bab73ab1f..b1fef7fc38f 100644
--- a/sys/arch/m88k/m88k/sig_machdep.c
+++ b/sys/arch/m88k/m88k/sig_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sig_machdep.c,v 1.23 2015/02/09 08:48:23 miod Exp $ */
+/* $OpenBSD: sig_machdep.c,v 1.24 2016/05/10 18:39:46 deraadt Exp $ */
/*
* Copyright (c) 2014 Miodrag Vallat.
*
@@ -207,18 +207,35 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%llx %llx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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)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);
+ sigexit(p, SIGILL);
+ 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;
diff --git a/sys/arch/m88k/m88k/subr.S b/sys/arch/m88k/m88k/subr.S
index 6d10b422fea..6504080d79b 100644
--- a/sys/arch/m88k/m88k/subr.S
+++ b/sys/arch/m88k/m88k/subr.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr.S,v 1.24 2014/06/08 13:20:39 miod Exp $ */
+/* $OpenBSD: subr.S,v 1.25 2016/05/10 18:39:46 deraadt Exp $ */
/*
* Mach Operating System
* Copyright (c) 1993-1992 Carnegie Mellon University
@@ -1087,6 +1087,8 @@ ENTRY(sigcode) /* r31 points to sigframe */
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
diff --git a/sys/arch/macppc/macppc/locore.S b/sys/arch/macppc/macppc/locore.S
index 1ed64bd7b0f..f042f47acc6 100644
--- a/sys/arch/macppc/macppc/locore.S
+++ b/sys/arch/macppc/macppc/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.53 2016/04/25 07:58:14 mpi Exp $ */
+/* $OpenBSD: locore.S,v 1.54 2016/05/10 18:39:46 deraadt Exp $ */
/* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */
/*
@@ -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):
diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c
index 58b61ceb31b..7ed9fa69054 100644
--- a/sys/arch/macppc/macppc/machdep.c
+++ b/sys/arch/macppc/macppc/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.173 2016/04/20 23:52:04 dlg Exp $ */
+/* $OpenBSD: machdep.c,v 1.174 2016/05/10 18:39:46 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
/*
@@ -481,6 +481,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
frame.sf_sip = &fp->sf_si;
initsiginfo(&frame.sf_si, sig, code, type, val);
}
+ frame.sf_sc.sc_cookie = (long)fp ^ p->p_p->ps_sigcookie;
if (copyout(&frame, fp, sizeof frame) != 0)
sigexit(p, SIGILL);
@@ -508,12 +509,34 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%x 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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 %lx should have been %lx\n",
+ p->p_comm, p->p_pid, sc.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
+ 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);
diff --git a/sys/arch/mips64/include/signal.h b/sys/arch/mips64/include/signal.h
index 3dc7627d660..48534b386bd 100644
--- a/sys/arch/mips64/include/signal.h
+++ b/sys/arch/mips64/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.10 2012/12/02 07:03:31 guenther Exp $ */
+/* $OpenBSD: signal.h,v 1.11 2016/05/10 18:39:47 deraadt Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -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... */
diff --git a/sys/arch/mips64/mips64/lcore_access.S b/sys/arch/mips64/mips64/lcore_access.S
index 82a775862b6..e6c9a53143e 100644
--- a/sys/arch/mips64/mips64/lcore_access.S
+++ b/sys/arch/mips64/mips64/lcore_access.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: lcore_access.S,v 1.24 2012/10/03 11:18:23 miod Exp $ */
+/* $OpenBSD: lcore_access.S,v 1.25 2016/05/10 18:39:47 deraadt Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -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:
diff --git a/sys/arch/mips64/mips64/sendsig.c b/sys/arch/mips64/mips64/sendsig.c
index b022882a217..45f0ee16996 100644
--- a/sys/arch/mips64/mips64/sendsig.c
+++ b/sys/arch/mips64/mips64/sendsig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sendsig.c,v 1.25 2016/03/06 19:42:27 mpi Exp $ */
+/* $OpenBSD: sendsig.c,v 1.26 2016/05/10 18:39:47 deraadt Exp $ */
/*
* Copyright (c) 1990 The Regents of the University of California.
@@ -164,6 +164,7 @@ sendsig(catcher, sig, mask, code, type, val)
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,46 @@ 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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%lx 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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)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);
+ sigexit(p, SIGILL);
+ 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
diff --git a/sys/arch/powerpc/include/signal.h b/sys/arch/powerpc/include/signal.h
index 7258c5a90df..67e82644ff7 100644
--- a/sys/arch/powerpc/include/signal.h
+++ b/sys/arch/powerpc/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.8 2012/12/02 07:03:31 guenther Exp $ */
+/* $OpenBSD: signal.h,v 1.9 2016/05/10 18:39:47 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.1 1996/09/30 16:34:34 ws Exp $ */
/*
@@ -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 */
};
diff --git a/sys/arch/sh/include/signal.h b/sys/arch/sh/include/signal.h
index e5152d73cf2..24fca36829b 100644
--- a/sys/arch/sh/include/signal.h
+++ b/sys/arch/sh/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.6 2012/12/02 07:03:31 guenther Exp $ */
+/* $OpenBSD: signal.h,v 1.7 2016/05/10 18:39:47 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.12 2005/12/11 12:18:58 christos Exp $ */
/*
@@ -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 */
diff --git a/sys/arch/sh/sh/locore_subr.S b/sys/arch/sh/sh/locore_subr.S
index 82d116362d0..ec1d1e6b87f 100644
--- a/sys/arch/sh/sh/locore_subr.S
+++ b/sys/arch/sh/sh/locore_subr.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore_subr.S,v 1.10 2010/09/06 08:00:31 jsg Exp $ */
+/* $OpenBSD: locore_subr.S,v 1.11 2016/05/10 18:39:47 deraadt Exp $ */
/* $NetBSD: locore_subr.S,v 1.28 2006/01/23 22:52:09 uwe Exp $ */
/*
@@ -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 */
diff --git a/sys/arch/sh/sh/sh_machdep.c b/sys/arch/sh/sh/sh_machdep.c
index b76adc05229..c07be231288 100644
--- a/sys/arch/sh/sh/sh_machdep.c
+++ b/sys/arch/sh/sh/sh_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sh_machdep.c,v 1.42 2016/03/05 17:16:33 tobiasu Exp $ */
+/* $OpenBSD: sh_machdep.c,v 1.43 2016/05/10 18:39:47 deraadt Exp $ */
/* $NetBSD: sh3_machdep.c,v 1.59 2006/03/04 01:13:36 uwe Exp $ */
/*
@@ -486,6 +486,8 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
/* frame.sf_uc.sc_err = 0; */
frame.sf_uc.sc_mask = mask;
+ frame.sf_uc.sc_cookie = (long)&fp->sf_uc ^ p->p_p->ps_sigcookie;
+printf("cookie %lx\n", frame.sf_uc.sc_cookie);
if (copyout(&frame, fp, sizeof(frame)) != 0) {
/*
* Process has trashed its stack; give it an illegal
@@ -519,19 +521,34 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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 ((error = copyin((caddr_t)scp, &context, sizeof(*scp))) != 0)
+ if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from sigtramp [pc 0x%x 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ sigexit(p, SIGILL);
+ return (EPERM);
+ }
+
+ if ((error = copyin(scp, &context, sizeof(*scp))) != 0)
return (error);
+ if (context.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, context.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
+ 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. */
tf = p->p_md.md_regs;
diff --git a/sys/arch/socppc/socppc/locore.S b/sys/arch/socppc/socppc/locore.S
index 6184aa6a86c..38a5bb01731 100644
--- a/sys/arch/socppc/socppc/locore.S
+++ b/sys/arch/socppc/socppc/locore.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.S,v 1.20 2016/04/25 07:58:14 mpi Exp $ */
+/* $OpenBSD: locore.S,v 1.21 2016/05/10 18:39:48 deraadt Exp $ */
/* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */
/*
@@ -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):
diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c
index bfed97cc704..38dad7dc79a 100644
--- a/sys/arch/socppc/socppc/machdep.c
+++ b/sys/arch/socppc/socppc/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.65 2016/03/03 02:42:16 bmercer Exp $ */
+/* $OpenBSD: machdep.c,v 1.66 2016/05/10 18:39:48 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
/*
@@ -508,6 +508,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
frame.sf_sip = &fp->sf_si;
initsiginfo(&frame.sf_si, sig, code, type, val);
}
+ frame.sf_sc.sc_cookie = (long)fp ^ p->p_p->ps_sigcookie;
if (copyout(&frame, fp, sizeof frame) != 0)
sigexit(p, SIGILL);
@@ -535,12 +536,34 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval)
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) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%x 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ 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 %lx should have been %lx\n",
+ p->p_comm, p->p_pid, sc.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
+ 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);
if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
return EINVAL;
diff --git a/sys/arch/sparc/include/signal.h b/sys/arch/sparc/include/signal.h
index 2c50cd06314..ed1d6819801 100644
--- a/sys/arch/sparc/include/signal.h
+++ b/sys/arch/sparc/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.11 2013/04/01 17:18:20 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.12 2016/05/10 18:39:48 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.4 1996/02/01 22:32:35 mycroft Exp $ */
/*
@@ -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 */
diff --git a/sys/arch/sparc/sparc/machdep.c b/sys/arch/sparc/sparc/machdep.c
index 9d663ab4595..139b0d449c0 100644
--- a/sys/arch/sparc/sparc/machdep.c
+++ b/sys/arch/sparc/sparc/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.175 2015/10/21 07:59:18 mpi Exp $ */
+/* $OpenBSD: machdep.c,v 1.176 2016/05/10 18:39:48 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.85 1997/09/12 08:55:02 pk Exp $ */
/*
@@ -432,7 +432,7 @@ sendsig(catcher, sig, mask, code, type, val)
*/
newsp = (int)fp - sizeof(struct rwindow);
write_user_windows();
- /* XXX do not copyout siginfo if not needed */
+ sf.sf_sc.sc_cookie = (long)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) {
@@ -486,7 +486,7 @@ sys_sigreturn(p, v, retval)
struct sys_sigreturn_args /* {
syscallarg(struct sigcontext *) sigcntxp;
} */ *uap = v;
- struct sigcontext ksc;
+ struct sigcontext ksc, *sc = SCARG(uap, sigcntxp);
struct trapframe *tf;
int error;
@@ -499,8 +499,30 @@ sys_sigreturn(p, v, retval)
printf("sigreturn: %s[%d], sigcntxp %p\n",
p->p_comm, p->p_pid, SCARG(uap, sigcntxp));
#endif
- if ((error = copyin(SCARG(uap, sigcntxp), &ksc, sizeof(ksc))) != 0)
+ if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%lx 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p), p->p_p->ps_sigcoderet);
+ sigexit(p, SIGILL);
+ return (EPERM);
+ }
+
+ if ((error = copyin(sc, &ksc, sizeof(ksc))) != 0)
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);
+ sigexit(p, SIGILL);
+ 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;
/*
* Only the icc bits in the psr are used, so it need not be
diff --git a/sys/arch/sparc64/include/signal.h b/sys/arch/sparc64/include/signal.h
index b5a2122f72e..3a9cc69b870 100644
--- a/sys/arch/sparc64/include/signal.h
+++ b/sys/arch/sparc64/include/signal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signal.h,v 1.11 2013/04/01 17:18:20 deraadt Exp $ */
+/* $OpenBSD: signal.h,v 1.12 2016/05/10 18:39:48 deraadt Exp $ */
/* $NetBSD: signal.h,v 1.10 2001/05/09 19:50:49 kleink Exp $ */
/*
@@ -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 */
diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s
index 2933bb6c378..b1a8a1d9dca 100644
--- a/sys/arch/sparc64/sparc64/locore.s
+++ b/sys/arch/sparc64/sparc64/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.181 2015/08/28 23:28:39 kettenis Exp $ */
+/* $OpenBSD: locore.s,v 1.182 2016/05/10 18:39:49 deraadt Exp $ */
/* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */
/*
@@ -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)
diff --git a/sys/arch/sparc64/sparc64/machdep.c b/sys/arch/sparc64/sparc64/machdep.c
index af20f427e13..e2a94b6fb10 100644
--- a/sys/arch/sparc64/sparc64/machdep.c
+++ b/sys/arch/sparc64/sparc64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.175 2016/03/07 13:21:51 naddy Exp $ */
+/* $OpenBSD: machdep.c,v 1.176 2016/05/10 18:39:49 deraadt Exp $ */
/* $NetBSD: machdep.c,v 1.108 2001/07/24 19:30:14 eeh Exp $ */
/*-
@@ -492,7 +492,7 @@ sendsig(catcher, sig, mask, code, type, val)
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,18 @@ sys_sigreturn(p, v, retval)
struct sys_sigreturn_args /* {
syscallarg(struct sigcontext *) sigcntxp;
} */ *uap = v;
- struct sigcontext sc, *scp;
+ struct sigcontext *scp = SCARG(uap, sigcntxp), ksc;
struct trapframe64 *tf;
int error = EINVAL;
+ if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
+ printf("%s(%d): sigreturn not from tramp [pc 0x%llx 0x%lx]\n",
+ p->p_comm, p->p_pid, PROC_PC(p),
+ p->p_p->ps_sigcoderet);
+ sigexit(p, SIGILL);
+ return (EPERM);
+ }
+
/* First ensure consistent stack state (see sendsig). */
write_user_windows();
@@ -558,15 +566,27 @@ 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 %lx should have been %lx\n",
+ p->p_comm, p->p_pid, ksc.sc_cookie,
+ (long)scp ^ p->p_p->ps_sigcookie);
+ sigexit(p, SIGILL);
+ return (EFAULT);
}
- scp = &sc;
+
+ /* 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 +594,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);
}