diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-03-12 17:57:13 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2017-03-12 17:57:13 +0000 |
commit | f944ef6cbadffe208807e3f21b7f87233010fc7c (patch) | |
tree | 8d4886aee41614e0218333a9ed3a65796ef7764a /sys/arch | |
parent | d416de90211ca3074b6370880043c3389b5ca401 (diff) |
Bring SROP mitigation to arm64. Make some small modifications to the arm
code as well to improve diffability. Changes the types used in the arm64
"struct sigcontext" to avoid having to include <sys/types.h>.
ok deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/arm/arm/sig_machdep.c | 26 | ||||
-rw-r--r-- | sys/arch/arm64/arm64/sig_machdep.c | 93 | ||||
-rw-r--r-- | sys/arch/arm64/include/signal.h | 25 |
3 files changed, 70 insertions, 74 deletions
diff --git a/sys/arch/arm/arm/sig_machdep.c b/sys/arch/arm/arm/sig_machdep.c index 43744c3c1ce..a0655e1bab1 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.14 2016/05/21 00:56:43 deraadt Exp $ */ +/* $OpenBSD: sig_machdep.c,v 1.15 2017/03/12 17:57:12 kettenis Exp $ */ /* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */ /* @@ -61,7 +61,6 @@ static __inline struct trapframe * process_frame(struct proc *p) { - return p->p_addr->u_pcb.pcb_tf; } @@ -85,8 +84,6 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, tf = process_frame(p); - /* Do we need to jump onto the signal stack? */ - /* Allocate space for the signal handler context. */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_usr_sp) && (psp->ps_sigonstack & sigmask(sig))) @@ -99,7 +96,7 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, fp--; /* make the stack aligned */ - fp = (void *)STACKALIGN(fp); + fp = (struct sigframe *)STACKALIGN(fp); /* Build stack frame for signal trampoline. */ bzero(&frame, sizeof(frame)); @@ -148,22 +145,15 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, /* * Build context to run handler in. We invoke the handler - * directly, only returning via the trampoline. Note the - * trampoline version numbers are coordinated with machine- - * dependent code in libc. - */ - - /* - * this was all in the switch below, seemed daft to duplicate it, if - * we do a new trampoline version it might change then + * directly, only returning via the trampoline. */ tf->tf_r0 = sig; - tf->tf_r1 = (int)frame.sf_sip; - tf->tf_r2 = (int)frame.sf_scp; - tf->tf_pc = (int)frame.sf_handler; - tf->tf_usr_sp = (int)fp; + tf->tf_r1 = (register_t)frame.sf_sip; + tf->tf_r2 = (register_t)frame.sf_scp; + tf->tf_pc = (register_t)frame.sf_handler; + tf->tf_usr_sp = (register_t)fp; - tf->tf_usr_lr = (int)p->p_p->ps_sigcode; + tf->tf_usr_lr = p->p_p->ps_sigcode; } /* diff --git a/sys/arch/arm64/arm64/sig_machdep.c b/sys/arch/arm64/arm64/sig_machdep.c index f5982c6a478..f8604fec018 100644 --- a/sys/arch/arm64/arm64/sig_machdep.c +++ b/sys/arch/arm64/arm64/sig_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sig_machdep.c,v 1.2 2016/12/19 01:25:53 jsg Exp $ */ +/* $OpenBSD: sig_machdep.c,v 1.3 2017/03/12 17:57:12 kettenis Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -62,7 +62,6 @@ * */ - #include <sys/param.h> #include <sys/mount.h> /* XXX only needed by syscallargs.h */ @@ -99,52 +98,52 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, union sigval val) { struct proc *p = curproc; - struct sigframe *fp, ksf; struct trapframe *tf; + struct sigframe *fp, frame; struct sigacts *psp = p->p_p->ps_sigacts; - siginfo_t *sip; - int fsize; + siginfo_t *sip = NULL; int i; tf = process_frame(p); - /* - * Allocate space for the signal handler context. - */ - fsize = sizeof(struct sigframe); - if (!(psp->ps_siginfo & sigmask(sig))) - fsize -= sizeof(siginfo_t); + /* Allocate space for the signal handler context. */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_sp) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)(p->p_sigstk.ss_sp + - p->p_sigstk.ss_size - fsize); + fp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + + p->p_sigstk.ss_size); else - fp = (struct sigframe *)(tf->tf_sp - fsize); + fp = (struct sigframe *)tf->tf_sp; + /* make room on the stack */ + fp--; + + /* make the stack aligned */ fp = (struct sigframe *)STACKALIGN(fp); - bzero (&ksf, sizeof(ksf)); - ksf.sf_signum = sig; - sip = NULL; + /* Build stack frame for signal trampoline. */ + bzero(&frame, sizeof(frame)); + frame.sf_signum = sig; - for (i=0; i < 30; i++) { - ksf.sf_sc.sc_x[i] = tf->tf_x[i]; - } - ksf.sf_sc.sc_sp = tf->tf_sp; - ksf.sf_sc.sc_lr = tf->tf_lr; - ksf.sf_sc.sc_elr = tf->tf_elr; - ksf.sf_sc.sc_spsr = tf->tf_spsr; + /* Save register context. */ + for (i=0; i < 30; i++) + frame.sf_sc.sc_x[i] = tf->tf_x[i]; + frame.sf_sc.sc_sp = tf->tf_sp; + frame.sf_sc.sc_lr = tf->tf_lr; + frame.sf_sc.sc_elr = tf->tf_elr; + frame.sf_sc.sc_spsr = tf->tf_spsr; + + /* Save signal mask. */ + frame.sf_sc.sc_mask = returnmask; - // Save signal mask. - ksf.sf_sc.sc_mask = returnmask; + /* XXX Save floating point context */ if (psp->ps_siginfo & sigmask(sig)) { sip = &fp->sf_si; - initsiginfo(&ksf.sf_si, sig, code, type, val); + initsiginfo(&frame.sf_si, sig, code, type, val); } - // XXX copy floating point context - if (copyout(&ksf, fp, fsize ) != 0) { + 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 * instruction to halt it in its tracks. @@ -154,15 +153,16 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, } /* - * Build the argument list for the signal handler. + * Build context to run handler in. We invoke the handler + * directly, only returning via the trampoline. */ - tf->tf_x[0] = sig; tf->tf_x[1] = (register_t)sip; tf->tf_x[2] = (register_t)&fp->sf_sc; - tf->tf_lr = p->p_p->ps_sigcode; tf->tf_elr = (register_t)catcher; tf->tf_sp = (register_t)fp; + + tf->tf_lr = p->p_p->ps_sigcode; } /* @@ -182,13 +182,27 @@ 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 ksc, *scp = SCARG(uap, sigcntxp); struct trapframe *tf; int i; - scp = SCARG(uap, sigcntxp); - if (copyin((caddr_t)scp, &ksc, sizeof(*scp)) != 0) + if (PROC_PC(p) != p->p_p->ps_sigcoderet) { + sigexit(p, SIGILL); + return (EPERM); + } + + if (copyin(scp, &ksc, sizeof(*scp)) != 0) + return (EFAULT); + + if (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)); /* * Make sure the processor mode has not been tampered with and @@ -198,20 +212,19 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) (ksc.sc_spsr & (PSR_I | PSR_F)) != 0) return (EINVAL); + /* XXX Restore floating point context */ + /* Restore register context. */ tf = process_frame(p); - for (i=0; i < 30; i++) { + for (i=0; i < 30; i++) tf->tf_x[i] = ksc.sc_x[i]; - } tf->tf_sp = ksc.sc_sp; tf->tf_lr = ksc.sc_lr; tf->tf_elr = ksc.sc_elr; - tf->tf_spsr = ksc.sc_spsr; + tf->tf_spsr = ksc.sc_spsr; /* Restore signal mask. */ p->p_sigmask = ksc.sc_mask & ~sigcantmask; - // XXX fpustate - return (EJUSTRETURN); } diff --git a/sys/arch/arm64/include/signal.h b/sys/arch/arm64/include/signal.h index ebe453bc7b1..ccc040ee183 100644 --- a/sys/arch/arm64/include/signal.h +++ b/sys/arch/arm64/include/signal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: signal.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* $OpenBSD: signal.h,v 1.2 2017/03/12 17:57:12 kettenis Exp $ */ /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -38,12 +38,6 @@ #include <sys/cdefs.h> -#if !defined(__LANGUAGE_ASSEMBLY) -#include <sys/types.h> - -/* - * Machine-dependent signal definitions - */ typedef int sig_atomic_t; #if __BSD_VISIBLE || __XPG_VISIBLE >= 420 @@ -56,16 +50,15 @@ typedef int sig_atomic_t; */ struct sigcontext { int __sc_unused; - int sc_mask; /* signal mask to restore (old style) */ + int sc_mask; /* signal mask to restore */ - uint64_t sc_sp; - uint64_t sc_lr; - uint64_t sc_elr; - uint64_t sc_spsr; - uint64_t sc_x[30]; + unsigned long sc_sp; + unsigned long sc_lr; + unsigned long sc_elr; + unsigned long sc_spsr; + unsigned long sc_x[30]; + + long sc_cookie; }; #endif /* __BSD_VISIBLE || __XPG_VISIBLE >= 420 */ - -#endif /* !__LANGUAGE_ASSEMBLY */ - #endif /* !_MACHINE_SIGNAL_H_ */ |