diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-08-18 03:32:17 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-08-18 03:32:17 +0000 |
commit | 3f31c981b1a74d2ecb49a95f024d91fda9334da9 (patch) | |
tree | dd70740acafee7540a927682344dd670f5212846 /sys/kern | |
parent | a33427cdc74e87f3a511989dc14ddfedf42e80a4 (diff) |
Add a possibility to add a random offset to the stack on exec. This makes
it slightly harder to write generic buffer overflows. This doesn't really
give any real security, but it raises the bar for script-kiddies and it's
really cheap.
The range of the random offsets is controlled by the sysctl
kern.stackgap_random (must be a power of 2).
This is disabled by default right now, but we'll set it to a reasonable value
(1024?) soon, after some more testing.
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); } |