summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
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/amd64
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/amd64')
-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
3 files changed, 29 insertions, 9 deletions
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_ */