kern/181497: ASLR Feature Request - patch included
Steven Lee
steven at roothosts.com
Sat Aug 24 02:20:00 UTC 2013
>Number: 181497
>Category: kern
>Synopsis: ASLR Feature Request - patch included
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Sat Aug 24 02:20:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator: Steven Lee
>Release: releng/9.2
>Organization:
Root Hosts
>Environment:
N/A
>Description:
Most modern operating systems have ASLR to help mitigate yet-unknown vulnerabilities.
It would be very nice if FreeBSD shipped with ASLR features in the kernel (default off), that could be easily switched on with a sysctl variable.
I understand that in some production environments ASLR may make a system slower through memory fragmentation, but at least give people the option to turn ASLR on for those who actually want it. :)
>How-To-Repeat:
N/A
>Fix:
This patch has been circulating the internet since FreeBSD 7.0-RELEASE at least. It looks like parts of it are from OpenBSD? (I could be wrong.) I've used it in production for many many years and it works like a champ.
The patch will just need the sysctl defaults inverted and the variable names possibly renamed for clarity.
Patch attached with submission follows:
commit 779a962519e7ead63dda24348b98f6cde8156752
Author: Oliver Pinter <opn at opn.(none)>
Date: Tue Oct 4 00:24:01 2011 +0200
forwardport mmap-randomization patch from 7-STABLE-op
Signed-off-by: Oliver Pinter <oliver.pntr at gmail.com>
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index fe01142..dc66db6 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -106,6 +106,7 @@ MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS);
static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS);
static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS);
+static int sysctl_kern_stackgap_random(SYSCTL_HANDLER_ARGS);
static int do_execve(struct thread *td, struct image_args *args,
struct mac *mac_p);
@@ -120,6 +121,9 @@ SYSCTL_PROC(_kern, KERN_USRSTACK, usrstack, CTLTYPE_ULONG|CTLFLAG_RD|
SYSCTL_PROC(_kern, OID_AUTO, stackprot, CTLTYPE_INT|CTLFLAG_RD,
NULL, 0, sysctl_kern_stackprot, "I", "");
+SYSCTL_PROC(_kern, OID_AUTO, stackgap_random, CTLTYPE_INT|CTLFLAG_RW,
+ NULL, 0, sysctl_kern_stackgap_random, "I", "stackgap maximum offset");
+
u_long ps_arg_cache_limit = PAGE_SIZE / 16;
SYSCTL_ULONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW,
&ps_arg_cache_limit, 0, "");
@@ -177,6 +181,30 @@ sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS)
sizeof(p->p_sysent->sv_stackprot)));
}
+static int stackgap_random = 64 * 1024;
+
+static int
+sysctl_kern_stackgap_random(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+ int val;
+
+ val=stackgap_random;
+ err=sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr) {
+ return (err);
+ }
+
+ if ((val<ALIGNBYTES && (val!=0))
+ || !powerof2(val) || val>64*1024*1024) {
+ return (EINVAL);
+ }
+
+ stackgap_random=val;
+
+ return (0);
+}
+
/*
* Each of the items is a pointer to a `const struct execsw', hence the
* double pointer here.
@@ -1248,6 +1276,7 @@ exec_copyout_strings(imgp)
size_t execpath_len;
int szsigcode, szps;
char canary[sizeof(long) * 8];
+ int sgap;
szps = sizeof(pagesizes[0]) * MAXPAGESIZES;
/*
@@ -1265,7 +1294,11 @@ exec_copyout_strings(imgp)
if (p->p_sysent->sv_szsigcode != NULL)
szsigcode = *(p->p_sysent->sv_szsigcode);
}
- destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ sgap=0;
+ if (stackgap_random!=0) {
+ sgap=ALIGN(arc4random()&(stackgap_random-1));
+ }
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap -
roundup(execpath_len, sizeof(char *)) -
roundup(sizeof(canary), sizeof(char *)) -
roundup(szps, sizeof(char *)) -
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index e85b681..991a37d 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/sysent.h>
#include <sys/vmmeter.h>
+#include <sys/sysctl.h>
#include <security/mac/mac_framework.h>
@@ -99,6 +100,10 @@ static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
static int vm_mmap_shm(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
int *, struct shmfd *, vm_ooffset_t, vm_object_t *);
+static int mmap_random=1;
+SYSCTL_INT(_vm, OID_AUTO, mmap_random, CTLFLAG_RW, &mmap_random, 0,
+ "random mmap offset");
+
/*
* MPSAFE
*/
@@ -256,7 +261,8 @@ sys_mmap(td, uap)
/*
* XXX for non-fixed mappings where no hint is provided or
* the hint would fall in the potential heap space,
- * place it after the end of the largest possible heap.
+ * place it after the end of the largest possible heap,
+ * plus a random offset, if mmap_random is set.
*
* There should really be a pmap call to determine a reasonable
* location.
@@ -265,9 +271,13 @@ sys_mmap(td, uap)
if (addr == 0 ||
(addr >= round_page((vm_offset_t)vms->vm_taddr) &&
addr < round_page((vm_offset_t)vms->vm_daddr +
- lim_max(td->td_proc, RLIMIT_DATA))))
+ lim_max(td->td_proc, RLIMIT_DATA)))) {
addr = round_page((vm_offset_t)vms->vm_daddr +
lim_max(td->td_proc, RLIMIT_DATA));
+ if (mmap_random) {
+ addr+=arc4random()&(256*1024*1024-1);
+ }
+ }
PROC_UNLOCK(td->td_proc);
}
if (flags & MAP_ANON) {
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list