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/alpha | |
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/alpha')
-rw-r--r-- | sys/arch/alpha/alpha/machdep.c | 7 | ||||
-rw-r--r-- | sys/arch/alpha/alpha/trap.c | 20 |
2 files changed, 23 insertions, 4 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) { |