diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-01-26 22:51:38 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-01-26 22:51:38 +0000 |
commit | 9f3935eea3833737ce1128b568dda34e5c4ab8ce (patch) | |
tree | 2bf7f068c2864c5a2889260bf0f2be3669a3f1f0 | |
parent | 40ecaaf940f5a7d17cd9eb113a1028c6a040fc63 (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.c | 26 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 23 | ||||
-rw-r--r-- | sys/sys/exec.h | 22 | ||||
-rw-r--r-- | sys/sys/proc.h | 3 |
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. */ |