summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-01-26 22:51:38 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-01-26 22:51:38 +0000
commit9f3935eea3833737ce1128b568dda34e5c4ab8ce (patch)
tree2bf7f068c2864c5a2889260bf0f2be3669a3f1f0
parent40ecaaf940f5a7d17cd9eb113a1028c6a040fc63 (diff)
Move the "stackgap" from the stack into its own page at a random address.
This allows us the unmap the initial part of the stack, such that it can't be used as a staging area for ROP (or other) attacks. ok guenther@, tedu@
-rw-r--r--sys/compat/common/compat_util.c26
-rw-r--r--sys/kern/kern_exec.c23
-rw-r--r--sys/sys/exec.h22
-rw-r--r--sys/sys/proc.h3
4 files changed, 36 insertions, 38 deletions
diff --git a/sys/compat/common/compat_util.c b/sys/compat/common/compat_util.c
index 039fbe93426..f2121d8a417 100644
--- a/sys/compat/common/compat_util.c
+++ b/sys/compat/common/compat_util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat_util.c,v 1.14 2014/12/16 18:30:03 tedu Exp $ */
+/* $OpenBSD: compat_util.c,v 1.15 2015/01/26 22:51:37 kettenis Exp $ */
/* $NetBSD: compat_util.c,v 1.4 1996/03/14 19:31:45 christos Exp $ */
/*
@@ -40,6 +40,7 @@
#include <sys/ioctl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <uvm/uvm_extern.h>
@@ -176,24 +177,29 @@ bad:
caddr_t
stackgap_init(struct proc *p)
{
- return STACKGAPBASE;
+ struct process *pr = p->p_p;
+
+ if (pr->ps_stackgap == 0) {
+ if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_stackgap,
+ round_page(STACKGAPLEN), NULL, 0, 0,
+ UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
+ MAP_INHERIT_COPY, MADV_RANDOM, UVM_FLAG_COPYONW)))
+ sigexit(p, SIGILL);
+ }
+
+ return (caddr_t)pr->ps_stackgap;
}
-
+
void *
stackgap_alloc(caddr_t *sgp, size_t sz)
{
void *n = (void *) *sgp;
caddr_t nsgp;
-
+
sz = ALIGN(sz);
nsgp = *sgp + sz;
-#ifdef MACHINE_STACK_GROWS_UP
- if (nsgp > ((caddr_t)PS_STRINGS) + STACKGAPLEN)
- return NULL;
-#else
- if (nsgp > ((caddr_t)PS_STRINGS))
+ if (nsgp > (caddr_t)trunc_page((vaddr_t)n) + STACKGAPLEN)
return NULL;
-#endif
*sgp = nsgp;
return n;
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 811d8e7fa5c..d71053b77ea 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.156 2015/01/20 19:43:21 kettenis Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.157 2015/01/26 22:51:37 kettenis Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -451,6 +451,22 @@ sys_execve(struct proc *p, void *v, register_t *retval)
if (error)
goto exec_abort;
+ /* old "stackgap" is gone now */
+ pr->ps_stackgap = 0;
+
+#ifdef MACHINE_STACK_GROWS_UP
+ pr->ps_strings = (vaddr_t)USRSTACK + sgap;
+ if (uvm_map_protect(&vm->vm_map, (vaddr_t)vm->vm_maxsaddr,
+ trunc_page(pr->ps_strings), PROT_NONE, TRUE))
+ goto exec_abort;
+#else
+ pr->ps_strings = (vaddr_t)USRSTACK - sizeof(arginfo) - sgap;
+ if (uvm_map_protect(&vm->vm_map,
+ round_page(pr->ps_strings + sizeof(arginfo)),
+ (vaddr_t)vm->vm_minsaddr, PROT_NONE, TRUE))
+ goto exec_abort;
+#endif
+
/* remember information about the process */
arginfo.ps_nargvstr = argc;
arginfo.ps_nenvstr = envc;
@@ -466,11 +482,6 @@ sys_execve(struct proc *p, void *v, register_t *retval)
goto exec_abort;
/* copy out the process's ps_strings structure */
-#ifdef MACHINE_STACK_GROWS_UP
- pr->ps_strings = (vaddr_t)PS_STRINGS + sgap;
-#else
- pr->ps_strings = (vaddr_t)PS_STRINGS - sgap;
-#endif
if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo)))
goto exec_abort;
diff --git a/sys/sys/exec.h b/sys/sys/exec.h
index 81c13a7ca1b..3d8cf92e33a 100644
--- a/sys/sys/exec.h
+++ b/sys/sys/exec.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec.h,v 1.27 2013/10/17 08:02:20 deraadt Exp $ */
+/* $OpenBSD: exec.h,v 1.28 2015/01/26 22:51:37 kettenis Exp $ */
/* $NetBSD: exec.h,v 1.59 1996/02/09 18:25:09 christos Exp $ */
/*-
@@ -58,31 +58,11 @@ struct ps_strings {
};
/*
- * Address of ps_strings structure (in user space).
- */
-#ifdef MACHINE_STACK_GROWS_UP
-#define PS_STRINGS ((struct ps_strings *)(USRSTACK))
-#else
-#define PS_STRINGS \
- ((struct ps_strings *)(USRSTACK - sizeof(struct ps_strings)))
-#endif
-
-/*
* Below the PS_STRINGS and sigtramp, we may require a gap on the stack
* (used to copyin/copyout various emulation data structures).
*/
#define STACKGAPLEN (2*1024) /* plenty enough for now */
-#ifdef MACHINE_STACK_GROWS_UP
-#define STACKGAPBASE_UNALIGNED \
- ((caddr_t)PS_STRINGS + sizeof(struct ps_strings))
-#else
-#define STACKGAPBASE_UNALIGNED \
- ((caddr_t)PS_STRINGS - STACKGAPLEN)
-#endif
-#define STACKGAPBASE \
- ((caddr_t)ALIGN(STACKGAPBASE_UNALIGNED))
-
/*
* the following structures allow execve() to put together processes
* in a more extensible and cleaner way.
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 77a372f425d..f00a9f8d48b 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.193 2015/01/20 19:43:21 kettenis Exp $ */
+/* $OpenBSD: proc.h,v 1.194 2015/01/26 22:51:37 kettenis Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -200,6 +200,7 @@ struct process {
struct pgrp *ps_pgrp; /* Pointer to process group. */
struct emul *ps_emul; /* Emulation information */
vaddr_t ps_strings; /* User pointers to argv/env */
+ vaddr_t ps_stackgap; /* User pointer to the "stackgap" */
vaddr_t ps_sigcode; /* User pointer to the signal code */
u_int ps_rtableid; /* Process routing table/domain. */
char ps_nice; /* Process "nice" value. */