summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2018-04-12 17:13:45 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2018-04-12 17:13:45 +0000
commit9e91f96d779c665c5377cfd5667ee7e276f4c6eb (patch)
treefe187bb093929803715228a98ffc99028915fbad /sys/arch/sparc64
parent0f04bf0af32f3ceff2d723822807131626fbff5d (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/sparc64')
-rw-r--r--sys/arch/sparc64/sparc64/machdep.c6
-rw-r--r--sys/arch/sparc64/sparc64/trap.c19
2 files changed, 21 insertions, 4 deletions
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: