diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exec.c | 20 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 19 |
2 files changed, 33 insertions, 6 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index eaa05b0dc75..b49eb939c55 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.54 2001/06/27 04:49:41 art Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.55 2001/08/18 03:32:16 art Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -66,6 +66,15 @@ #include <machine/cpu.h> #include <machine/reg.h> +#include <dev/rndvar.h> + +/* + * stackgap_random specifies if the stackgap should have a random size added + * to it. Must be a n^2. If non-zero, the stack gap will be calculated as: + * (arc4random() * ALIGNBYTES) & (stackgap_random - 1) + STACKGAPLEN. + */ +int stackgap_random; + /* * check exec: * given an "executable" described in the exec package's namei info, @@ -219,7 +228,7 @@ sys_execve(p, v, retval) void *v; register_t *retval; { - register struct sys_execve_args /* { + struct sys_execve_args /* { syscallarg(char *) path; syscallarg(char * *) argp; syscallarg(char * *) envp; @@ -232,7 +241,7 @@ sys_execve(p, v, retval) char *argp; char * const *cpp, *dp, *sp; long argc, envc; - size_t len; + size_t len, sgap; #ifdef MACHINE_STACK_GROWS_UP size_t slen; #endif @@ -355,9 +364,12 @@ sys_execve(p, v, retval) szsigcode = pack.ep_emul->e_esigcode - pack.ep_emul->e_sigcode; + sgap = STACKGAPLEN; + if (stackgap_random != 0) + sgap += (arc4random() * ALIGNBYTES) & (stackgap_random - 1); /* Now check if args & environ fit into new stack */ len = ((argc + envc + 2 + pack.ep_emul->e_arglen) * sizeof(char *) + - sizeof(long) + dp + STACKGAPLEN + szsigcode + + sizeof(long) + dp + sgap + szsigcode + sizeof(struct ps_strings)) - argp; len = ALIGN(len); /* make the stack "safely" aligned */ diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index d2f2b25a5de..9b642481e68 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.55 2001/07/17 20:57:49 deraadt Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.56 2001/08/18 03:32:16 art Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -230,11 +230,12 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) size_t newlen; struct proc *p; { - int error, level, inthostid; + int error, level, inthostid, oldsgap; extern char ostype[], osrelease[], osversion[], version[]; extern int somaxconn, sominconn; extern int usermount, nosuidcoredump; extern long cp_time[CPUSTATES]; + extern int stackgap_random; /* all sysctl names at this level are terminal */ if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF || @@ -394,6 +395,20 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) return (sysctl_rdint(oldp, oldlenp, newp, nprocs)); case KERN_POOL: return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp)); + case KERN_STACKGAPRANDOM: + oldsgap = stackgap_random; + + error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap_random); + /* + * Safety harness. + */ + if ((stackgap_random < ALIGNBYTES && stackgap_random != 0) || + !powerof2(stackgap_random) || + stackgap_random > PAGE_SIZE * 2) { + stackgap_random = oldsgap; + return (EINVAL); + } + return (error); default: return (EOPNOTSUPP); } |