diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2018-04-12 17:13:45 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2018-04-12 17:13:45 +0000 |
commit | 9e91f96d779c665c5377cfd5667ee7e276f4c6eb (patch) | |
tree | fe187bb093929803715228a98ffc99028915fbad /sys/arch | |
parent | 0f04bf0af32f3ceff2d723822807131626fbff5d (diff) |
Implement MAP_STACK option for mmap(). Synchronous faults (pagefault and
syscall) confirm the stack register points at MAP_STACK memory, otherwise
SIGSEGV is delivered. sigaltstack() and pthread_attr_setstack() are modified
to create a MAP_STACK sub-region which satisfies alignment requirements.
Observe that MAP_STACK can only be set/cleared by mmap(), which zeroes the
contents of the region -- there is no mprotect() equivalent operation, so
there is no MAP_STACK-adding gadget.
This opportunistic software-emulation of a stack protection bit makes
stack-pivot operations during ROPchain fragile (kind of like removing a
tool from the toolbox).
original discussion with tedu, uvm work by stefan, testing by mortimer
ok kettenis
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/alpha/alpha/machdep.c | 7 | ||||
-rw-r--r-- | sys/arch/alpha/alpha/trap.c | 20 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/trap.c | 21 | ||||
-rw-r--r-- | sys/arch/arm/arm/fault.c | 20 | ||||
-rw-r--r-- | sys/arch/arm/arm/sig_machdep.c | 8 | ||||
-rw-r--r-- | sys/arch/arm64/arm64/ast.c | 5 | ||||
-rw-r--r-- | sys/arch/arm64/arm64/sig_machdep.c | 8 | ||||
-rw-r--r-- | sys/arch/arm64/arm64/trap.c | 18 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/trap.c | 24 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/i386/i386/trap.c | 20 | ||||
-rw-r--r-- | sys/arch/m88k/m88k/sig_machdep.c | 5 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/sendsig.c | 7 | ||||
-rw-r--r-- | sys/arch/mips64/mips64/trap.c | 25 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/trap.c | 20 | ||||
-rw-r--r-- | sys/arch/sh/sh/sh_machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/socppc/socppc/machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/machdep.c | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/trap.c | 19 |
22 files changed, 219 insertions, 44 deletions
diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index a4f9a41cd7f..a4ff49d2e6b 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.183 2017/12/30 20:46:59 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.184 2018/04/12 17:13:41 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */ /*- @@ -1414,8 +1414,9 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(oldsp) && (psp->ps_sigonstack & sigmask(sig))) - scp = (struct sigcontext *)(p->p_sigstk.ss_sp + - p->p_sigstk.ss_size - rndfsize); + scp = (struct sigcontext *) + (trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size) + - rndfsize); else scp = (struct sigcontext *)(oldsp - rndfsize); diff --git a/sys/arch/alpha/alpha/trap.c b/sys/arch/alpha/alpha/trap.c index 2fee1864859..2dce18bcb26 100644 --- a/sys/arch/alpha/alpha/trap.c +++ b/sys/arch/alpha/alpha/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.84 2018/04/09 04:11:02 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.85 2018/04/12 17:13:41 deraadt Exp $ */ /* $NetBSD: trap.c,v 1.52 2000/05/24 16:48:33 thorpej Exp $ */ /*- @@ -242,8 +242,26 @@ trap(a0, a1, a2, entry, framep) framep->tf_regs[FRAME_SP] = alpha_pal_rdusp(); user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0; if (user) { + vaddr_t sp; + p->p_md.md_tf = framep; refreshcreds(p); + + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + 0, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, entry, SEGV_ACCERR, sv); + } + + KERNEL_UNLOCK(); + } } switch (entry) { diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index b05455ab943..8810f71dcb8 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.240 2018/03/29 01:21:02 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.241 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -593,7 +593,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, /* Allocate space for the signal handler context. */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_rsp) && (psp->ps_sigonstack & sigmask(sig))) - sp = (register_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size; + sp = trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else sp = tf->tf_rsp - 128; diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index dc2d115c207..418395b54b7 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.64 2018/02/21 19:24:15 guenther Exp $ */ +/* $OpenBSD: trap.c,v 1.65 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */ /*- @@ -175,9 +175,28 @@ trap(struct trapframe *frame) #endif if (!KERNELMODE(frame->tf_cs, frame->tf_rflags)) { + vaddr_t sp; + type |= T_USER; p->p_md.md_regs = frame; refreshcreds(p); + + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + (int)frame->tf_trapno, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, type & ~T_USER, + SEGV_ACCERR, sv); + } + + KERNEL_UNLOCK(); + } } switch (type) { diff --git a/sys/arch/arm/arm/fault.c b/sys/arch/arm/arm/fault.c index 8ece22e083b..c69f5ea9439 100644 --- a/sys/arch/arm/arm/fault.c +++ b/sys/arch/arm/arm/fault.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fault.c,v 1.32 2018/01/26 16:22:19 kettenis Exp $ */ +/* $OpenBSD: fault.c,v 1.33 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: fault.c,v 1.46 2004/01/21 15:39:21 skrll Exp $ */ /* @@ -237,8 +237,26 @@ data_abort_handler(trapframe_t *tf) */ if (user) { + vaddr_t sp; + p->p_addr->u_pcb.pcb_tf = tf; refreshcreds(p); + + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + 0, sp, p->p_spstart, p->p_spend); + + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, 0, SEGV_ACCERR, sv); + } + KERNEL_UNLOCK(); + } } /* diff --git a/sys/arch/arm/arm/sig_machdep.c b/sys/arch/arm/arm/sig_machdep.c index a0655e1bab1..8808158457a 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.15 2017/03/12 17:57:12 kettenis Exp $ */ +/* $OpenBSD: sig_machdep.c,v 1.16 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */ /* @@ -58,6 +58,8 @@ #include <machine/pcb.h> #include <arm/cpufunc.h> +#include <uvm/uvm_extern.h> + static __inline struct trapframe * process_frame(struct proc *p) { @@ -87,8 +89,8 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, /* 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))) - fp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + - p->p_sigstk.ss_size); + fp = (struct sigframe *) + trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else fp = (struct sigframe *)tf->tf_usr_sp; diff --git a/sys/arch/arm64/arm64/ast.c b/sys/arch/arm64/arm64/ast.c index 240d6cc5355..dc5586ff085 100644 --- a/sys/arch/arm64/arm64/ast.c +++ b/sys/arch/arm64/arm64/ast.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ast.c,v 1.4 2017/09/08 05:36:51 deraadt Exp $ */ +/* $OpenBSD: ast.c,v 1.5 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com> * @@ -18,7 +18,10 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/proc.h> #include <sys/user.h> +#include <sys/signal.h> #include <sys/syscall.h> #include <sys/syscall_mi.h> #include <machine/pcb.h> diff --git a/sys/arch/arm64/arm64/sig_machdep.c b/sys/arch/arm64/arm64/sig_machdep.c index 739544a5424..dcd0e38c0d6 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.4 2017/08/08 21:52:41 drahn Exp $ */ +/* $OpenBSD: sig_machdep.c,v 1.5 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -78,6 +78,8 @@ #include <machine/frame.h> #include <machine/pcb.h> +#include <uvm/uvm_extern.h> + static __inline struct trapframe * process_frame(struct proc *p) { @@ -109,8 +111,8 @@ sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, /* 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 *)((caddr_t)p->p_sigstk.ss_sp + - p->p_sigstk.ss_size); + fp = (struct sigframe *) + trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else fp = (struct sigframe *)tf->tf_sp; diff --git a/sys/arch/arm64/arm64/trap.c b/sys/arch/arm64/arm64/trap.c index c655e5e6607..6e493a4e15f 100644 --- a/sys/arch/arm64/arm64/trap.c +++ b/sys/arch/arm64/arm64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.18 2018/04/09 22:21:05 kettenis Exp $ */ +/* $OpenBSD: trap.c,v 1.19 2018/04/12 17:13:43 deraadt Exp $ */ /*- * Copyright (c) 2014 Andrew Turner * All rights reserved. @@ -225,6 +225,7 @@ do_el0_sync(struct trapframe *frame) union sigval sv; uint32_t exception; uint64_t esr, far; + vaddr_t sp; esr = READ_SPECIALREG(esr_el1); exception = ESR_ELx_EXCEPTION(esr); @@ -235,6 +236,21 @@ do_el0_sync(struct trapframe *frame) p->p_addr->u_pcb.pcb_tf = frame; refreshcreds(p); + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + exception, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, exception, SEGV_ACCERR, sv); + } + KERNEL_UNLOCK(); + } + switch(exception) { case EXCP_UNKNOWN: vfp_save(); diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c index 3cbd49e0e02..3f9b5f2ab77 100644 --- a/sys/arch/hppa/hppa/machdep.c +++ b/sys/arch/hppa/hppa/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.250 2017/12/30 20:46:59 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.251 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 1999-2003 Michael Shalayeff @@ -1224,7 +1224,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_sp) && (psp->ps_sigonstack & sigmask(sig))) - scp = (register_t)p->p_sigstk.ss_sp; + scp = round_page((vaddr_t)p->p_sigstk.ss_sp); else scp = (tf->tf_sp + 63) & ~63; diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c index b58f2c9158d..4769647a5d6 100644 --- a/sys/arch/hppa/hppa/trap.c +++ b/sys/arch/hppa/hppa/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.142 2017/07/22 15:20:11 kettenis Exp $ */ +/* $OpenBSD: trap.c,v 1.143 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 1998-2004 Michael Shalayeff @@ -213,9 +213,29 @@ trap(int type, struct trapframe *frame) mtctl(frame->tf_eiem, CR_EIEM); } - if (type & T_USER) + if (type & T_USER) { + vaddr_t sp; + refreshcreds(p); + //sp = frame->tf_sp; + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + type & ! ~T_USER, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, type & ~T_USER, + SEGV_ACCERR, sv); + } + KERNEL_UNLOCK(); + } + } + switch (type) { case T_NONEXIST: case T_NONEXIST | T_USER: diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 14f8a48bd8e..6f7c5d4fca1 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.615 2018/04/11 15:44:08 bluhm Exp $ */ +/* $OpenBSD: machdep.c,v 1.616 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -2401,7 +2401,7 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_esp) && (psp->ps_sigonstack & sigmask(sig))) - sp = (long)p->p_sigstk.ss_sp + p->p_sigstk.ss_size; + sp = trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else sp = tf->tf_esp; diff --git a/sys/arch/i386/i386/trap.c b/sys/arch/i386/i386/trap.c index c801739197b..046cbc9e274 100644 --- a/sys/arch/i386/i386/trap.c +++ b/sys/arch/i386/i386/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.136 2017/10/04 17:41:01 deraadt Exp $ */ +/* $OpenBSD: trap.c,v 1.137 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: trap.c,v 1.95 1996/05/05 06:50:02 mycroft Exp $ */ /*- @@ -154,9 +154,27 @@ trap(struct trapframe *frame) #endif if (!KERNELMODE(frame->tf_cs, frame->tf_eflags)) { + vaddr_t sp; + type |= T_USER; p->p_md.md_regs = frame; refreshcreds(p); + + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + (int)frame->tf_trapno, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, type & ~T_USER, + SEGV_ACCERR, sv); + } + KERNEL_UNLOCK(); + } } switch (type) { diff --git a/sys/arch/m88k/m88k/sig_machdep.c b/sys/arch/m88k/m88k/sig_machdep.c index 534b173b712..7b9766ab7b5 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.27 2016/10/08 23:31:57 guenther Exp $ */ +/* $OpenBSD: sig_machdep.c,v 1.28 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 2014 Miodrag Vallat. * @@ -128,7 +128,8 @@ sendsig(sig_t catcher, int sig, int mask, unsigned long code, int type, if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->tf_r[31]) && (psp->ps_sigonstack & sigmask(sig))) { addr = local_stack_frame(tf, - (vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size, fsize); + trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size), + fsize); } else addr = local_stack_frame(tf, tf->tf_r[31], fsize); diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c index 6aaae3cb1cb..1470b2a78df 100644 --- a/sys/arch/macppc/macppc/machdep.c +++ b/sys/arch/macppc/macppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.182 2017/12/11 05:27:40 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.183 2018/04/12 17:13:43 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -461,8 +461,8 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->fixreg[1]) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)(p->p_sigstk.ss_sp - + p->p_sigstk.ss_size); + fp = (struct sigframe *) + trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else fp = (struct sigframe *)tf->fixreg[1]; diff --git a/sys/arch/mips64/mips64/sendsig.c b/sys/arch/mips64/mips64/sendsig.c index 3e6ebfd02e8..38b8324aa22 100644 --- a/sys/arch/mips64/mips64/sendsig.c +++ b/sys/arch/mips64/mips64/sendsig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sendsig.c,v 1.27 2016/05/21 00:56:43 deraadt Exp $ */ +/* $OpenBSD: sendsig.c,v 1.28 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -121,8 +121,9 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, fsize -= sizeof(siginfo_t); if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(regs->sp) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)(p->p_sigstk.ss_sp + - p->p_sigstk.ss_size - fsize); + fp = (struct sigframe *) + (trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size) + - fsize); else fp = (struct sigframe *)(regs->sp - fsize); /* diff --git a/sys/arch/mips64/mips64/trap.c b/sys/arch/mips64/mips64/trap.c index 75f6c1360cd..4ffa78973cf 100644 --- a/sys/arch/mips64/mips64/trap.c +++ b/sys/arch/mips64/mips64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.130 2017/09/02 15:56:29 visa Exp $ */ +/* $OpenBSD: trap.c,v 1.131 2018/04/12 17:13:43 deraadt Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -251,9 +251,30 @@ trap(struct trapframe *trapframe) } #endif - if (type & T_USER) + if (type & T_USER) { + vaddr_t sp; + refreshcreds(p); + sp = trapframe->sp; + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + union sigval sv; + + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, type, + sp, p->p_spstart, p->p_spend); + + sv.sival_ptr = (void *)trapframe->pc; + trapsignal(p, SIGSEGV, 0, SEGV_ACCERR, sv); + } + KERNEL_UNLOCK(); + } + } + itsa(trapframe, ci, p, type); if (type & T_USER) diff --git a/sys/arch/powerpc/powerpc/trap.c b/sys/arch/powerpc/powerpc/trap.c index 5974f88b802..564cdf2f640 100644 --- a/sys/arch/powerpc/powerpc/trap.c +++ b/sys/arch/powerpc/powerpc/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.106 2016/12/20 12:08:01 jsg Exp $ */ +/* $OpenBSD: trap.c,v 1.107 2018/04/12 17:13:44 deraadt Exp $ */ /* $NetBSD: trap.c,v 1.3 1996/10/13 03:31:37 christos Exp $ */ /* @@ -234,8 +234,26 @@ trap(struct trapframe *frame) db_expr_t offset; if (frame->srr1 & PSL_PR) { + vaddr_t sp; + type |= EXC_USER; refreshcreds(p); + + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + type, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, type, SEGV_ACCERR, sv); + } + + KERNEL_UNLOCK(); + } } switch (type) { diff --git a/sys/arch/sh/sh/sh_machdep.c b/sys/arch/sh/sh/sh_machdep.c index ec1c393a77d..218db7f2e75 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.46 2016/05/21 00:56:44 deraadt Exp $ */ +/* $OpenBSD: sh_machdep.c,v 1.47 2018/04/12 17:13:44 deraadt Exp $ */ /* $NetBSD: sh3_machdep.c,v 1.59 2006/03/04 01:13:36 uwe Exp $ */ /* @@ -460,8 +460,8 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(p->p_md.md_regs->tf_r15) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)((vaddr_t)p->p_sigstk.ss_sp + - p->p_sigstk.ss_size); + fp = (struct sigframe *) + trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else fp = (void *)p->p_md.md_regs->tf_r15; --fp; diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c index bf0b0228074..830a2e24307 100644 --- a/sys/arch/socppc/socppc/machdep.c +++ b/sys/arch/socppc/socppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.73 2017/12/11 05:27:40 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.74 2018/04/12 17:13:44 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -487,8 +487,8 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(tf->fixreg[1]) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)(p->p_sigstk.ss_sp - + p->p_sigstk.ss_size); + fp = (struct sigframe *) + trunc_page(vaddr_t)p->p_sigstk.ss_sp + pp->p_sigstk.ss_size); else fp = (struct sigframe *)tf->fixreg[1]; diff --git a/sys/arch/sparc64/sparc64/machdep.c b/sys/arch/sparc64/sparc64/machdep.c index 153633b01fb..1aa11f69ac7 100644 --- a/sys/arch/sparc64/sparc64/machdep.c +++ b/sys/arch/sparc64/sparc64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.187 2017/12/30 20:46:59 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.188 2018/04/12 17:13:44 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.108 2001/07/24 19:30:14 eeh Exp $ */ /*- @@ -432,8 +432,8 @@ sendsig(sig_t catcher, int sig, int mask, u_long code, int type, */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !sigonstack(oldsp) && (psp->ps_sigonstack & sigmask(sig))) - fp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + - p->p_sigstk.ss_size); + fp = (struct sigframe *) + trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); else fp = (struct sigframe *)oldsp; /* Allocate an aligned sigframe */ diff --git a/sys/arch/sparc64/sparc64/trap.c b/sys/arch/sparc64/sparc64/trap.c index 55c8bd6213d..7cc1973a107 100644 --- a/sys/arch/sparc64/sparc64/trap.c +++ b/sys/arch/sparc64/sparc64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.98 2017/07/22 15:17:49 kettenis Exp $ */ +/* $OpenBSD: trap.c,v 1.99 2018/04/12 17:13:44 deraadt Exp $ */ /* $NetBSD: trap.c,v 1.73 2001/08/09 01:03:01 eeh Exp $ */ /* @@ -348,6 +348,7 @@ trap(struct trapframe64 *tf, unsigned type, vaddr_t pc, long tstate) struct proc *p; struct pcb *pcb; int pstate = (tstate>>TSTATE_PSTATE_SHIFT); + vaddr_t sp; u_int64_t s; int64_t n; union sigval sv; @@ -427,6 +428,22 @@ trap(struct trapframe64 *tf, unsigned type, vaddr_t pc, long tstate) p->p_md.md_tf = tf; /* for ptrace/signals */ refreshcreds(p); + sp = PROC_STACK(p); + if (p->p_vmspace->vm_map.serial != p->p_spserial || + p->p_spstart == 0 || sp < p->p_spstart || + sp >= p->p_spend) { + KERNEL_LOCK(); + if (!uvm_map_check_stack_range(p, sp)) { + printf("trap [%s]%d/%d type %d: sp %lx not inside %lx-%lx\n", + p->p_p->ps_comm, p->p_p->ps_pid, p->p_tid, + (int)type, sp, p->p_spstart, p->p_spend); + sv.sival_ptr = (void *)PROC_PC(p); + trapsignal(p, SIGSEGV, type, SEGV_ACCERR, sv); + } + + KERNEL_UNLOCK(); + } + switch (type) { default: |