From nobody@FreeBSD.org  Sat Aug 24 02:15:41 2013
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTP id D19C165E
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 24 Aug 2013 02:15:41 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from oldred.freebsd.org (oldred.freebsd.org [8.8.178.121])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by mx1.freebsd.org (Postfix) with ESMTPS id AF872233C
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 24 Aug 2013 02:15:41 +0000 (UTC)
Received: from oldred.freebsd.org ([127.0.1.6])
	by oldred.freebsd.org (8.14.5/8.14.7) with ESMTP id r7O2FfEn009157
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 24 Aug 2013 02:15:41 GMT
	(envelope-from nobody@oldred.freebsd.org)
Received: (from nobody@localhost)
	by oldred.freebsd.org (8.14.5/8.14.5/Submit) id r7O2Ff2o009155;
	Sat, 24 Aug 2013 02:15:41 GMT
	(envelope-from nobody)
Message-Id: <201308240215.r7O2Ff2o009155@oldred.freebsd.org>
Date: Sat, 24 Aug 2013 02:15:41 GMT
From: Steven Lee <steven@roothosts.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: ASLR Feature Request - patch included
X-Send-Pr-Version: www-3.1
X-GNATS-Notify: swills@FreeBSD.org

>Number:         181497
>Category:       kern
>Synopsis:       [kernel] [patch] Add ASLR feature to kernel
>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:  Sun Mar 23 07:06:48 UTC 2014
>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@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@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:

From: Oliver Pinter <oliver.pntr@gmail.com>
To: Steven Lee <steven@roothosts.com>
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: kern/181497: ASLR Feature Request - patch included
Date: Sat, 24 Aug 2013 15:48:49 +0200

 new version of the patchset:
 https://github.com/opntr/freebsd-patches-2013-tavasz/tree/master/r249952+ASLR
 

From: Steven Lee <steven@roothosts.com>
To: Oliver Pinter <oliver.pntr@gmail.com>, 
 freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/181497: ASLR Feature Request - patch included
Date: Sat, 24 Aug 2013 14:49:03 -0600

 Wow... very nice. :)
 
 -- 
 Regards,
 Steven Lee
 

From: Mark Linimon <linimon@lonesome.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: [oliver.pntr@gmail.com: Re: kern/181497: ASLR Feature Request -
 patch included]
Date: Sat, 24 Aug 2013 21:59:17 -0500

 ----- Forwarded message from Oliver Pinter <oliver.pntr@gmail.com> -----
 
 Date: Sat, 24 Aug 2013 23:40:15 +0200
 From: Oliver Pinter <oliver.pntr@gmail.com>
 To: Steven Lee <steven@roothosts.com>
 Cc: freebsd-bugs@freebsd.org
 Subject: Re: kern/181497: ASLR Feature Request - patch included
 
 performance test on HEAD from Juni + ASLR patches:
 http://centaur.sch.bme.hu/~oliverp/hunger/new/
 
 ----- End forwarded message -----

From: Shawn Webb <lattera@gmail.com>
To: bug-followup@FreeBSD.org,
 steven@roothosts.com
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Sun, 2 Feb 2014 19:34:40 -0500

 --Apple-Mail=_B6453ACB-0EC9-4C80-B575-87E00F273BCF
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii
 
 Over the past few months, I've had the pleasure of enhancing Oliver's =
 original patch. I've added support for randomizing the address of the =
 RTLD and changing the behavior of ASLR to be set on a per-jail basis. =
 This means that if a user requires an application that doesn't support =
 ASLR (crashes, exhibits bugs, etc.), then the affected application can =
 simply be placed in a jail with ASLR turned off. The rest of the system =
 and the rest of the jails would still have ASLR turned on.
 
 Oliver had ported over PaX's ASLR to NetBSD a few years back, and these =
 patches brings FreeBSD feature-for-feature complete with NetBSD's ASLR =
 implementation. What's lacking, along with NetBSD's implementation, is =
 exec base randomization. This needs to be done on a per-binary basis, =
 for binaries compiled with -fPIE. Additionally, we might want to =
 specifically mark executables with an ELF note, specifying that it's =
 safe to relocate the exec base.
 
 One known bug is that applications compiled with clang with -fPIC -fPIE =
 -static combined could segfault. I can provide a sample binary (with =
 sample code) if needed for a simple five-line test application.
 
 I will continue to research exec base randomization, but this task might =
 be a bit over my head skill-wise.
 
 Attached is the patch against 11-current as of 02 Feb 2014. If I make =
 more progress on exec base randomization, you can follow my GitHub repo =
 at https://github.com/lattera/freebsd, branch soldierx/lattera/aslr.
 
 Thanks,
 
 Shawn Webb
 
 
 --Apple-Mail=_B6453ACB-0EC9-4C80-B575-87E00F273BCF
 Content-Disposition: attachment;
 	filename=fbsd_aslr_11-current-2014-02-02.patch.txt
 Content-Type: text/plain;
 	name="fbsd_aslr_11-current-2014-02-02.patch.txt"
 Content-Transfer-Encoding: quoted-printable
 
 diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
 index f6da68e..3f9487c 100644
 --- a/sys/kern/imgact_elf.c
 +++ b/sys/kern/imgact_elf.c
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_compat.h"
  #include "opt_core.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/capability.h>
 @@ -47,7 +48,9 @@ __FBSDID("$FreeBSD$");
  #include <sys/mount.h>
  #include <sys/mman.h>
  #include <sys/namei.h>
 +#include <sys/pax.h>
  #include <sys/pioctl.h>
 +#include <sys/jail.h>
  #include <sys/proc.h>
  #include <sys/procfs.h>
  #include <sys/racct.h>
 @@ -600,6 +603,7 @@ __elfN(load_file)(struct proc *p, const char *file, =
 u_long *addr,
  	u_long rbase;
  	u_long base_addr =3D 0;
  	int error, i, numsegs;
 +    struct prison *pr; /* For ASLR */
 =20
  #ifdef CAPABILITY_MODE
  	/*
 @@ -664,6 +668,13 @@ __elfN(load_file)(struct proc *p, const char *file, =
 u_long *addr,
  		goto fail;
  	}
 =20
 +#ifdef PAX_ASLR
 +    pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +    if (pax_aslr_active(NULL, imgp->proc)) {
 +        rbase +=3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +    }
 +#endif
 +
  	/* Only support headers that fit within first page for now      =
 */
  	if ((hdr->e_phoff > PAGE_SIZE) ||
  	    (u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - =
 hdr->e_phoff) {
 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
 index 9f4ceac..099ff0a 100644
 --- a/sys/kern/kern_exec.c
 +++ b/sys/kern/kern_exec.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_hwpmc_hooks.h"
  #include "opt_ktrace.h"
 +#include "opt_pax.h"
  #include "opt_vm.h"
 =20
  #include <sys/param.h>
 @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$");
  dtrace_execexit_func_t	dtrace_fasttrap_exec;
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  SDT_PROVIDER_DECLARE(proc);
  SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
  SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
 @@ -1055,6 +1060,10 @@ exec_new_vmspace(imgp, sv)
  		map =3D &vmspace->vm_map;
  	}
 =20
 +#ifdef PAX_ASLR
 +	pax_aslr_init(curthread, imgp);
 +#endif /* PAX_ASLR */
 +
  	/* Map a shared page */
  	obj =3D sv->sv_shared_page_obj;
  	if (obj !=3D NULL) {
 @@ -1232,12 +1241,16 @@ exec_copyout_strings(imgp)
  	int argc, envc;
  	char **vectp;
  	char *stringp, *destp;
 +#ifdef	PAX_ASLR
 +	char *orig_destp;
 +#endif /* PAX_ASLR */
  	register_t *stack_base;
  	struct ps_strings *arginfo;
  	struct proc *p;
  	size_t execpath_len;
  	int szsigcode, szps;
  	char canary[sizeof(long) * 8];
 +    unsigned int sgap;
 =20
  	szps =3D sizeof(pagesizes[0]) * MAXPAGESIZES;
  	/*
 @@ -1255,11 +1268,16 @@ exec_copyout_strings(imgp)
  		if (p->p_sysent->sv_szsigcode !=3D NULL)
  			szsigcode =3D *(p->p_sysent->sv_szsigcode);
  	}
 -	destp =3D	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
 +    sgap=3D(unsigned int)(ALIGN(arc4random()&((64*1024)-1)));
 +	destp =3D	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE - =
 sgap -
  	    roundup(execpath_len, sizeof(char *)) -
  	    roundup(sizeof(canary), sizeof(char *)) -
  	    roundup(szps, sizeof(char *)) -
  	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char =
 *));
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 =20
  	/*
  	 * install sigcode
 diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
 index 700b7d6..af97118 100644
 --- a/sys/kern/kern_jail.c
 +++ b/sys/kern/kern_jail.c
 @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_ddb.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/types.h>
 @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/syscallsubr.h>
  #include <sys/sysctl.h>
  #include <sys/vnode.h>
 +#include <sys/pax.h>
 =20
  #include <net/if.h>
  #include <net/if_var.h>
 @@ -114,6 +116,20 @@ struct prison prison0 =3D {
  	.pr_flags	=3D PR_HOST|_PR_IP_SADDRSEL,
  #endif
  	.pr_allow	=3D PR_ALLOW_ALL,
 +#ifdef PAX_ASLR
 +    .pr_pax_set =3D 0,
 +    .pr_pax_aslr_status =3D 0,
 +    .pr_pax_aslr_debug =3D 0,
 +    .pr_pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN,
 +#ifdef COMPAT_FREEBSD32
 +    .pr_pax_aslr_compat_status =3D 0,
 +    .pr_pax_aslr_compat_mmap_len =3D =
 PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_compat_stack_len =3D =
 PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_compat_exec_len =3D =
 PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN,
 +#endif /* COMPAT_FREEBSD32 */
 +#endif /* PAX_ASLR */
  };
  MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
 =20
 diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
 new file mode 100644
 index 0000000..9182606
 --- /dev/null
 +++ b/sys/kern/kern_pax.c
 @@ -0,0 +1,589 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#include <sys/cdefs.h>
 +__FBSDID("$FreeBSD$");
 +
 +#include "opt_pax.h"
 +#include "opt_compat.h"
 +
 +#include <sys/param.h>
 +#include <sys/systm.h>
 +#include <sys/kernel.h>
 +#include <sys/imgact.h>
 +#include <sys/sysent.h>
 +#include <sys/proc.h>
 +#include <sys/elf_common.h>
 +#include <sys/pax.h>
 +#include <sys/sysctl.h>
 +#include <sys/vnode.h>
 +#include <sys/queue.h>
 +#include <sys/libkern.h>
 +#include <sys/jail.h>
 +
 +#include <sys/mman.h>
 +#include <sys/libkern.h>
 +#include <sys/exec.h>
 +
 +#include <vm/pmap.h>
 +#include <vm/vm_map.h>
 +
 +static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS);
 +
 +/*
 + * sysctls and tunables
 + */
 +int pax_aslr_status =3D PAX_ASLR_ENABLED;
 +int pax_aslr_debug =3D 0;
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MAX_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +
 +SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
 +    "PaX (exploit mitigation) features.");
 +SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0,
 +    "Address Space Layout Randomization.");
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status);
 +
 +SYSCTL_INT(_security_pax_aslr, OID_AUTO, debug, =
 CTLFLAG_RWTUN|CTLFLAG_PRISON, &pax_aslr_debug, 0, "ASLR debug mode");
 +TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16] 64 bit: [16,32]");
 +TUNABLE_INT("security.pax.aslr.mmap", &pax_aslr_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_exec_len);
 +
 +static int
 +sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_status =3D val;
 +            if (pr)
 +                pr->pr_pax_aslr_status =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_mmap_len : =
 pax_aslr_mmap_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_mmap_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_mmap_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_stack_len : =
 pax_aslr_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_stack_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_stack_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : =
 pax_aslr_exec_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_exec_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_exec_len =3D val;
 +
 +    return (0);
 +}
 +
 +/*
 + * COMPAT_FREEBSD32 and linuxulator..
 + */
 +#ifdef COMPAT_FREEBSD32
 +int pax_aslr_compat_status =3D PAX_ASLR_ENABLED;
 +
 +static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS);
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0,
 +    "Setting for COMPAT_FREEBSD32 and linuxulator.");
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.compat.status", =
 &pax_aslr_compat_status);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16]");
 +TUNABLE_INT("security.pax.aslr.compat.mmap", =
 &pax_aslr_compat_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_exec_len);
 +
 +
 +static int
 +sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_status) : =
 &pax_aslr_compat_status;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_compat_status =3D val;
 +            *ptr =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_mmap_len) : =
 &pax_aslr_compat_mmap_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_mmap_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_stack_len) : =
 &pax_aslr_compat_stack_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_compat_stack_len : =
 pax_aslr_compat_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_stack_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_exec_len) : =
 &pax_aslr_compat_exec_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_exec_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +#endif /* COMPAT_FREEBSD32 */
 +
 +
 +/*
 + * ASLR functions
 + */
 +bool
 +pax_aslr_active(struct thread *td, struct proc *proc)
 +{
 +    int status;
 +    struct prison *pr=3DNULL;
 +#ifdef  notyet
 +    uint32_t    flags;
 +#endif /* notyet */
 +
 +    if (!(td) && !(proc))
 +        return (true);
 +
 +#ifdef notyet
 +    flags =3D (td !=3D NULL) ? td->td_proc->p_pax : proc->p_pax;
 +#endif /* notyet */
 +    pr =3D pax_aslr_get_prison(td, proc);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    status =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : =
 pax_aslr_status;
 +
 +    switch (status) {
 +    case    PAX_ASLR_DISABLED:
 +        return (false);
 +    case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +        return (true);
 +    case    PAX_ASLR_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_ASLR) =3D=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    case    PAX_ASLR_GLOBAL_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_NOASLR) !=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    default:
 +        return (true);
 +    }
 +
 +    return (true);
 +}
 +
 +struct prison *
 +pax_aslr_get_prison(struct thread *td, struct proc *proc)
 +{
 +    if ((td)) {
 +        if ((td->td_proc) && (td->td_proc->p_ucred))
 +            return td->td_proc->p_ucred->cr_prison;
 +
 +        return NULL;
 +    }
 +
 +    if (!(proc))
 +        return NULL;
 +
 +    return proc->p_ucred->cr_prison;
 +}
 +
 +void
 +pax_aslr_init_prison(struct prison *pr)
 +{
 +    if (!(pr))
 +        return;
 +
 +    if (pr->pr_pax_set)
 +        return;
 +
 +    if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] pax_aslr_init_prison: Setting prison %s =
 ASLR variables\n", pr->pr_name);
 +
 +    pr->pr_pax_aslr_status =3D pax_aslr_status;
 +    pr->pr_pax_aslr_debug =3D pax_aslr_debug;
 +    pr->pr_pax_aslr_mmap_len =3D pax_aslr_mmap_len;
 +    pr->pr_pax_aslr_stack_len =3D pax_aslr_stack_len;
 +    pr->pr_pax_aslr_exec_len =3D pax_aslr_exec_len;
 +
 +#ifdef COMPAT_FREEBSD32
 +    pr->pr_pax_aslr_compat_status =3D pax_aslr_compat_status;
 +    pr->pr_pax_aslr_compat_mmap_len =3D pax_aslr_compat_mmap_len;
 +    pr->pr_pax_aslr_compat_stack_len =3D pax_aslr_compat_stack_len;
 +    pr->pr_pax_aslr_compat_exec_len =3D pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
 +
 +    pr->pr_pax_set =3D 1;
 +}
 +
 +void
 +pax_aslr_init(struct thread *td, struct image_params *imgp)
 +{
 +    struct vmspace *vm;
 +    u_int sv_flags;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    if (imgp =3D=3D NULL) {
 +        panic("[PaX ASLR] pax_aslr_init - imgp =3D=3D NULL");
 +    }
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    vm =3D imgp->proc->p_vmspace;
 +    sv_flags =3D imgp->proc->p_sysent->sv_flags;
 +
 +#ifndef COMPAT_FREEBSD32
 +    vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +    vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +    vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    vm->vm_aslr_delta_exec =3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : =
 pax_aslr_exec_len));
 +#else /* COMPAT_FREEBSD32 */
 +    if ((sv_flags & SV_LP64) !=3D 0) {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    } else {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compat_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    }
 +#endif /* !COMPAT_FREEBSD32 */
 +}
 +
 +void
 +pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t =
 orig_addr, int flags)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    if (!(flags & MAP_FIXED) && ((orig_addr =3D=3D 0) || !(flags & =
 MAP_ANON))) {
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] applying to %p orig_addr=3D%p f=3D%x\n",
 +                (void *)*addr, (void *)orig_addr, flags);
 +        if (!(td->td_proc->p_vmspace->vm_map.flags & =
 MAP_ENTRY_GROWS_DOWN))
 +            *addr +=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        else
 +            *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] result %p\n", (void *)*addr);
 +    }
 +    else if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] not applying to %p orig_addr=3D%p f=3D%x\n",
 +        (void *)*addr, (void *)orig_addr, flags);
 +}
 +
 +void
 +pax_aslr_stack(struct thread *td, char **addr, char *orig_addr)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_stack;
 +    if ((pr) && pr->pr_pax_aslr_debug)
 +        uprintf("[PaX ASLR] orig_addr=3D%p, addr=3D%p\n",
 +            (void *)orig_addr, (void *)*addr);
 +}
 diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
 index f99e053..e575aa7 100644
 --- a/sys/kern/kern_prot.c
 +++ b/sys/kern/kern_prot.c
 @@ -1612,9 +1612,42 @@ p_cansched(struct thread *td, struct proc *p)
   * XXX: data declarations should be together near the beginning of the =
 file.
   */
  static int	unprivileged_proc_debug =3D 1;
 +#if 0
  SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_proc_debug, =
 CTLFLAG_RW,
      &unprivileged_proc_debug, 0,
      "Unprivileged processes may use process debugging facilities");
 +#endif
 +
 +int
 +sysctl_unprivileged_proc_debug(SYSCTL_HANDLER_ARGS);
 +
 +SYSCTL_PROC(_security_bsd, OID_AUTO, unprivileged_proc_debug,
 +    CTLTYPE_INT | CTLFLAG_RW, &unprivileged_proc_debug, 0,
 +    sysctl_unprivileged_proc_debug, "I",
 +    "Unprivileged processes may use process debugging facilities");
 +
 +int
 +sysctl_unprivileged_proc_debug(SYSCTL_HANDLER_ARGS)
 +{
 +    static int set=3D0;
 +    int error =3D 0;
 +    int debug=3Dunprivileged_proc_debug;
 +
 +    error =3D sysctl_handle_int(oidp, &debug, 0, req);
 +    if (error =3D=3D 0 && req->newptr) {
 +        if (debug < 0 || debug > 1)
 +            return (EPERM);
 +
 +        if (debug !=3D unprivileged_proc_debug && set =3D=3D 0) {
 +            unprivileged_proc_debug =3D debug;
 +            set++;
 +        } else {
 +            return (EPERM);
 +        }
 +    }
 +
 +    return (error);
 +}
 =20
  /*-
   * Determine whether td may debug p.
 @@ -1631,11 +1664,9 @@ p_candebug(struct thread *td, struct proc *p)
 =20
  	KASSERT(td =3D=3D curthread, ("%s: td not curthread", =
 __func__));
  	PROC_LOCK_ASSERT(p, MA_OWNED);
 -	if (!unprivileged_proc_debug) {
 -		error =3D priv_check(td, PRIV_DEBUG_UNPRIV);
 -		if (error)
 -			return (error);
 -	}
 +	if (!unprivileged_proc_debug)
 +			return (EPERM);
 +
  	if (td->td_proc =3D=3D p)
  		return (0);
  	if ((error =3D prison_check(td->td_ucred, p->p_ucred)))
 diff --git a/sys/sys/jail.h b/sys/sys/jail.h
 index 59d791c..f2bb97c 100644
 --- a/sys/sys/jail.h
 +++ b/sys/sys/jail.h
 @@ -184,6 +184,20 @@ struct prison {
  	char		 pr_hostname[MAXHOSTNAMELEN];	/* (p) jail =
 hostname */
  	char		 pr_domainname[MAXHOSTNAMELEN];	/* (p) jail =
 domainname */
  	char		 pr_hostuuid[HOSTUUIDLEN];	/* (p) jail =
 hostuuid */
 +#ifdef PAX_ASLR
 +    int pr_pax_set;
 +    int pr_pax_aslr_status;
 +    int pr_pax_aslr_debug;
 +    int pr_pax_aslr_mmap_len;
 +    int pr_pax_aslr_stack_len;
 +    int pr_pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +#if defined(PAX_ASLR) && defined(COMPAT_FREEBSD32)
 +    int pr_pax_aslr_compat_status;
 +    int pr_pax_aslr_compat_mmap_len;
 +    int pr_pax_aslr_compat_stack_len;
 +    int pr_pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
  };
 =20
  struct prison_racct {
 diff --git a/sys/sys/pax.h b/sys/sys/pax.h
 new file mode 100644
 index 0000000..9c36894
 --- /dev/null
 +++ b/sys/sys/pax.h
 @@ -0,0 +1,166 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#ifndef	__SYS_PAX_H
 +#define	__SYS_PAX_H
 +
 +struct image_params;
 +struct thread;
 +struct vmspace;
 +struct vm_offset_t;
 +
 +/*
 + * used in sysctl handler
 + */
 +#define	PAX_ASLR_DISABLED		0
 +#define PAX_ASLR_ENABLED		1
 +#define PAX_ASLR_GLOBAL_ENABLED		2
 +#define	PAX_ASLR_FORCE_GLOBAL_ENABLED	3
 +
 +#ifndef PAX_ASLR_DELTA
 +#define	PAX_ASLR_DELTA(delta, lsb, len)	\
 +	(((delta) & ((1UL << (len)) - 1)) << (lsb))
 +#endif /* PAX_ASLR_DELTA */
 +
 +#ifdef PAX_ASLR
 +/*
 + * generic ASLR values
 + *
 + *  	MMAP	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  8 bit | 16 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 16 bit | 32 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	STACK	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	EXEC	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + */
 +#ifndef PAX_ASLR_DELTA_MMAP_LSB
 +#define PAX_ASLR_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_DELTA_MMAP_MIN_LEN	((sizeof(void *) * NBBY) / 4)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_DELTA_MMAP_MAX_LEN	((sizeof(void *) * NBBY) / 2)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_LSB
 +#define PAX_ASLR_DELTA_STACK_LSB	3
 +#endif /* PAX_ASLR_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_DELTA_STACK_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_DELTA_STACK_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_LSB
 +#define PAX_ASLR_DELTA_EXEC_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_EXEC_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_DELTA_EXEC_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_DELTA_EXEC_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +/*
 + * ASLR values for COMPAT_FREEBSD32 and COMPAT_LINUX
 + */
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN	((sizeof(int) * NBBY) / =
 4)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN	((sizeof(int) * NBBY) / =
 2)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB
 +#define PAX_ASLR_COMPAT_DELTA_STACK_LSB		3
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +extern int pax_aslr_status;
 +extern int pax_aslr_debug;
 +extern int pax_aslr_compat_status;
 +
 +extern int pax_aslr_mmap_len;
 +extern int pax_aslr_stack_len;
 +extern int pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +
 +void pax_init(void);
 +void pax_aslr_init_prison(struct prison *pr);
 +bool pax_aslr_active(struct thread *td, struct proc *proc);
 +void pax_aslr_init(struct thread *td, struct image_params *imgp);
 +void pax_aslr_mmap(struct thread *td, vm_offset_t *addr,
 +			vm_offset_t orig_addr, int flags);
 +void pax_aslr_stack(struct thread *td, char **addr, char *orig_addr);
 +struct prison *pax_aslr_get_prison(struct thread *td, struct proc =
 *proc);
 +
 +#endif /* __SYS_PAX_H */
 
 --Apple-Mail=_B6453ACB-0EC9-4C80-B575-87E00F273BCF--

From: =?ISO-8859-1?Q?Olivier_Cochard=2DLabb=E9?= <olivier@cochard.me>
To: bug-followup@freebsd.org, steven@roothosts.com
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Mon, 3 Feb 2014 16:46:47 +0100

 --089e0160c5e4989c9f04f1826ff6
 Content-Type: text/plain; charset=ISO-8859-1
 
 I've try to patch 10.0 with the last attached patch, but it complains
 because it didn't find file opt_pax.h (and I didn't see this file in the
 patch).
 
 --089e0160c5e4989c9f04f1826ff6
 Content-Type: text/html; charset=ISO-8859-1
 
 <div dir="ltr">I&#39;ve try to patch 10.0 with the last attached patch, but it complains because it didn&#39;t fin<span class="">d file opt_pax.h (and I didn&#39;t see this file in the patch).<br></span></div>
 
 --089e0160c5e4989c9f04f1826ff6--

From: Shawn Webb <lattera@gmail.com>
To: bug-followup@FreeBSD.org,
 steven@roothosts.com
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Tue, 4 Feb 2014 14:57:44 -0500

 --Apple-Mail=_70D08D01-527F-4575-806A-36757E957E5A
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii
 
 I'm sorry, my patch actually wasn't right. It included other fixes I had =
 in my branch for other features and didn't include some of the other =
 ASLR bits. Attached is the right patch.
 
 Thanks,
 
 Shawn
 
 
 --Apple-Mail=_70D08D01-527F-4575-806A-36757E957E5A
 Content-Disposition: attachment;
 	filename=2014-02-04_aslr.patch
 Content-Type: application/octet-stream;
 	x-unix-mode=0744;
 	name="2014-02-04_aslr.patch"
 Content-Transfer-Encoding: 7bit
 
 diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h
 index bda9722..5e83a8f 100644
 --- a/sys/amd64/include/vmparam.h
 +++ b/sys/amd64/include/vmparam.h
 @@ -170,7 +170,7 @@
  #define	VM_MAXUSER_ADDRESS	UVADDR(NUPML4E, 0, 0, 0)
  
  #define	SHAREDPAGE		(VM_MAXUSER_ADDRESS - PAGE_SIZE)
 -#define	USRSTACK		SHAREDPAGE
 +#define	USRSTACK		(SHAREDPAGE - 4*PAGE_SIZE)
  
  #define	VM_MAX_ADDRESS		UPT_MAX_ADDRESS
  #define	VM_MIN_ADDRESS		(0)
 diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
 index c7b677f..501e0b2 100644
 --- a/sys/compat/freebsd32/freebsd32_misc.c
 +++ b/sys/compat/freebsd32/freebsd32_misc.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_compat.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
  
  #define __ELF_WORD_SIZE 32
  
 @@ -113,6 +114,10 @@ __FBSDID("$FreeBSD$");
  
  FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
  
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  #ifndef __mips__
  CTASSERT(sizeof(struct timeval32) == 8);
  CTASSERT(sizeof(struct timespec32) == 8);
 @@ -2823,6 +2828,9 @@ freebsd32_copyout_strings(struct image_params *imgp)
  	int argc, envc, i;
  	u_int32_t *vectp;
  	char *stringp, *destp;
 +#ifdef PAX_ASLR
 +	char *orig_destp;
 +#endif /* PAX_ASLR */
  	u_int32_t *stack_base;
  	struct freebsd32_ps_strings *arginfo;
  	char canary[sizeof(long) * 8];
 @@ -2850,6 +2858,11 @@ freebsd32_copyout_strings(struct image_params *imgp)
  	    roundup(sizeof(pagesizes32), sizeof(char *)) -
  	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
  
 +#ifdef PAX_ASLR
 +	orig_destp = destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 +
  	/*
  	 * install sigcode
  	 */
 diff --git a/sys/conf/files b/sys/conf/files
 index dea5920..1c5dcf9 100644
 --- a/sys/conf/files
 +++ b/sys/conf/files
 @@ -2799,6 +2799,7 @@ kern/kern_mtxpool.c		standard
  kern/kern_mutex.c		standard
  kern/kern_ntptime.c		standard
  kern/kern_osd.c			standard
 +kern/kern_pax.c			optional pax_aslr
  kern/kern_physio.c		standard
  kern/kern_pmc.c			standard
  kern/kern_poll.c		optional device_polling
 diff --git a/sys/conf/options b/sys/conf/options
 index 7e0bb62..7ec2e13 100644
 --- a/sys/conf/options
 +++ b/sys/conf/options
 @@ -915,6 +915,9 @@ RACCT		opt_global.h
  # Resource Limits
  RCTL		opt_global.h
  
 +# PaX - hardening options
 +PAX_ASLR		opt_pax.h
 +PAX_ASLR_MAX_SEC	opt_pax.h
  # Random number generator(s)
  RANDOM_YARROW	opt_random.h
  RANDOM_FORTUNA	opt_random.h
 diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
 index f6da68e..3f9487c 100644
 --- a/sys/kern/imgact_elf.c
 +++ b/sys/kern/imgact_elf.c
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_compat.h"
  #include "opt_core.h"
 +#include "opt_pax.h"
  
  #include <sys/param.h>
  #include <sys/capability.h>
 @@ -47,7 +48,9 @@ __FBSDID("$FreeBSD$");
  #include <sys/mount.h>
  #include <sys/mman.h>
  #include <sys/namei.h>
 +#include <sys/pax.h>
  #include <sys/pioctl.h>
 +#include <sys/jail.h>
  #include <sys/proc.h>
  #include <sys/procfs.h>
  #include <sys/racct.h>
 @@ -600,6 +603,7 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
  	u_long rbase;
  	u_long base_addr = 0;
  	int error, i, numsegs;
 +    struct prison *pr; /* For ASLR */
  
  #ifdef CAPABILITY_MODE
  	/*
 @@ -664,6 +668,13 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
  		goto fail;
  	}
  
 +#ifdef PAX_ASLR
 +    pr = pax_aslr_get_prison(NULL, imgp->proc);
 +    if (pax_aslr_active(NULL, imgp->proc)) {
 +        rbase += round_page(PAX_ASLR_DELTA(arc4random(), PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +    }
 +#endif
 +
  	/* Only support headers that fit within first page for now      */
  	if ((hdr->e_phoff > PAGE_SIZE) ||
  	    (u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) {
 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
 index 9f4ceac..099ff0a 100644
 --- a/sys/kern/kern_exec.c
 +++ b/sys/kern/kern_exec.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_hwpmc_hooks.h"
  #include "opt_ktrace.h"
 +#include "opt_pax.h"
  #include "opt_vm.h"
  
  #include <sys/param.h>
 @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$");
  dtrace_execexit_func_t	dtrace_fasttrap_exec;
  #endif
  
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  SDT_PROVIDER_DECLARE(proc);
  SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
  SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
 @@ -1055,6 +1060,10 @@ exec_new_vmspace(imgp, sv)
  		map = &vmspace->vm_map;
  	}
  
 +#ifdef PAX_ASLR
 +	pax_aslr_init(curthread, imgp);
 +#endif /* PAX_ASLR */
 +
  	/* Map a shared page */
  	obj = sv->sv_shared_page_obj;
  	if (obj != NULL) {
 @@ -1232,12 +1241,16 @@ exec_copyout_strings(imgp)
  	int argc, envc;
  	char **vectp;
  	char *stringp, *destp;
 +#ifdef	PAX_ASLR
 +	char *orig_destp;
 +#endif /* PAX_ASLR */
  	register_t *stack_base;
  	struct ps_strings *arginfo;
  	struct proc *p;
  	size_t execpath_len;
  	int szsigcode, szps;
  	char canary[sizeof(long) * 8];
 +    unsigned int sgap;
  
  	szps = sizeof(pagesizes[0]) * MAXPAGESIZES;
  	/*
 @@ -1255,11 +1268,16 @@ 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=(unsigned int)(ALIGN(arc4random()&((64*1024)-1)));
 +	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap -
  	    roundup(execpath_len, sizeof(char *)) -
  	    roundup(sizeof(canary), sizeof(char *)) -
  	    roundup(szps, sizeof(char *)) -
  	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
 +#ifdef PAX_ASLR
 +	orig_destp = destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
  
  	/*
  	 * install sigcode
 diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
 index 700b7d6..af97118 100644
 --- a/sys/kern/kern_jail.c
 +++ b/sys/kern/kern_jail.c
 @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_ddb.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
  
  #include <sys/param.h>
  #include <sys/types.h>
 @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/syscallsubr.h>
  #include <sys/sysctl.h>
  #include <sys/vnode.h>
 +#include <sys/pax.h>
  
  #include <net/if.h>
  #include <net/if_var.h>
 @@ -114,6 +116,20 @@ struct prison prison0 = {
  	.pr_flags	= PR_HOST|_PR_IP_SADDRSEL,
  #endif
  	.pr_allow	= PR_ALLOW_ALL,
 +#ifdef PAX_ASLR
 +    .pr_pax_set = 0,
 +    .pr_pax_aslr_status = 0,
 +    .pr_pax_aslr_debug = 0,
 +    .pr_pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_MIN_LEN,
 +#ifdef COMPAT_FREEBSD32
 +    .pr_pax_aslr_compat_status = 0,
 +    .pr_pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN,
 +#endif /* COMPAT_FREEBSD32 */
 +#endif /* PAX_ASLR */
  };
  MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
  
 diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
 new file mode 100644
 index 0000000..9182606
 --- /dev/null
 +++ b/sys/kern/kern_pax.c
 @@ -0,0 +1,589 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote products
 + *    derived from this software without specific prior written permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of SoldierX.
 + */
 +
 +#include <sys/cdefs.h>
 +__FBSDID("$FreeBSD$");
 +
 +#include "opt_pax.h"
 +#include "opt_compat.h"
 +
 +#include <sys/param.h>
 +#include <sys/systm.h>
 +#include <sys/kernel.h>
 +#include <sys/imgact.h>
 +#include <sys/sysent.h>
 +#include <sys/proc.h>
 +#include <sys/elf_common.h>
 +#include <sys/pax.h>
 +#include <sys/sysctl.h>
 +#include <sys/vnode.h>
 +#include <sys/queue.h>
 +#include <sys/libkern.h>
 +#include <sys/jail.h>
 +
 +#include <sys/mman.h>
 +#include <sys/libkern.h>
 +#include <sys/exec.h>
 +
 +#include <vm/pmap.h>
 +#include <vm/vm_map.h>
 +
 +static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS);
 +
 +/*
 + * sysctls and tunables
 + */
 +int pax_aslr_status = PAX_ASLR_ENABLED;
 +int pax_aslr_debug = 0;
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_MAX_LEN;
 +int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_MIN_LEN;
 +int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +
 +SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
 +    "PaX (exploit mitigation) features.");
 +SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0,
 +    "Address Space Layout Randomization.");
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status);
 +
 +SYSCTL_INT(_security_pax_aslr, OID_AUTO, debug, CTLFLAG_RWTUN|CTLFLAG_PRISON, &pax_aslr_debug, 0, "ASLR debug mode");
 +TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16] 64 bit: [16,32]");
 +TUNABLE_INT("security.pax.aslr.mmap", &pax_aslr_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_exec_len);
 +
 +static int
 +sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = (pr != NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_status = val;
 +            if (pr)
 +                pr->pr_pax_aslr_status = val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_mmap_len = val;
 +    if (pr)
 +        pr->pr_pax_aslr_mmap_len = val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_stack_len = val;
 +    if (pr)
 +        pr->pr_pax_aslr_stack_len = val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = (pr != NULL) ? pr->pr_pax_aslr_exec_len : pax_aslr_exec_len;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_exec_len = val;
 +    if (pr)
 +        pr->pr_pax_aslr_exec_len = val;
 +
 +    return (0);
 +}
 +
 +/*
 + * COMPAT_FREEBSD32 and linuxulator..
 + */
 +#ifdef COMPAT_FREEBSD32
 +int pax_aslr_compat_status = PAX_ASLR_ENABLED;
 +
 +static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS);
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN;
 +int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
 +int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0,
 +    "Setting for COMPAT_FREEBSD32 and linuxulator.");
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.compat.status", &pax_aslr_compat_status);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16]");
 +TUNABLE_INT("security.pax.aslr.compat.mmap", &pax_aslr_compat_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_exec_len);
 +
 +
 +static int
 +sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +    ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_status) : &pax_aslr_compat_status;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = *ptr;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_compat_status = val;
 +            *ptr = val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +    ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_mmap_len) : &pax_aslr_compat_mmap_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = *ptr;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_mmap_len = val;
 +    *ptr = val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +    ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_stack_len) : &pax_aslr_compat_stack_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = (pr != NULL) ? pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_stack_len = val;
 +    *ptr = val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(req->td, NULL);
 +    ptr = (pr != NULL) ? &(pr->pr_pax_aslr_compat_exec_len) : &pax_aslr_compat_exec_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val = *ptr;
 +    err = sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_exec_len = val;
 +    *ptr = val;
 +
 +    return (0);
 +}
 +#endif /* COMPAT_FREEBSD32 */
 +
 +
 +/*
 + * ASLR functions
 + */
 +bool
 +pax_aslr_active(struct thread *td, struct proc *proc)
 +{
 +    int status;
 +    struct prison *pr=NULL;
 +#ifdef  notyet
 +    uint32_t    flags;
 +#endif /* notyet */
 +
 +    if (!(td) && !(proc))
 +        return (true);
 +
 +#ifdef notyet
 +    flags = (td != NULL) ? td->td_proc->p_pax : proc->p_pax;
 +#endif /* notyet */
 +    pr = pax_aslr_get_prison(td, proc);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    status = (pr != NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
 +
 +    switch (status) {
 +    case    PAX_ASLR_DISABLED:
 +        return (false);
 +    case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +        return (true);
 +    case    PAX_ASLR_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_ASLR) == 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    case    PAX_ASLR_GLOBAL_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_NOASLR) != 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    default:
 +        return (true);
 +    }
 +
 +    return (true);
 +}
 +
 +struct prison *
 +pax_aslr_get_prison(struct thread *td, struct proc *proc)
 +{
 +    if ((td)) {
 +        if ((td->td_proc) && (td->td_proc->p_ucred))
 +            return td->td_proc->p_ucred->cr_prison;
 +
 +        return NULL;
 +    }
 +
 +    if (!(proc))
 +        return NULL;
 +
 +    return proc->p_ucred->cr_prison;
 +}
 +
 +void
 +pax_aslr_init_prison(struct prison *pr)
 +{
 +    if (!(pr))
 +        return;
 +
 +    if (pr->pr_pax_set)
 +        return;
 +
 +    if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] pax_aslr_init_prison: Setting prison %s ASLR variables\n", pr->pr_name);
 +
 +    pr->pr_pax_aslr_status = pax_aslr_status;
 +    pr->pr_pax_aslr_debug = pax_aslr_debug;
 +    pr->pr_pax_aslr_mmap_len = pax_aslr_mmap_len;
 +    pr->pr_pax_aslr_stack_len = pax_aslr_stack_len;
 +    pr->pr_pax_aslr_exec_len = pax_aslr_exec_len;
 +
 +#ifdef COMPAT_FREEBSD32
 +    pr->pr_pax_aslr_compat_status = pax_aslr_compat_status;
 +    pr->pr_pax_aslr_compat_mmap_len = pax_aslr_compat_mmap_len;
 +    pr->pr_pax_aslr_compat_stack_len = pax_aslr_compat_stack_len;
 +    pr->pr_pax_aslr_compat_exec_len = pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
 +
 +    pr->pr_pax_set = 1;
 +}
 +
 +void
 +pax_aslr_init(struct thread *td, struct image_params *imgp)
 +{
 +    struct vmspace *vm;
 +    u_int sv_flags;
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    if (imgp == NULL) {
 +        panic("[PaX ASLR] pax_aslr_init - imgp == NULL");
 +    }
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    vm = imgp->proc->p_vmspace;
 +    sv_flags = imgp->proc->p_sysent->sv_flags;
 +
 +#ifndef COMPAT_FREEBSD32
 +    vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_MMAP_LSB, (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +    vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_STACK_LSB, (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +    vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
 +    vm->vm_aslr_delta_exec = round_page(PAX_ASLR_DELTA(arc4random(), PAX_ASLR_DELTA_EXEC_LSB, (pr != NULL) ? pr->pr_pax_aslr_exec_len : pax_aslr_exec_len));
 +#else /* COMPAT_FREEBSD32 */
 +    if ((sv_flags & SV_LP64) != 0) {
 +        vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_MMAP_LSB, (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +        vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_STACK_LSB, (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +        vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
 +    } else {
 +        vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr != NULL) ? pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compat_mmap_len);
 +        vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr != NULL) ? pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len);
 +        vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
 +    }
 +#endif /* !COMPAT_FREEBSD32 */
 +}
 +
 +void
 +pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t orig_addr, int flags)
 +{
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    if (!(flags & MAP_FIXED) && ((orig_addr == 0) || !(flags & MAP_ANON))) {
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] applying to %p orig_addr=%p f=%x\n",
 +                (void *)*addr, (void *)orig_addr, flags);
 +        if (!(td->td_proc->p_vmspace->vm_map.flags & MAP_ENTRY_GROWS_DOWN))
 +            *addr += td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        else
 +            *addr -= td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] result %p\n", (void *)*addr);
 +    }
 +    else if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] not applying to %p orig_addr=%p f=%x\n",
 +        (void *)*addr, (void *)orig_addr, flags);
 +}
 +
 +void
 +pax_aslr_stack(struct thread *td, char **addr, char *orig_addr)
 +{
 +    struct prison *pr=NULL;
 +
 +    pr = pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    *addr -= td->td_proc->p_vmspace->vm_aslr_delta_stack;
 +    if ((pr) && pr->pr_pax_aslr_debug)
 +        uprintf("[PaX ASLR] orig_addr=%p, addr=%p\n",
 +            (void *)orig_addr, (void *)*addr);
 +}
 diff --git a/sys/sys/jail.h b/sys/sys/jail.h
 index 59d791c..f2bb97c 100644
 --- a/sys/sys/jail.h
 +++ b/sys/sys/jail.h
 @@ -184,6 +184,20 @@ struct prison {
  	char		 pr_hostname[MAXHOSTNAMELEN];	/* (p) jail hostname */
  	char		 pr_domainname[MAXHOSTNAMELEN];	/* (p) jail domainname */
  	char		 pr_hostuuid[HOSTUUIDLEN];	/* (p) jail hostuuid */
 +#ifdef PAX_ASLR
 +    int pr_pax_set;
 +    int pr_pax_aslr_status;
 +    int pr_pax_aslr_debug;
 +    int pr_pax_aslr_mmap_len;
 +    int pr_pax_aslr_stack_len;
 +    int pr_pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +#if defined(PAX_ASLR) && defined(COMPAT_FREEBSD32)
 +    int pr_pax_aslr_compat_status;
 +    int pr_pax_aslr_compat_mmap_len;
 +    int pr_pax_aslr_compat_stack_len;
 +    int pr_pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
  };
  
  struct prison_racct {
 diff --git a/sys/sys/pax.h b/sys/sys/pax.h
 new file mode 100644
 index 0000000..9c36894
 --- /dev/null
 +++ b/sys/sys/pax.h
 @@ -0,0 +1,166 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote products
 + *    derived from this software without specific prior written permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of SoldierX.
 + */
 +
 +#ifndef	__SYS_PAX_H
 +#define	__SYS_PAX_H
 +
 +struct image_params;
 +struct thread;
 +struct vmspace;
 +struct vm_offset_t;
 +
 +/*
 + * used in sysctl handler
 + */
 +#define	PAX_ASLR_DISABLED		0
 +#define PAX_ASLR_ENABLED		1
 +#define PAX_ASLR_GLOBAL_ENABLED		2
 +#define	PAX_ASLR_FORCE_GLOBAL_ENABLED	3
 +
 +#ifndef PAX_ASLR_DELTA
 +#define	PAX_ASLR_DELTA(delta, lsb, len)	\
 +	(((delta) & ((1UL << (len)) - 1)) << (lsb))
 +#endif /* PAX_ASLR_DELTA */
 +
 +#ifdef PAX_ASLR
 +/*
 + * generic ASLR values
 + *
 + *  	MMAP	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  8 bit | 16 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 16 bit | 32 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	STACK	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	EXEC	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + */
 +#ifndef PAX_ASLR_DELTA_MMAP_LSB
 +#define PAX_ASLR_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_DELTA_MMAP_MIN_LEN	((sizeof(void *) * NBBY) / 4)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_DELTA_MMAP_MAX_LEN	((sizeof(void *) * NBBY) / 2)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_LSB
 +#define PAX_ASLR_DELTA_STACK_LSB	3
 +#endif /* PAX_ASLR_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_DELTA_STACK_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_DELTA_STACK_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_LSB
 +#define PAX_ASLR_DELTA_EXEC_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_EXEC_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_DELTA_EXEC_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_DELTA_EXEC_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +/*
 + * ASLR values for COMPAT_FREEBSD32 and COMPAT_LINUX
 + */
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN	((sizeof(int) * NBBY) / 4)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN	((sizeof(int) * NBBY) / 2)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB
 +#define PAX_ASLR_COMPAT_DELTA_STACK_LSB		3
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN	((sizeof(int) * NBBY) / 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN	((sizeof(int) * NBBY) / 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN	((sizeof(int) * NBBY) / 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN	((sizeof(int) * NBBY) / 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +extern int pax_aslr_status;
 +extern int pax_aslr_debug;
 +extern int pax_aslr_compat_status;
 +
 +extern int pax_aslr_mmap_len;
 +extern int pax_aslr_stack_len;
 +extern int pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +
 +void pax_init(void);
 +void pax_aslr_init_prison(struct prison *pr);
 +bool pax_aslr_active(struct thread *td, struct proc *proc);
 +void pax_aslr_init(struct thread *td, struct image_params *imgp);
 +void pax_aslr_mmap(struct thread *td, vm_offset_t *addr,
 +			vm_offset_t orig_addr, int flags);
 +void pax_aslr_stack(struct thread *td, char **addr, char *orig_addr);
 +struct prison *pax_aslr_get_prison(struct thread *td, struct proc *proc);
 +
 +#endif /* __SYS_PAX_H */
 diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
 index e15e0ca..3c066ef 100644
 --- a/sys/vm/vm_map.c
 +++ b/sys/vm/vm_map.c
 @@ -65,6 +65,8 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD$");
  
 +#include "opt_pax.h"
 +
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/kernel.h>
 @@ -289,6 +291,10 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, pmap_pinit_t pinit)
  	vm->vm_taddr = 0;
  	vm->vm_daddr = 0;
  	vm->vm_maxsaddr = 0;
 +#ifdef PAX_ASLR
 +	vm->vm_aslr_delta_mmap = 0;
 +	vm->vm_aslr_delta_stack = 0;
 +#endif /* PAX_ASLR */
  	return (vm);
  }
  
 diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
 index 850bf25..e4fbebd 100644
 --- a/sys/vm/vm_map.h
 +++ b/sys/vm/vm_map.h
 @@ -241,6 +241,8 @@ struct vmspace {
  	caddr_t vm_taddr;	/* (c) user virtual address of text */
  	caddr_t vm_daddr;	/* (c) user virtual address of data */
  	caddr_t vm_maxsaddr;	/* user VA at max stack growth */
 +	vm_size_t vm_aslr_delta_mmap;	/* mmap() random delta for ASLR */
 +	vm_size_t vm_aslr_delta_stack;	/* stack random delta for ASLR */
  	volatile int vm_refcnt;	/* number of references */
  	/*
  	 * Keep the PMAP last, so that CPU-specific variations of that
 diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
 index 17f8cad..3693dfa 100644
 --- a/sys/vm/vm_mmap.c
 +++ b/sys/vm/vm_mmap.c
 @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
  
  #include "opt_compat.h"
  #include "opt_hwpmc_hooks.h"
 +#include "opt_pax.h"
  
  #include <sys/param.h>
  #include <sys/systm.h>
 @@ -91,6 +92,10 @@ __FBSDID("$FreeBSD$");
  #include <sys/pmckern.h>
  #endif
  
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  int old_mlock = 0;
  SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, &old_mlock, 0,
      "Do not apply RLIMIT_MEMLOCK on mlockall");
 @@ -203,6 +208,9 @@ sys_mmap(td, uap)
  	struct file *fp;
  	struct vnode *vp;
  	vm_offset_t addr;
 +#ifdef PAX_ASLR
 +	vm_offset_t orig_addr;
 +#endif /* PAX_ASLR */
  	vm_size_t size, pageoff;
  	vm_prot_t cap_maxprot, prot, maxprot;
  	void *handle;
 @@ -213,6 +221,9 @@ sys_mmap(td, uap)
  	cap_rights_t rights;
  
  	addr = (vm_offset_t) uap->addr;
 +#ifdef PAX_ASLR
 +	orig_addr = addr;
 +#endif /* PAX_ASLR */
  	size = uap->len;
  	prot = uap->prot & VM_PROT_ALL;
  	flags = uap->flags;
 @@ -309,9 +320,11 @@ 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))))
 -			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));
 +                addr = round_page(addr + (arc4random()&(256*1024*1024-1)));
 +        }
  		PROC_UNLOCK(td->td_proc);
  	}
  	if (flags & MAP_ANON) {
 @@ -414,6 +427,9 @@ sys_mmap(td, uap)
  map:
  	td->td_fpop = fp;
  	maxprot &= cap_maxprot;
 +#ifdef PAX_ASLR
 +	pax_aslr_mmap(td, &addr, orig_addr, flags);
 +#endif /* PAX_ASLR */
  	error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
  	    flags, handle_type, handle, pos);
  	td->td_fpop = NULL;
 
 --Apple-Mail=_70D08D01-527F-4575-806A-36757E957E5A--

From: Shawn Webb <lattera@gmail.com>
To: bug-followup@FreeBSD.org,
 steven@roothosts.com
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Sun, 9 Feb 2014 19:37:03 -0500

 --Apple-Mail=_C84F0573-719D-4AC2-8D2A-DD418EFCAAE8
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii
 
 Attached is a patch that applies on top of the existing patch to fix a =
 few minor bugs.
 
 Thanks,
 
 Shawn
 
 
 --Apple-Mail=_C84F0573-719D-4AC2-8D2A-DD418EFCAAE8
 Content-Disposition: attachment;
 	filename=aslr-2014-02-09.patch.txt
 Content-Type: text/plain;
 	x-unix-mode=0644;
 	name="aslr-2014-02-09.patch.txt"
 Content-Transfer-Encoding: quoted-printable
 
 diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
 index 3f9487c..3a36f20 100644
 --- a/sys/kern/imgact_elf.c
 +++ b/sys/kern/imgact_elf.c
 @@ -603,7 +603,9 @@ __elfN(load_file)(struct proc *p, const char *file, =
 u_long *addr,
  	u_long rbase;
  	u_long base_addr =3D 0;
  	int error, i, numsegs;
 -    struct prison *pr; /* For ASLR */
 +#ifdef PAX_ASLR
 +    struct prison *pr;
 +#endif
 =20
  #ifdef CAPABILITY_MODE
  	/*
 @@ -659,22 +661,21 @@ __elfN(load_file)(struct proc *p, const char =
 *file, u_long *addr,
  	hdr =3D (const Elf_Ehdr *)imgp->image_header;
  	if ((error =3D __elfN(check_header)(hdr)) !=3D 0)
  		goto fail;
 -	if (hdr->e_type =3D=3D ET_DYN)
 +	if (hdr->e_type =3D=3D ET_DYN) {
  		rbase =3D *addr;
 -	else if (hdr->e_type =3D=3D ET_EXEC)
 +#ifdef PAX_ASLR
 +        pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +        if (pax_aslr_active(NULL, imgp->proc)) {
 +            rbase +=3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +        }
 +#endif
 +    } else if (hdr->e_type =3D=3D ET_EXEC) {
  		rbase =3D 0;
 -	else {
 +    } else {
  		error =3D ENOEXEC;
  		goto fail;
  	}
 =20
 -#ifdef PAX_ASLR
 -    pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 -    if (pax_aslr_active(NULL, imgp->proc)) {
 -        rbase +=3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 -    }
 -#endif
 -
  	/* Only support headers that fit within first page for now      =
 */
  	if ((hdr->e_phoff > PAGE_SIZE) ||
  	    (u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - =
 hdr->e_phoff) {
 diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
 index 9182606..7654e5b 100644
 --- a/sys/kern/kern_pax.c
 +++ b/sys/kern/kern_pax.c
 @@ -528,7 +528,6 @@ pax_aslr_init(struct thread *td, struct image_params =
 *imgp)
      vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
          PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
      vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 -    vm->vm_aslr_delta_exec =3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : =
 pax_aslr_exec_len));
  #else /* COMPAT_FREEBSD32 */
      if ((sv_flags & SV_LP64) !=3D 0) {
          vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 
 --Apple-Mail=_C84F0573-719D-4AC2-8D2A-DD418EFCAAE8--

From: Shawn Webb <lattera@gmail.com>
To: bug-followup@FreeBSD.org,
 steven@roothosts.com
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Sun, 16 Mar 2014 15:19:11 -0400

 --Apple-Mail=_C583F33A-7989-4B50-AB79-0566D922BAD4
 Content-Transfer-Encoding: 7bit
 Content-Type: text/plain;
 	charset=us-ascii
 
 Attached is a combined patch.
 
 
 --Apple-Mail=_C583F33A-7989-4B50-AB79-0566D922BAD4
 Content-Disposition: attachment;
 	filename=aslr-2014-03-16.patch.txt
 Content-Type: text/plain;
 	x-unix-mode=0644;
 	name="aslr-2014-03-16.patch.txt"
 Content-Transfer-Encoding: quoted-printable
 
 diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h
 index bda9722..5e83a8f 100644
 --- a/sys/amd64/include/vmparam.h
 +++ b/sys/amd64/include/vmparam.h
 @@ -170,7 +170,7 @@
  #define	VM_MAXUSER_ADDRESS	UVADDR(NUPML4E, 0, 0, 0)
 =20
  #define	SHAREDPAGE		(VM_MAXUSER_ADDRESS - PAGE_SIZE)
 -#define	USRSTACK		SHAREDPAGE
 +#define	USRSTACK		(SHAREDPAGE - 4*PAGE_SIZE)
 =20
  #define	VM_MAX_ADDRESS		UPT_MAX_ADDRESS
  #define	VM_MIN_ADDRESS		(0)
 diff --git a/sys/compat/freebsd32/freebsd32_misc.c =
 b/sys/compat/freebsd32/freebsd32_misc.c
 index 749c91d..2b80bad 100644
 --- a/sys/compat/freebsd32/freebsd32_misc.c
 +++ b/sys/compat/freebsd32/freebsd32_misc.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_compat.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #define __ELF_WORD_SIZE 32
 =20
 @@ -113,6 +114,10 @@ __FBSDID("$FreeBSD$");
 =20
  FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  #ifndef __mips__
  CTASSERT(sizeof(struct timeval32) =3D=3D 8);
  CTASSERT(sizeof(struct timespec32) =3D=3D 8);
 @@ -2823,6 +2828,9 @@ freebsd32_copyout_strings(struct image_params =
 *imgp)
  	int argc, envc, i;
  	u_int32_t *vectp;
  	char *stringp, *destp;
 +#ifdef PAX_ASLR
 +	char *orig_destp;
 +#endif /* PAX_ASLR */
  	u_int32_t *stack_base;
  	struct freebsd32_ps_strings *arginfo;
  	char canary[sizeof(long) * 8];
 @@ -2850,6 +2858,11 @@ freebsd32_copyout_strings(struct image_params =
 *imgp)
  	    roundup(sizeof(pagesizes32), sizeof(char *)) -
  	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char =
 *));
 =20
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 +
  	/*
  	 * install sigcode
  	 */
 diff --git a/sys/conf/files b/sys/conf/files
 index 596cc69..c2e59ca 100644
 --- a/sys/conf/files
 +++ b/sys/conf/files
 @@ -2835,6 +2835,7 @@ kern/kern_mtxpool.c		standard
  kern/kern_mutex.c		standard
  kern/kern_ntptime.c		standard
  kern/kern_osd.c			standard
 +kern/kern_pax.c			optional pax_aslr
  kern/kern_physio.c		standard
  kern/kern_pmc.c			standard
  kern/kern_poll.c		optional device_polling
 diff --git a/sys/conf/options b/sys/conf/options
 index 75fe424..ecabb5f 100644
 --- a/sys/conf/options
 +++ b/sys/conf/options
 @@ -910,6 +910,9 @@ RACCT		opt_global.h
  # Resource Limits
  RCTL		opt_global.h
 =20
 +# PaX - hardening options
 +PAX_ASLR		opt_pax.h
 +PAX_ASLR_MAX_SEC	opt_pax.h
  # Random number generator(s)
  RANDOM_YARROW	opt_random.h
  RANDOM_FORTUNA	opt_random.h
 diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
 index f6da68e..3a36f20 100644
 --- a/sys/kern/imgact_elf.c
 +++ b/sys/kern/imgact_elf.c
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_compat.h"
  #include "opt_core.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/capability.h>
 @@ -47,7 +48,9 @@ __FBSDID("$FreeBSD$");
  #include <sys/mount.h>
  #include <sys/mman.h>
  #include <sys/namei.h>
 +#include <sys/pax.h>
  #include <sys/pioctl.h>
 +#include <sys/jail.h>
  #include <sys/proc.h>
  #include <sys/procfs.h>
  #include <sys/racct.h>
 @@ -600,6 +603,9 @@ __elfN(load_file)(struct proc *p, const char *file, =
 u_long *addr,
  	u_long rbase;
  	u_long base_addr =3D 0;
  	int error, i, numsegs;
 +#ifdef PAX_ASLR
 +    struct prison *pr;
 +#endif
 =20
  #ifdef CAPABILITY_MODE
  	/*
 @@ -655,11 +661,17 @@ __elfN(load_file)(struct proc *p, const char =
 *file, u_long *addr,
  	hdr =3D (const Elf_Ehdr *)imgp->image_header;
  	if ((error =3D __elfN(check_header)(hdr)) !=3D 0)
  		goto fail;
 -	if (hdr->e_type =3D=3D ET_DYN)
 +	if (hdr->e_type =3D=3D ET_DYN) {
  		rbase =3D *addr;
 -	else if (hdr->e_type =3D=3D ET_EXEC)
 +#ifdef PAX_ASLR
 +        pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +        if (pax_aslr_active(NULL, imgp->proc)) {
 +            rbase +=3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +        }
 +#endif
 +    } else if (hdr->e_type =3D=3D ET_EXEC) {
  		rbase =3D 0;
 -	else {
 +    } else {
  		error =3D ENOEXEC;
  		goto fail;
  	}
 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
 index 9f4ceac..099ff0a 100644
 --- a/sys/kern/kern_exec.c
 +++ b/sys/kern/kern_exec.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_hwpmc_hooks.h"
  #include "opt_ktrace.h"
 +#include "opt_pax.h"
  #include "opt_vm.h"
 =20
  #include <sys/param.h>
 @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$");
  dtrace_execexit_func_t	dtrace_fasttrap_exec;
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  SDT_PROVIDER_DECLARE(proc);
  SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
  SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
 @@ -1055,6 +1060,10 @@ exec_new_vmspace(imgp, sv)
  		map =3D &vmspace->vm_map;
  	}
 =20
 +#ifdef PAX_ASLR
 +	pax_aslr_init(curthread, imgp);
 +#endif /* PAX_ASLR */
 +
  	/* Map a shared page */
  	obj =3D sv->sv_shared_page_obj;
  	if (obj !=3D NULL) {
 @@ -1232,12 +1241,16 @@ exec_copyout_strings(imgp)
  	int argc, envc;
  	char **vectp;
  	char *stringp, *destp;
 +#ifdef	PAX_ASLR
 +	char *orig_destp;
 +#endif /* PAX_ASLR */
  	register_t *stack_base;
  	struct ps_strings *arginfo;
  	struct proc *p;
  	size_t execpath_len;
  	int szsigcode, szps;
  	char canary[sizeof(long) * 8];
 +    unsigned int sgap;
 =20
  	szps =3D sizeof(pagesizes[0]) * MAXPAGESIZES;
  	/*
 @@ -1255,11 +1268,16 @@ exec_copyout_strings(imgp)
  		if (p->p_sysent->sv_szsigcode !=3D NULL)
  			szsigcode =3D *(p->p_sysent->sv_szsigcode);
  	}
 -	destp =3D	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
 +    sgap=3D(unsigned int)(ALIGN(arc4random()&((64*1024)-1)));
 +	destp =3D	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE - =
 sgap -
  	    roundup(execpath_len, sizeof(char *)) -
  	    roundup(sizeof(canary), sizeof(char *)) -
  	    roundup(szps, sizeof(char *)) -
  	    roundup((ARG_MAX - imgp->args->stringspace), sizeof(char =
 *));
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 =20
  	/*
  	 * install sigcode
 diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
 index 47cd568..f8751a4 100644
 --- a/sys/kern/kern_jail.c
 +++ b/sys/kern/kern_jail.c
 @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_ddb.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/types.h>
 @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/syscallsubr.h>
  #include <sys/sysctl.h>
  #include <sys/vnode.h>
 +#include <sys/pax.h>
 =20
  #include <net/if.h>
  #include <net/if_var.h>
 @@ -114,6 +116,20 @@ struct prison prison0 =3D {
  	.pr_flags	=3D PR_HOST|_PR_IP_SADDRSEL,
  #endif
  	.pr_allow	=3D PR_ALLOW_ALL,
 +#ifdef PAX_ASLR
 +    .pr_pax_set =3D 0,
 +    .pr_pax_aslr_status =3D 0,
 +    .pr_pax_aslr_debug =3D 0,
 +    .pr_pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN,
 +#ifdef COMPAT_FREEBSD32
 +    .pr_pax_aslr_compat_status =3D 0,
 +    .pr_pax_aslr_compat_mmap_len =3D =
 PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_compat_stack_len =3D =
 PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_compat_exec_len =3D =
 PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN,
 +#endif /* COMPAT_FREEBSD32 */
 +#endif /* PAX_ASLR */
  };
  MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
 =20
 diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
 new file mode 100644
 index 0000000..7654e5b
 --- /dev/null
 +++ b/sys/kern/kern_pax.c
 @@ -0,0 +1,588 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#include <sys/cdefs.h>
 +__FBSDID("$FreeBSD$");
 +
 +#include "opt_pax.h"
 +#include "opt_compat.h"
 +
 +#include <sys/param.h>
 +#include <sys/systm.h>
 +#include <sys/kernel.h>
 +#include <sys/imgact.h>
 +#include <sys/sysent.h>
 +#include <sys/proc.h>
 +#include <sys/elf_common.h>
 +#include <sys/pax.h>
 +#include <sys/sysctl.h>
 +#include <sys/vnode.h>
 +#include <sys/queue.h>
 +#include <sys/libkern.h>
 +#include <sys/jail.h>
 +
 +#include <sys/mman.h>
 +#include <sys/libkern.h>
 +#include <sys/exec.h>
 +
 +#include <vm/pmap.h>
 +#include <vm/vm_map.h>
 +
 +static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS);
 +
 +/*
 + * sysctls and tunables
 + */
 +int pax_aslr_status =3D PAX_ASLR_ENABLED;
 +int pax_aslr_debug =3D 0;
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MAX_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +
 +SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
 +    "PaX (exploit mitigation) features.");
 +SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0,
 +    "Address Space Layout Randomization.");
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status);
 +
 +SYSCTL_INT(_security_pax_aslr, OID_AUTO, debug, =
 CTLFLAG_RWTUN|CTLFLAG_PRISON, &pax_aslr_debug, 0, "ASLR debug mode");
 +TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16] 64 bit: [16,32]");
 +TUNABLE_INT("security.pax.aslr.mmap", &pax_aslr_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_exec_len);
 +
 +static int
 +sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_status =3D val;
 +            if (pr)
 +                pr->pr_pax_aslr_status =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_mmap_len : =
 pax_aslr_mmap_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_mmap_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_mmap_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_stack_len : =
 pax_aslr_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_stack_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_stack_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : =
 pax_aslr_exec_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_exec_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_exec_len =3D val;
 +
 +    return (0);
 +}
 +
 +/*
 + * COMPAT_FREEBSD32 and linuxulator..
 + */
 +#ifdef COMPAT_FREEBSD32
 +int pax_aslr_compat_status =3D PAX_ASLR_ENABLED;
 +
 +static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS);
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0,
 +    "Setting for COMPAT_FREEBSD32 and linuxulator.");
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.compat.status", =
 &pax_aslr_compat_status);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16]");
 +TUNABLE_INT("security.pax.aslr.compat.mmap", =
 &pax_aslr_compat_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_exec_len);
 +
 +
 +static int
 +sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_status) : =
 &pax_aslr_compat_status;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_compat_status =3D val;
 +            *ptr =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_mmap_len) : =
 &pax_aslr_compat_mmap_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_mmap_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_stack_len) : =
 &pax_aslr_compat_stack_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_compat_stack_len : =
 pax_aslr_compat_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_stack_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_exec_len) : =
 &pax_aslr_compat_exec_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_exec_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +#endif /* COMPAT_FREEBSD32 */
 +
 +
 +/*
 + * ASLR functions
 + */
 +bool
 +pax_aslr_active(struct thread *td, struct proc *proc)
 +{
 +    int status;
 +    struct prison *pr=3DNULL;
 +#ifdef  notyet
 +    uint32_t    flags;
 +#endif /* notyet */
 +
 +    if (!(td) && !(proc))
 +        return (true);
 +
 +#ifdef notyet
 +    flags =3D (td !=3D NULL) ? td->td_proc->p_pax : proc->p_pax;
 +#endif /* notyet */
 +    pr =3D pax_aslr_get_prison(td, proc);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    status =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : =
 pax_aslr_status;
 +
 +    switch (status) {
 +    case    PAX_ASLR_DISABLED:
 +        return (false);
 +    case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +        return (true);
 +    case    PAX_ASLR_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_ASLR) =3D=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    case    PAX_ASLR_GLOBAL_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_NOASLR) !=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    default:
 +        return (true);
 +    }
 +
 +    return (true);
 +}
 +
 +struct prison *
 +pax_aslr_get_prison(struct thread *td, struct proc *proc)
 +{
 +    if ((td)) {
 +        if ((td->td_proc) && (td->td_proc->p_ucred))
 +            return td->td_proc->p_ucred->cr_prison;
 +
 +        return NULL;
 +    }
 +
 +    if (!(proc))
 +        return NULL;
 +
 +    return proc->p_ucred->cr_prison;
 +}
 +
 +void
 +pax_aslr_init_prison(struct prison *pr)
 +{
 +    if (!(pr))
 +        return;
 +
 +    if (pr->pr_pax_set)
 +        return;
 +
 +    if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] pax_aslr_init_prison: Setting prison %s =
 ASLR variables\n", pr->pr_name);
 +
 +    pr->pr_pax_aslr_status =3D pax_aslr_status;
 +    pr->pr_pax_aslr_debug =3D pax_aslr_debug;
 +    pr->pr_pax_aslr_mmap_len =3D pax_aslr_mmap_len;
 +    pr->pr_pax_aslr_stack_len =3D pax_aslr_stack_len;
 +    pr->pr_pax_aslr_exec_len =3D pax_aslr_exec_len;
 +
 +#ifdef COMPAT_FREEBSD32
 +    pr->pr_pax_aslr_compat_status =3D pax_aslr_compat_status;
 +    pr->pr_pax_aslr_compat_mmap_len =3D pax_aslr_compat_mmap_len;
 +    pr->pr_pax_aslr_compat_stack_len =3D pax_aslr_compat_stack_len;
 +    pr->pr_pax_aslr_compat_exec_len =3D pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
 +
 +    pr->pr_pax_set =3D 1;
 +}
 +
 +void
 +pax_aslr_init(struct thread *td, struct image_params *imgp)
 +{
 +    struct vmspace *vm;
 +    u_int sv_flags;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    if (imgp =3D=3D NULL) {
 +        panic("[PaX ASLR] pax_aslr_init - imgp =3D=3D NULL");
 +    }
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    vm =3D imgp->proc->p_vmspace;
 +    sv_flags =3D imgp->proc->p_sysent->sv_flags;
 +
 +#ifndef COMPAT_FREEBSD32
 +    vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +    vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +    vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +#else /* COMPAT_FREEBSD32 */
 +    if ((sv_flags & SV_LP64) !=3D 0) {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    } else {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compat_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    }
 +#endif /* !COMPAT_FREEBSD32 */
 +}
 +
 +void
 +pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t =
 orig_addr, int flags)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    if (!(flags & MAP_FIXED) && ((orig_addr =3D=3D 0) || !(flags & =
 MAP_ANON))) {
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] applying to %p orig_addr=3D%p f=3D%x\n",
 +                (void *)*addr, (void *)orig_addr, flags);
 +        if (!(td->td_proc->p_vmspace->vm_map.flags & =
 MAP_ENTRY_GROWS_DOWN))
 +            *addr +=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        else
 +            *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] result %p\n", (void *)*addr);
 +    }
 +    else if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] not applying to %p orig_addr=3D%p f=3D%x\n",
 +        (void *)*addr, (void *)orig_addr, flags);
 +}
 +
 +void
 +pax_aslr_stack(struct thread *td, char **addr, char *orig_addr)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_stack;
 +    if ((pr) && pr->pr_pax_aslr_debug)
 +        uprintf("[PaX ASLR] orig_addr=3D%p, addr=3D%p\n",
 +            (void *)orig_addr, (void *)*addr);
 +}
 diff --git a/sys/sys/jail.h b/sys/sys/jail.h
 index 59d791c..f2bb97c 100644
 --- a/sys/sys/jail.h
 +++ b/sys/sys/jail.h
 @@ -184,6 +184,20 @@ struct prison {
  	char		 pr_hostname[MAXHOSTNAMELEN];	/* (p) jail =
 hostname */
  	char		 pr_domainname[MAXHOSTNAMELEN];	/* (p) jail =
 domainname */
  	char		 pr_hostuuid[HOSTUUIDLEN];	/* (p) jail =
 hostuuid */
 +#ifdef PAX_ASLR
 +    int pr_pax_set;
 +    int pr_pax_aslr_status;
 +    int pr_pax_aslr_debug;
 +    int pr_pax_aslr_mmap_len;
 +    int pr_pax_aslr_stack_len;
 +    int pr_pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +#if defined(PAX_ASLR) && defined(COMPAT_FREEBSD32)
 +    int pr_pax_aslr_compat_status;
 +    int pr_pax_aslr_compat_mmap_len;
 +    int pr_pax_aslr_compat_stack_len;
 +    int pr_pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
  };
 =20
  struct prison_racct {
 diff --git a/sys/sys/pax.h b/sys/sys/pax.h
 new file mode 100644
 index 0000000..9c36894
 --- /dev/null
 +++ b/sys/sys/pax.h
 @@ -0,0 +1,166 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#ifndef	__SYS_PAX_H
 +#define	__SYS_PAX_H
 +
 +struct image_params;
 +struct thread;
 +struct vmspace;
 +struct vm_offset_t;
 +
 +/*
 + * used in sysctl handler
 + */
 +#define	PAX_ASLR_DISABLED		0
 +#define PAX_ASLR_ENABLED		1
 +#define PAX_ASLR_GLOBAL_ENABLED		2
 +#define	PAX_ASLR_FORCE_GLOBAL_ENABLED	3
 +
 +#ifndef PAX_ASLR_DELTA
 +#define	PAX_ASLR_DELTA(delta, lsb, len)	\
 +	(((delta) & ((1UL << (len)) - 1)) << (lsb))
 +#endif /* PAX_ASLR_DELTA */
 +
 +#ifdef PAX_ASLR
 +/*
 + * generic ASLR values
 + *
 + *  	MMAP	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  8 bit | 16 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 16 bit | 32 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	STACK	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	EXEC	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + */
 +#ifndef PAX_ASLR_DELTA_MMAP_LSB
 +#define PAX_ASLR_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_DELTA_MMAP_MIN_LEN	((sizeof(void *) * NBBY) / 4)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_DELTA_MMAP_MAX_LEN	((sizeof(void *) * NBBY) / 2)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_LSB
 +#define PAX_ASLR_DELTA_STACK_LSB	3
 +#endif /* PAX_ASLR_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_DELTA_STACK_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_DELTA_STACK_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_LSB
 +#define PAX_ASLR_DELTA_EXEC_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_EXEC_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_DELTA_EXEC_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_DELTA_EXEC_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +/*
 + * ASLR values for COMPAT_FREEBSD32 and COMPAT_LINUX
 + */
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN	((sizeof(int) * NBBY) / =
 4)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN	((sizeof(int) * NBBY) / =
 2)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB
 +#define PAX_ASLR_COMPAT_DELTA_STACK_LSB		3
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +extern int pax_aslr_status;
 +extern int pax_aslr_debug;
 +extern int pax_aslr_compat_status;
 +
 +extern int pax_aslr_mmap_len;
 +extern int pax_aslr_stack_len;
 +extern int pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +
 +void pax_init(void);
 +void pax_aslr_init_prison(struct prison *pr);
 +bool pax_aslr_active(struct thread *td, struct proc *proc);
 +void pax_aslr_init(struct thread *td, struct image_params *imgp);
 +void pax_aslr_mmap(struct thread *td, vm_offset_t *addr,
 +			vm_offset_t orig_addr, int flags);
 +void pax_aslr_stack(struct thread *td, char **addr, char *orig_addr);
 +struct prison *pax_aslr_get_prison(struct thread *td, struct proc =
 *proc);
 +
 +#endif /* __SYS_PAX_H */
 diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
 index e15e0ca..3c066ef 100644
 --- a/sys/vm/vm_map.c
 +++ b/sys/vm/vm_map.c
 @@ -65,6 +65,8 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD$");
 =20
 +#include "opt_pax.h"
 +
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/kernel.h>
 @@ -289,6 +291,10 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, =
 pmap_pinit_t pinit)
  	vm->vm_taddr =3D 0;
  	vm->vm_daddr =3D 0;
  	vm->vm_maxsaddr =3D 0;
 +#ifdef PAX_ASLR
 +	vm->vm_aslr_delta_mmap =3D 0;
 +	vm->vm_aslr_delta_stack =3D 0;
 +#endif /* PAX_ASLR */
  	return (vm);
  }
 =20
 diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
 index 850bf25..e4fbebd 100644
 --- a/sys/vm/vm_map.h
 +++ b/sys/vm/vm_map.h
 @@ -241,6 +241,8 @@ struct vmspace {
  	caddr_t vm_taddr;	/* (c) user virtual address of text */
  	caddr_t vm_daddr;	/* (c) user virtual address of data */
  	caddr_t vm_maxsaddr;	/* user VA at max stack growth */
 +	vm_size_t vm_aslr_delta_mmap;	/* mmap() random delta for ASLR =
 */
 +	vm_size_t vm_aslr_delta_stack;	/* stack random delta for ASLR =
 */
  	volatile int vm_refcnt;	/* number of references */
  	/*
  	 * Keep the PMAP last, so that CPU-specific variations of that
 diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
 index 17f8cad..3693dfa 100644
 --- a/sys/vm/vm_mmap.c
 +++ b/sys/vm/vm_mmap.c
 @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 =20
  #include "opt_compat.h"
  #include "opt_hwpmc_hooks.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/systm.h>
 @@ -91,6 +92,10 @@ __FBSDID("$FreeBSD$");
  #include <sys/pmckern.h>
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  int old_mlock =3D 0;
  SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, =
 &old_mlock, 0,
      "Do not apply RLIMIT_MEMLOCK on mlockall");
 @@ -203,6 +208,9 @@ sys_mmap(td, uap)
  	struct file *fp;
  	struct vnode *vp;
  	vm_offset_t addr;
 +#ifdef PAX_ASLR
 +	vm_offset_t orig_addr;
 +#endif /* PAX_ASLR */
  	vm_size_t size, pageoff;
  	vm_prot_t cap_maxprot, prot, maxprot;
  	void *handle;
 @@ -213,6 +221,9 @@ sys_mmap(td, uap)
  	cap_rights_t rights;
 =20
  	addr =3D (vm_offset_t) uap->addr;
 +#ifdef PAX_ASLR
 +	orig_addr =3D addr;
 +#endif /* PAX_ASLR */
  	size =3D uap->len;
  	prot =3D uap->prot & VM_PROT_ALL;
  	flags =3D uap->flags;
 @@ -309,9 +320,11 @@ sys_mmap(td, uap)
  		if (addr =3D=3D 0 ||
  		    (addr >=3D round_page((vm_offset_t)vms->vm_taddr) &&
  		    addr < round_page((vm_offset_t)vms->vm_daddr +
 -		    lim_max(td->td_proc, RLIMIT_DATA))))
 -			addr =3D round_page((vm_offset_t)vms->vm_daddr +
 -			    lim_max(td->td_proc, RLIMIT_DATA));
 +		    lim_max(td->td_proc, RLIMIT_DATA)))) {
 +                addr =3D round_page((vm_offset_t)vms->vm_daddr +
 +                    lim_max(td->td_proc, RLIMIT_DATA));
 +                addr =3D round_page(addr + =
 (arc4random()&(256*1024*1024-1)));
 +        }
  		PROC_UNLOCK(td->td_proc);
  	}
  	if (flags & MAP_ANON) {
 @@ -414,6 +427,9 @@ sys_mmap(td, uap)
  map:
  	td->td_fpop =3D fp;
  	maxprot &=3D cap_maxprot;
 +#ifdef PAX_ASLR
 +	pax_aslr_mmap(td, &addr, orig_addr, flags);
 +#endif /* PAX_ASLR */
  	error =3D vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
  	    flags, handle_type, handle, pos);
  	td->td_fpop =3D NULL;
 
 --Apple-Mail=_C583F33A-7989-4B50-AB79-0566D922BAD4--

From: Shawn Webb <lattera@gmail.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Fri, 21 Mar 2014 07:52:58 -0400

 --Apple-Mail=_6421661B-1BA8-4BA0-96DB-F61C15728C24
 Content-Transfer-Encoding: quoted-printable
 Content-Type: text/plain;
 	charset=us-ascii
 
 Attached is a new patch with integrates ASLR into loading =
 Position-Independent Executables (PIEs).
 
 
 --Apple-Mail=_6421661B-1BA8-4BA0-96DB-F61C15728C24
 Content-Disposition: attachment;
 	filename=aslr-2014-03-21_01.patch.txt
 Content-Type: text/plain;
 	x-unix-mode=0644;
 	name="aslr-2014-03-21_01.patch.txt"
 Content-Transfer-Encoding: quoted-printable
 
 diff --git a/sys/compat/freebsd32/freebsd32_misc.c =
 b/sys/compat/freebsd32/freebsd32_misc.c
 index b093a76..1bf0d12 100644
 --- a/sys/compat/freebsd32/freebsd32_misc.c
 +++ b/sys/compat/freebsd32/freebsd32_misc.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_compat.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #define __ELF_WORD_SIZE 32
 =20
 @@ -113,6 +114,10 @@ __FBSDID("$FreeBSD$");
 =20
  FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  #ifndef __mips__
  CTASSERT(sizeof(struct timeval32) =3D=3D 8);
  CTASSERT(sizeof(struct timespec32) =3D=3D 8);
 @@ -2822,6 +2827,9 @@ freebsd32_copyout_strings(struct image_params =
 *imgp)
  {
  	int argc, envc, i;
  	u_int32_t *vectp;
 +#ifdef PAX_ASLR
 +	uintptr_t orig_destp;
 +#endif /* PAX_ASLR */
  	char *stringp;
  	uintptr_t destp;
  	u_int32_t *stack_base;
 @@ -2847,6 +2855,11 @@ freebsd32_copyout_strings(struct image_params =
 *imgp)
  		szsigcode =3D 0;
  	destp =3D	(uintptr_t)arginfo;
 =20
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 +
  	/*
  	 * install sigcode
  	 */
 diff --git a/sys/conf/files b/sys/conf/files
 index 596cc69..c2e59ca 100644
 --- a/sys/conf/files
 +++ b/sys/conf/files
 @@ -2835,6 +2835,7 @@ kern/kern_mtxpool.c		standard
  kern/kern_mutex.c		standard
  kern/kern_ntptime.c		standard
  kern/kern_osd.c			standard
 +kern/kern_pax.c			optional pax_aslr
  kern/kern_physio.c		standard
  kern/kern_pmc.c			standard
  kern/kern_poll.c		optional device_polling
 diff --git a/sys/conf/options b/sys/conf/options
 index 75fe424..ecabb5f 100644
 --- a/sys/conf/options
 +++ b/sys/conf/options
 @@ -910,6 +910,9 @@ RACCT		opt_global.h
  # Resource Limits
  RCTL		opt_global.h
 =20
 +# PaX - hardening options
 +PAX_ASLR		opt_pax.h
 +PAX_ASLR_MAX_SEC	opt_pax.h
  # Random number generator(s)
  RANDOM_YARROW	opt_random.h
  RANDOM_FORTUNA	opt_random.h
 diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
 index d5ec365..308e3f9 100644
 --- a/sys/kern/imgact_elf.c
 +++ b/sys/kern/imgact_elf.c
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_compat.h"
  #include "opt_core.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/capsicum.h>
 @@ -47,7 +48,9 @@ __FBSDID("$FreeBSD$");
  #include <sys/mount.h>
  #include <sys/mman.h>
  #include <sys/namei.h>
 +#include <sys/pax.h>
  #include <sys/pioctl.h>
 +#include <sys/jail.h>
  #include <sys/proc.h>
  #include <sys/procfs.h>
  #include <sys/racct.h>
 @@ -600,6 +603,9 @@ __elfN(load_file)(struct proc *p, const char *file, =
 u_long *addr,
  	u_long rbase;
  	u_long base_addr =3D 0;
  	int error, i, numsegs;
 +#ifdef PAX_ASLR
 +    struct prison *pr;
 +#endif
 =20
  #ifdef CAPABILITY_MODE
  	/*
 @@ -655,11 +661,17 @@ __elfN(load_file)(struct proc *p, const char =
 *file, u_long *addr,
  	hdr =3D (const Elf_Ehdr *)imgp->image_header;
  	if ((error =3D __elfN(check_header)(hdr)) !=3D 0)
  		goto fail;
 -	if (hdr->e_type =3D=3D ET_DYN)
 +	if (hdr->e_type =3D=3D ET_DYN) {
  		rbase =3D *addr;
 -	else if (hdr->e_type =3D=3D ET_EXEC)
 +#ifdef PAX_ASLR
 +        if (pax_aslr_active(NULL, imgp->proc)) {
 +            pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +            rbase +=3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +        }
 +#endif
 +    } else if (hdr->e_type =3D=3D ET_EXEC) {
  		rbase =3D 0;
 -	else {
 +    } else {
  		error =3D ENOEXEC;
  		goto fail;
  	}
 @@ -729,6 +741,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params =
 *imgp)
  	Elf_Brandinfo *brand_info;
  	char *path;
  	struct sysentvec *sv;
 +#ifdef PAX_ASLR
 +    struct prison *pr;
 +#endif
 =20
  	/*
  	 * Do we have a valid ELF header ?
 @@ -793,10 +808,20 @@ __CONCAT(exec_, __elfN(imgact))(struct =
 image_params *imgp)
  		 * Honour the base load address from the dso if it is
  		 * non-zero for some reason.
  		 */
 -		if (baddr =3D=3D 0)
 +		if (baddr =3D=3D 0) {
 +#ifdef PAX_ASLR
 +            if (pax_aslr_active(NULL, imgp->proc)) {
 +                pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +                et_dyn_addr =3D trunc_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +            } else {
 +                et_dyn_addr =3D ET_DYN_LOAD_ADDR;
 +            }
 +#else
  			et_dyn_addr =3D ET_DYN_LOAD_ADDR;
 -		else
 +#endif
 +        } else {
  			et_dyn_addr =3D 0;
 +        }
  	} else
  		et_dyn_addr =3D 0;
  	sv =3D brand_info->sysvec;
 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
 index 9f223ca..fe6357f 100644
 --- a/sys/kern/kern_exec.c
 +++ b/sys/kern/kern_exec.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_hwpmc_hooks.h"
  #include "opt_ktrace.h"
 +#include "opt_pax.h"
  #include "opt_vm.h"
 =20
  #include <sys/param.h>
 @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$");
  dtrace_execexit_func_t	dtrace_fasttrap_exec;
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  SDT_PROVIDER_DECLARE(proc);
  SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
  SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
 @@ -1055,6 +1060,10 @@ exec_new_vmspace(imgp, sv)
  		map =3D &vmspace->vm_map;
  	}
 =20
 +#ifdef PAX_ASLR
 +	pax_aslr_init(curthread, imgp);
 +#endif /* PAX_ASLR */
 +
  	/* Map a shared page */
  	obj =3D sv->sv_shared_page_obj;
  	if (obj !=3D NULL) {
 @@ -1231,6 +1240,9 @@ exec_copyout_strings(imgp)
  {
  	int argc, envc;
  	char **vectp;
 +#ifdef	PAX_ASLR
 +	uintptr_t orig_destp;
 +#endif /* PAX_ASLR */
  	char *stringp;
  	uintptr_t destp;
  	register_t *stack_base;
 @@ -1239,6 +1251,7 @@ exec_copyout_strings(imgp)
  	size_t execpath_len;
  	int szsigcode, szps;
  	char canary[sizeof(long) * 8];
 +    unsigned int sgap;
 =20
  	szps =3D sizeof(pagesizes[0]) * MAXPAGESIZES;
  	/*
 @@ -1256,7 +1269,12 @@ exec_copyout_strings(imgp)
  		if (p->p_sysent->sv_szsigcode !=3D NULL)
  			szsigcode =3D *(p->p_sysent->sv_szsigcode);
  	}
 +    sgap=3D(unsigned int)(ALIGN(arc4random()&((64*1024)-1)));
  	destp =3D	(uintptr_t)arginfo;
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 =20
  	/*
  	 * install sigcode
 diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
 index 47cd568..f8751a4 100644
 --- a/sys/kern/kern_jail.c
 +++ b/sys/kern/kern_jail.c
 @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_ddb.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/types.h>
 @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/syscallsubr.h>
  #include <sys/sysctl.h>
  #include <sys/vnode.h>
 +#include <sys/pax.h>
 =20
  #include <net/if.h>
  #include <net/if_var.h>
 @@ -114,6 +116,20 @@ struct prison prison0 =3D {
  	.pr_flags	=3D PR_HOST|_PR_IP_SADDRSEL,
  #endif
  	.pr_allow	=3D PR_ALLOW_ALL,
 +#ifdef PAX_ASLR
 +    .pr_pax_set =3D 0,
 +    .pr_pax_aslr_status =3D 0,
 +    .pr_pax_aslr_debug =3D 0,
 +    .pr_pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN,
 +#ifdef COMPAT_FREEBSD32
 +    .pr_pax_aslr_compat_status =3D 0,
 +    .pr_pax_aslr_compat_mmap_len =3D =
 PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_compat_stack_len =3D =
 PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_compat_exec_len =3D =
 PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN,
 +#endif /* COMPAT_FREEBSD32 */
 +#endif /* PAX_ASLR */
  };
  MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
 =20
 diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
 new file mode 100644
 index 0000000..2185baf
 --- /dev/null
 +++ b/sys/kern/kern_pax.c
 @@ -0,0 +1,588 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#include <sys/cdefs.h>
 +__FBSDID("$FreeBSD$");
 +
 +#include "opt_pax.h"
 +#include "opt_compat.h"
 +
 +#include <sys/param.h>
 +#include <sys/systm.h>
 +#include <sys/kernel.h>
 +#include <sys/imgact.h>
 +#include <sys/sysent.h>
 +#include <sys/proc.h>
 +#include <sys/elf_common.h>
 +#include <sys/pax.h>
 +#include <sys/sysctl.h>
 +#include <sys/vnode.h>
 +#include <sys/queue.h>
 +#include <sys/libkern.h>
 +#include <sys/jail.h>
 +
 +#include <sys/mman.h>
 +#include <sys/libkern.h>
 +#include <sys/exec.h>
 +
 +#include <vm/pmap.h>
 +#include <vm/vm_map.h>
 +
 +static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS);
 +
 +/*
 + * sysctls and tunables
 + */
 +int pax_aslr_status =3D PAX_ASLR_ENABLED;
 +int pax_aslr_debug =3D 0;
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MAX_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +
 +SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
 +    "PaX (exploit mitigation) features.");
 +SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0,
 +    "Address Space Layout Randomization.");
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status);
 +
 +SYSCTL_INT(_security_pax_aslr, OID_AUTO, debug, =
 CTLFLAG_RWTUN|CTLFLAG_PRISON, &pax_aslr_debug, 0, "ASLR debug mode");
 +TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16] 64 bit: [16,32]");
 +TUNABLE_INT("security.pax.aslr.mmap", &pax_aslr_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_exec_len);
 +
 +static int
 +sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_status =3D val;
 +            if (pr)
 +                pr->pr_pax_aslr_status =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_mmap_len : =
 pax_aslr_mmap_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_mmap_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_mmap_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_stack_len : =
 pax_aslr_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_stack_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_stack_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : =
 pax_aslr_exec_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_exec_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_exec_len =3D val;
 +
 +    return (0);
 +}
 +
 +/*
 + * COMPAT_FREEBSD32 and linuxulator..
 + */
 +#ifdef COMPAT_FREEBSD32
 +int pax_aslr_compat_status =3D PAX_ASLR_ENABLED;
 +
 +static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS);
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0,
 +    "Setting for COMPAT_FREEBSD32 and linuxulator.");
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.compat.status", =
 &pax_aslr_compat_status);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16]");
 +TUNABLE_INT("security.pax.aslr.compat.mmap", =
 &pax_aslr_compat_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_exec_len);
 +
 +
 +static int
 +sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_status) : =
 &pax_aslr_compat_status;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_compat_status =3D val;
 +            *ptr =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_mmap_len) : =
 &pax_aslr_compat_mmap_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_mmap_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_stack_len) : =
 &pax_aslr_compat_stack_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_compat_stack_len : =
 pax_aslr_compat_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_stack_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_exec_len) : =
 &pax_aslr_compat_exec_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_exec_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +#endif /* COMPAT_FREEBSD32 */
 +
 +
 +/*
 + * ASLR functions
 + */
 +bool
 +pax_aslr_active(struct thread *td, struct proc *proc)
 +{
 +    int status;
 +    struct prison *pr=3DNULL;
 +#ifdef  notyet
 +    uint32_t    flags;
 +#endif /* notyet */
 +
 +    if (!(td) && !(proc))
 +        return (true);
 +
 +#ifdef notyet
 +    flags =3D (td !=3D NULL) ? td->td_proc->p_pax : proc->p_pax;
 +#endif /* notyet */
 +    pr =3D pax_aslr_get_prison(td, proc);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    status =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : =
 pax_aslr_status;
 +
 +    switch (status) {
 +    case    PAX_ASLR_DISABLED:
 +        return (false);
 +    case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +        return (true);
 +    case    PAX_ASLR_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_ASLR) =3D=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    case    PAX_ASLR_GLOBAL_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_NOASLR) !=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    default:
 +        return (true);
 +    }
 +
 +    return (true);
 +}
 +
 +struct prison *
 +pax_aslr_get_prison(struct thread *td, struct proc *proc)
 +{
 +    if ((td)) {
 +        if ((td->td_proc) && (td->td_proc->p_ucred))
 +            return td->td_proc->p_ucred->cr_prison;
 +
 +        return NULL;
 +    }
 +
 +    if (!(proc))
 +        return NULL;
 +
 +    return proc->p_ucred->cr_prison;
 +}
 +
 +void
 +pax_aslr_init_prison(struct prison *pr)
 +{
 +    if (!(pr))
 +        return;
 +
 +    if (pr->pr_pax_set)
 +        return;
 +
 +    if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] pax_aslr_init_prison: Setting prison %s =
 ASLR variables\n", pr->pr_name);
 +
 +    pr->pr_pax_aslr_status =3D pax_aslr_status;
 +    pr->pr_pax_aslr_debug =3D pax_aslr_debug;
 +    pr->pr_pax_aslr_mmap_len =3D pax_aslr_mmap_len;
 +    pr->pr_pax_aslr_stack_len =3D pax_aslr_stack_len;
 +    pr->pr_pax_aslr_exec_len =3D pax_aslr_exec_len;
 +
 +#ifdef COMPAT_FREEBSD32
 +    pr->pr_pax_aslr_compat_status =3D pax_aslr_compat_status;
 +    pr->pr_pax_aslr_compat_mmap_len =3D pax_aslr_compat_mmap_len;
 +    pr->pr_pax_aslr_compat_stack_len =3D pax_aslr_compat_stack_len;
 +    pr->pr_pax_aslr_compat_exec_len =3D pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
 +
 +    pr->pr_pax_set =3D 1;
 +}
 +
 +void
 +pax_aslr_init(struct thread *td, struct image_params *imgp)
 +{
 +    struct vmspace *vm;
 +    u_int sv_flags;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    if (imgp =3D=3D NULL) {
 +        panic("[PaX ASLR] pax_aslr_init - imgp =3D=3D NULL");
 +    }
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    vm =3D imgp->proc->p_vmspace;
 +    sv_flags =3D imgp->proc->p_sysent->sv_flags;
 +
 +#ifndef COMPAT_FREEBSD32
 +    vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +    vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +    vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +#else /* COMPAT_FREEBSD32 */
 +    if ((sv_flags & SV_LP64) !=3D 0) {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    } else {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compat_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    }
 +#endif /* !COMPAT_FREEBSD32 */
 +}
 +
 +void
 +pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t =
 orig_addr, int flags)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    if (!(flags & MAP_FIXED) && ((orig_addr =3D=3D 0) || !(flags & =
 MAP_ANON))) {
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] applying to %p orig_addr=3D%p f=3D%x\n",
 +                (void *)*addr, (void *)orig_addr, flags);
 +        if (!(td->td_proc->p_vmspace->vm_map.flags & =
 MAP_ENTRY_GROWS_DOWN))
 +            *addr +=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        else
 +            *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] result %p\n", (void *)*addr);
 +    }
 +    else if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] not applying to %p orig_addr=3D%p f=3D%x\n",
 +        (void *)*addr, (void *)orig_addr, flags);
 +}
 +
 +void
 +pax_aslr_stack(struct thread *td, uintptr_t *addr, uintptr_t orig_addr)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_stack;
 +    if ((pr) && pr->pr_pax_aslr_debug)
 +        uprintf("[PaX ASLR] orig_addr=3D%p, addr=3D%p\n",
 +            (void *)orig_addr, (void *)*addr);
 +}
 diff --git a/sys/sys/jail.h b/sys/sys/jail.h
 index 59d791c..f2bb97c 100644
 --- a/sys/sys/jail.h
 +++ b/sys/sys/jail.h
 @@ -184,6 +184,20 @@ struct prison {
  	char		 pr_hostname[MAXHOSTNAMELEN];	/* (p) jail =
 hostname */
  	char		 pr_domainname[MAXHOSTNAMELEN];	/* (p) jail =
 domainname */
  	char		 pr_hostuuid[HOSTUUIDLEN];	/* (p) jail =
 hostuuid */
 +#ifdef PAX_ASLR
 +    int pr_pax_set;
 +    int pr_pax_aslr_status;
 +    int pr_pax_aslr_debug;
 +    int pr_pax_aslr_mmap_len;
 +    int pr_pax_aslr_stack_len;
 +    int pr_pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +#if defined(PAX_ASLR) && defined(COMPAT_FREEBSD32)
 +    int pr_pax_aslr_compat_status;
 +    int pr_pax_aslr_compat_mmap_len;
 +    int pr_pax_aslr_compat_stack_len;
 +    int pr_pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
  };
 =20
  struct prison_racct {
 diff --git a/sys/sys/pax.h b/sys/sys/pax.h
 new file mode 100644
 index 0000000..b66e68b
 --- /dev/null
 +++ b/sys/sys/pax.h
 @@ -0,0 +1,166 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#ifndef	__SYS_PAX_H
 +#define	__SYS_PAX_H
 +
 +struct image_params;
 +struct thread;
 +struct vmspace;
 +struct vm_offset_t;
 +
 +/*
 + * used in sysctl handler
 + */
 +#define	PAX_ASLR_DISABLED		0
 +#define PAX_ASLR_ENABLED		1
 +#define PAX_ASLR_GLOBAL_ENABLED		2
 +#define	PAX_ASLR_FORCE_GLOBAL_ENABLED	3
 +
 +#ifndef PAX_ASLR_DELTA
 +#define	PAX_ASLR_DELTA(delta, lsb, len)	\
 +	(((delta) & ((1UL << (len)) - 1)) << (lsb))
 +#endif /* PAX_ASLR_DELTA */
 +
 +#ifdef PAX_ASLR
 +/*
 + * generic ASLR values
 + *
 + *  	MMAP	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  8 bit | 16 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 16 bit | 32 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	STACK	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	EXEC	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + */
 +#ifndef PAX_ASLR_DELTA_MMAP_LSB
 +#define PAX_ASLR_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_DELTA_MMAP_MIN_LEN	((sizeof(void *) * NBBY) / 4)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_DELTA_MMAP_MAX_LEN	((sizeof(void *) * NBBY) / 2)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_LSB
 +#define PAX_ASLR_DELTA_STACK_LSB	3
 +#endif /* PAX_ASLR_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_DELTA_STACK_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_DELTA_STACK_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_LSB
 +#define PAX_ASLR_DELTA_EXEC_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_EXEC_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_DELTA_EXEC_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_DELTA_EXEC_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +/*
 + * ASLR values for COMPAT_FREEBSD32 and COMPAT_LINUX
 + */
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN	((sizeof(int) * NBBY) / =
 4)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN	((sizeof(int) * NBBY) / =
 2)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB
 +#define PAX_ASLR_COMPAT_DELTA_STACK_LSB		3
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +extern int pax_aslr_status;
 +extern int pax_aslr_debug;
 +extern int pax_aslr_compat_status;
 +
 +extern int pax_aslr_mmap_len;
 +extern int pax_aslr_stack_len;
 +extern int pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +
 +void pax_init(void);
 +void pax_aslr_init_prison(struct prison *pr);
 +bool pax_aslr_active(struct thread *td, struct proc *proc);
 +void pax_aslr_init(struct thread *td, struct image_params *imgp);
 +void pax_aslr_mmap(struct thread *td, vm_offset_t *addr,
 +			vm_offset_t orig_addr, int flags);
 +void pax_aslr_stack(struct thread *td, uintptr_t *addr, uintptr_t =
 orig_addr);
 +struct prison *pax_aslr_get_prison(struct thread *td, struct proc =
 *proc);
 +
 +#endif /* __SYS_PAX_H */
 diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
 index e15e0ca..3c066ef 100644
 --- a/sys/vm/vm_map.c
 +++ b/sys/vm/vm_map.c
 @@ -65,6 +65,8 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD$");
 =20
 +#include "opt_pax.h"
 +
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/kernel.h>
 @@ -289,6 +291,10 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, =
 pmap_pinit_t pinit)
  	vm->vm_taddr =3D 0;
  	vm->vm_daddr =3D 0;
  	vm->vm_maxsaddr =3D 0;
 +#ifdef PAX_ASLR
 +	vm->vm_aslr_delta_mmap =3D 0;
 +	vm->vm_aslr_delta_stack =3D 0;
 +#endif /* PAX_ASLR */
  	return (vm);
  }
 =20
 diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
 index 850bf25..e4fbebd 100644
 --- a/sys/vm/vm_map.h
 +++ b/sys/vm/vm_map.h
 @@ -241,6 +241,8 @@ struct vmspace {
  	caddr_t vm_taddr;	/* (c) user virtual address of text */
  	caddr_t vm_daddr;	/* (c) user virtual address of data */
  	caddr_t vm_maxsaddr;	/* user VA at max stack growth */
 +	vm_size_t vm_aslr_delta_mmap;	/* mmap() random delta for ASLR =
 */
 +	vm_size_t vm_aslr_delta_stack;	/* stack random delta for ASLR =
 */
  	volatile int vm_refcnt;	/* number of references */
  	/*
  	 * Keep the PMAP last, so that CPU-specific variations of that
 diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
 index 272491e..3707c5a 100644
 --- a/sys/vm/vm_mmap.c
 +++ b/sys/vm/vm_mmap.c
 @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 =20
  #include "opt_compat.h"
  #include "opt_hwpmc_hooks.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/systm.h>
 @@ -91,6 +92,10 @@ __FBSDID("$FreeBSD$");
  #include <sys/pmckern.h>
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  int old_mlock =3D 0;
  SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, =
 &old_mlock, 0,
      "Do not apply RLIMIT_MEMLOCK on mlockall");
 @@ -203,6 +208,9 @@ sys_mmap(td, uap)
  	struct file *fp;
  	struct vnode *vp;
  	vm_offset_t addr;
 +#ifdef PAX_ASLR
 +	vm_offset_t orig_addr;
 +#endif /* PAX_ASLR */
  	vm_size_t size, pageoff;
  	vm_prot_t cap_maxprot, prot, maxprot;
  	void *handle;
 @@ -213,6 +221,9 @@ sys_mmap(td, uap)
  	cap_rights_t rights;
 =20
  	addr =3D (vm_offset_t) uap->addr;
 +#ifdef PAX_ASLR
 +	orig_addr =3D addr;
 +#endif /* PAX_ASLR */
  	size =3D uap->len;
  	prot =3D uap->prot & VM_PROT_ALL;
  	flags =3D uap->flags;
 @@ -309,9 +320,11 @@ sys_mmap(td, uap)
  		if (addr =3D=3D 0 ||
  		    (addr >=3D round_page((vm_offset_t)vms->vm_taddr) &&
  		    addr < round_page((vm_offset_t)vms->vm_daddr +
 -		    lim_max(td->td_proc, RLIMIT_DATA))))
 -			addr =3D round_page((vm_offset_t)vms->vm_daddr +
 -			    lim_max(td->td_proc, RLIMIT_DATA));
 +		    lim_max(td->td_proc, RLIMIT_DATA)))) {
 +                addr =3D round_page((vm_offset_t)vms->vm_daddr +
 +                    lim_max(td->td_proc, RLIMIT_DATA));
 +                addr =3D round_page(addr + =
 (arc4random()&(256*1024*1024-1)));
 +        }
  		PROC_UNLOCK(td->td_proc);
  	}
  	if (flags & MAP_ANON) {
 @@ -414,6 +427,9 @@ sys_mmap(td, uap)
  map:
  	td->td_fpop =3D fp;
  	maxprot &=3D cap_maxprot;
 +#ifdef PAX_ASLR
 +	pax_aslr_mmap(td, &addr, orig_addr, flags);
 +#endif /* PAX_ASLR */
  	error =3D vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
  	    flags, handle_type, handle, pos);
  	td->td_fpop =3D NULL;
 
 --Apple-Mail=_6421661B-1BA8-4BA0-96DB-F61C15728C24--

From: Shawn Webb <lattera@gmail.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel
Date: Fri, 21 Mar 2014 20:49:01 -0400

 --Apple-Mail=_3B294110-F7A1-429D-BF98-4300F2774717
 Content-Transfer-Encoding: 7bit
 Content-Type: text/plain;
 	charset=us-ascii
 
 The attached patch provides better stability to the new PIE feature.
 
 
 --Apple-Mail=_3B294110-F7A1-429D-BF98-4300F2774717
 Content-Disposition: attachment;
 	filename=aslr-2014-03-21_02.patch.txt
 Content-Type: text/plain;
 	name="aslr-2014-03-21_02.patch.txt"
 Content-Transfer-Encoding: quoted-printable
 
 diff --git a/sys/compat/freebsd32/freebsd32_misc.c =
 b/sys/compat/freebsd32/freebsd32_misc.c
 index b093a76..1bf0d12 100644
 --- a/sys/compat/freebsd32/freebsd32_misc.c
 +++ b/sys/compat/freebsd32/freebsd32_misc.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_compat.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #define __ELF_WORD_SIZE 32
 =20
 @@ -113,6 +114,10 @@ __FBSDID("$FreeBSD$");
 =20
  FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  #ifndef __mips__
  CTASSERT(sizeof(struct timeval32) =3D=3D 8);
  CTASSERT(sizeof(struct timespec32) =3D=3D 8);
 @@ -2822,6 +2827,9 @@ freebsd32_copyout_strings(struct image_params =
 *imgp)
  {
  	int argc, envc, i;
  	u_int32_t *vectp;
 +#ifdef PAX_ASLR
 +	uintptr_t orig_destp;
 +#endif /* PAX_ASLR */
  	char *stringp;
  	uintptr_t destp;
  	u_int32_t *stack_base;
 @@ -2847,6 +2855,11 @@ freebsd32_copyout_strings(struct image_params =
 *imgp)
  		szsigcode =3D 0;
  	destp =3D	(uintptr_t)arginfo;
 =20
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 +
  	/*
  	 * install sigcode
  	 */
 diff --git a/sys/conf/files b/sys/conf/files
 index 596cc69..c2e59ca 100644
 --- a/sys/conf/files
 +++ b/sys/conf/files
 @@ -2835,6 +2835,7 @@ kern/kern_mtxpool.c		standard
  kern/kern_mutex.c		standard
  kern/kern_ntptime.c		standard
  kern/kern_osd.c			standard
 +kern/kern_pax.c			optional pax_aslr
  kern/kern_physio.c		standard
  kern/kern_pmc.c			standard
  kern/kern_poll.c		optional device_polling
 diff --git a/sys/conf/options b/sys/conf/options
 index 75fe424..ecabb5f 100644
 --- a/sys/conf/options
 +++ b/sys/conf/options
 @@ -910,6 +910,9 @@ RACCT		opt_global.h
  # Resource Limits
  RCTL		opt_global.h
 =20
 +# PaX - hardening options
 +PAX_ASLR		opt_pax.h
 +PAX_ASLR_MAX_SEC	opt_pax.h
  # Random number generator(s)
  RANDOM_YARROW	opt_random.h
  RANDOM_FORTUNA	opt_random.h
 diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
 index d5ec365..68852bb 100644
 --- a/sys/kern/imgact_elf.c
 +++ b/sys/kern/imgact_elf.c
 @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_compat.h"
  #include "opt_core.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/capsicum.h>
 @@ -47,7 +48,9 @@ __FBSDID("$FreeBSD$");
  #include <sys/mount.h>
  #include <sys/mman.h>
  #include <sys/namei.h>
 +#include <sys/pax.h>
  #include <sys/pioctl.h>
 +#include <sys/jail.h>
  #include <sys/proc.h>
  #include <sys/procfs.h>
  #include <sys/racct.h>
 @@ -600,6 +603,9 @@ __elfN(load_file)(struct proc *p, const char *file, =
 u_long *addr,
  	u_long rbase;
  	u_long base_addr =3D 0;
  	int error, i, numsegs;
 +#ifdef PAX_ASLR
 +    struct prison *pr;
 +#endif
 =20
  #ifdef CAPABILITY_MODE
  	/*
 @@ -655,11 +661,17 @@ __elfN(load_file)(struct proc *p, const char =
 *file, u_long *addr,
  	hdr =3D (const Elf_Ehdr *)imgp->image_header;
  	if ((error =3D __elfN(check_header)(hdr)) !=3D 0)
  		goto fail;
 -	if (hdr->e_type =3D=3D ET_DYN)
 +	if (hdr->e_type =3D=3D ET_DYN) {
  		rbase =3D *addr;
 -	else if (hdr->e_type =3D=3D ET_EXEC)
 +#ifdef PAX_ASLR
 +        if (pax_aslr_active(NULL, imgp->proc)) {
 +            pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +            rbase +=3D round_page(PAX_ASLR_DELTA(arc4random(), =
 PAX_ASLR_DELTA_EXEC_LSB, pr->pr_pax_aslr_exec_len));
 +        }
 +#endif
 +    } else if (hdr->e_type =3D=3D ET_EXEC) {
  		rbase =3D 0;
 -	else {
 +    } else {
  		error =3D ENOEXEC;
  		goto fail;
  	}
 @@ -729,6 +741,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params =
 *imgp)
  	Elf_Brandinfo *brand_info;
  	char *path;
  	struct sysentvec *sv;
 +#ifdef PAX_ASLR
 +    struct prison *pr;
 +#endif
 =20
  	/*
  	 * Do we have a valid ELF header ?
 @@ -793,10 +808,23 @@ __CONCAT(exec_, __elfN(imgact))(struct =
 image_params *imgp)
  		 * Honour the base load address from the dso if it is
  		 * non-zero for some reason.
  		 */
 -		if (baddr =3D=3D 0)
 +		if (baddr =3D=3D 0) {
 +#ifdef PAX_ASLR
 +            if (pax_aslr_active(NULL, imgp->proc)) {
 +                pr =3D pax_aslr_get_prison(NULL, imgp->proc);
 +                do {
 +                    /* Do this in a loop to make sure we don't attempt =
 a NULL page mapping */
 +                    et_dyn_addr =3D =
 trunc_page(PAX_ASLR_DELTA(arc4random(), PAX_ASLR_DELTA_EXEC_LSB, =
 pr->pr_pax_aslr_exec_len));
 +                } while (et_dyn_addr =3D=3D 0);
 +            } else {
 +                et_dyn_addr =3D ET_DYN_LOAD_ADDR;
 +            }
 +#else
  			et_dyn_addr =3D ET_DYN_LOAD_ADDR;
 -		else
 +#endif
 +        } else {
  			et_dyn_addr =3D 0;
 +        }
  	} else
  		et_dyn_addr =3D 0;
  	sv =3D brand_info->sysvec;
 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
 index 9f223ca..7f54f33 100644
 --- a/sys/kern/kern_exec.c
 +++ b/sys/kern/kern_exec.c
 @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_capsicum.h"
  #include "opt_hwpmc_hooks.h"
  #include "opt_ktrace.h"
 +#include "opt_pax.h"
  #include "opt_vm.h"
 =20
  #include <sys/param.h>
 @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$");
  dtrace_execexit_func_t	dtrace_fasttrap_exec;
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  SDT_PROVIDER_DECLARE(proc);
  SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
  SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
 @@ -1055,6 +1060,10 @@ exec_new_vmspace(imgp, sv)
  		map =3D &vmspace->vm_map;
  	}
 =20
 +#ifdef PAX_ASLR
 +	pax_aslr_init(curthread, imgp);
 +#endif /* PAX_ASLR */
 +
  	/* Map a shared page */
  	obj =3D sv->sv_shared_page_obj;
  	if (obj !=3D NULL) {
 @@ -1231,6 +1240,9 @@ exec_copyout_strings(imgp)
  {
  	int argc, envc;
  	char **vectp;
 +#ifdef	PAX_ASLR
 +	uintptr_t orig_destp;
 +#endif /* PAX_ASLR */
  	char *stringp;
  	uintptr_t destp;
  	register_t *stack_base;
 @@ -1257,6 +1269,10 @@ exec_copyout_strings(imgp)
  			szsigcode =3D *(p->p_sysent->sv_szsigcode);
  	}
  	destp =3D	(uintptr_t)arginfo;
 +#ifdef PAX_ASLR
 +	orig_destp =3D destp;
 +	pax_aslr_stack(curthread, &destp, orig_destp);
 +#endif /* PAX_ASLR */
 =20
  	/*
  	 * install sigcode
 diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
 index 47cd568..f8751a4 100644
 --- a/sys/kern/kern_jail.c
 +++ b/sys/kern/kern_jail.c
 @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
  #include "opt_ddb.h"
  #include "opt_inet.h"
  #include "opt_inet6.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/types.h>
 @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/syscallsubr.h>
  #include <sys/sysctl.h>
  #include <sys/vnode.h>
 +#include <sys/pax.h>
 =20
  #include <net/if.h>
  #include <net/if_var.h>
 @@ -114,6 +116,20 @@ struct prison prison0 =3D {
  	.pr_flags	=3D PR_HOST|_PR_IP_SADDRSEL,
  #endif
  	.pr_allow	=3D PR_ALLOW_ALL,
 +#ifdef PAX_ASLR
 +    .pr_pax_set =3D 0,
 +    .pr_pax_aslr_status =3D 0,
 +    .pr_pax_aslr_debug =3D 0,
 +    .pr_pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN,
 +#ifdef COMPAT_FREEBSD32
 +    .pr_pax_aslr_compat_status =3D 0,
 +    .pr_pax_aslr_compat_mmap_len =3D =
 PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN,
 +    .pr_pax_aslr_compat_stack_len =3D =
 PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN,
 +    .pr_pax_aslr_compat_exec_len =3D =
 PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN,
 +#endif /* COMPAT_FREEBSD32 */
 +#endif /* PAX_ASLR */
  };
  MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
 =20
 diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c
 new file mode 100644
 index 0000000..2185baf
 --- /dev/null
 +++ b/sys/kern/kern_pax.c
 @@ -0,0 +1,588 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#include <sys/cdefs.h>
 +__FBSDID("$FreeBSD$");
 +
 +#include "opt_pax.h"
 +#include "opt_compat.h"
 +
 +#include <sys/param.h>
 +#include <sys/systm.h>
 +#include <sys/kernel.h>
 +#include <sys/imgact.h>
 +#include <sys/sysent.h>
 +#include <sys/proc.h>
 +#include <sys/elf_common.h>
 +#include <sys/pax.h>
 +#include <sys/sysctl.h>
 +#include <sys/vnode.h>
 +#include <sys/queue.h>
 +#include <sys/libkern.h>
 +#include <sys/jail.h>
 +
 +#include <sys/mman.h>
 +#include <sys/libkern.h>
 +#include <sys/exec.h>
 +
 +#include <vm/pmap.h>
 +#include <vm/vm_map.h>
 +
 +static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS);
 +
 +/*
 + * sysctls and tunables
 + */
 +int pax_aslr_status =3D PAX_ASLR_ENABLED;
 +int pax_aslr_debug =3D 0;
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MAX_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MIN_LEN;
 +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +
 +SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
 +    "PaX (exploit mitigation) features.");
 +SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0,
 +    "Address Space Layout Randomization.");
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status);
 +
 +SYSCTL_INT(_security_pax_aslr, OID_AUTO, debug, =
 CTLFLAG_RWTUN|CTLFLAG_PRISON, &pax_aslr_debug, 0, "ASLR debug mode");
 +TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16] 64 bit: [16,32]");
 +TUNABLE_INT("security.pax.aslr.mmap", &pax_aslr_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12] 64 bit: [12,21]");
 +TUNABLE_INT("security.pax.aslr.stack", &pax_aslr_exec_len);
 +
 +static int
 +sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_status =3D val;
 +            if (pr)
 +                pr->pr_pax_aslr_status =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_mmap_len : =
 pax_aslr_mmap_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_mmap_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_mmap_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_stack_len : =
 pax_aslr_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_stack_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_stack_len =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : =
 pax_aslr_exec_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_exec_len =3D val;
 +    if (pr)
 +        pr->pr_pax_aslr_exec_len =3D val;
 +
 +    return (0);
 +}
 +
 +/*
 + * COMPAT_FREEBSD32 and linuxulator..
 + */
 +#ifdef COMPAT_FREEBSD32
 +int pax_aslr_compat_status =3D PAX_ASLR_ENABLED;
 +
 +static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS);
 +static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS);
 +
 +#ifdef PAX_ASLR_MAX_SEC
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN;
 +#else
 +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
 +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
 +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
 +#endif /* PAX_ASLR_MAX_SEC */
 +
 +SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0,
 +    "Setting for COMPAT_FREEBSD32 and linuxulator.");
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_status, "I",
 +    "Restrictions status. "
 +    "0 - disabled, "
 +    "1 - enabled,  "
 +    "2 - global enabled, "
 +    "3 - force global enabled");
 +TUNABLE_INT("security.pax.aslr.compat.status", =
 &pax_aslr_compat_status);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_mmap, "I",
 +    "Number of bits randomized for mmap(2) calls. "
 +    "32 bit: [8,16]");
 +TUNABLE_INT("security.pax.aslr.compat.mmap", =
 &pax_aslr_compat_mmap_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_stack, "I",
 +    "Number of bits randomized for the stack. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_stack_len);
 +
 +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len,
 +    CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_TUN|CTLFLAG_PRISON,
 +    NULL, 0, sysctl_pax_aslr_compat_exec, "I",
 +    "Number of bits randomized for the PIE exec base. "
 +    "32 bit: [6,12]");
 +TUNABLE_INT("security.pax.aslr.compat.stack", =
 &pax_aslr_compat_exec_len);
 +
 +
 +static int
 +sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_status) : =
 &pax_aslr_compat_status;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    switch (val) {
 +        case    PAX_ASLR_DISABLED:
 +        case    PAX_ASLR_ENABLED:
 +        case    PAX_ASLR_GLOBAL_ENABLED:
 +        case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +            pax_aslr_compat_status =3D val;
 +            *ptr =3D val;
 +            break;
 +        default:
 +            return (EINVAL);
 +    }
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_mmap_len) : =
 &pax_aslr_compat_mmap_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_mmap_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_stack_len) : =
 &pax_aslr_compat_stack_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_compat_stack_len : =
 pax_aslr_compat_stack_len;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_stack_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +
 +static int
 +sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
 +{
 +    int err;
 +    int val, *ptr;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(req->td, NULL);
 +    ptr =3D (pr !=3D NULL) ? &(pr->pr_pax_aslr_compat_exec_len) : =
 &pax_aslr_compat_exec_len;
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    val =3D *ptr;
 +    err =3D sysctl_handle_int(oidp, &val, sizeof(int), req);
 +    if (err || !req->newptr)
 +        return (err);
 +
 +    if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +        || val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN)
 +        return (EINVAL);
 +
 +    pax_aslr_compat_exec_len =3D val;
 +    *ptr =3D val;
 +
 +    return (0);
 +}
 +#endif /* COMPAT_FREEBSD32 */
 +
 +
 +/*
 + * ASLR functions
 + */
 +bool
 +pax_aslr_active(struct thread *td, struct proc *proc)
 +{
 +    int status;
 +    struct prison *pr=3DNULL;
 +#ifdef  notyet
 +    uint32_t    flags;
 +#endif /* notyet */
 +
 +    if (!(td) && !(proc))
 +        return (true);
 +
 +#ifdef notyet
 +    flags =3D (td !=3D NULL) ? td->td_proc->p_pax : proc->p_pax;
 +#endif /* notyet */
 +    pr =3D pax_aslr_get_prison(td, proc);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    status =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : =
 pax_aslr_status;
 +
 +    switch (status) {
 +    case    PAX_ASLR_DISABLED:
 +        return (false);
 +    case    PAX_ASLR_FORCE_GLOBAL_ENABLED:
 +        return (true);
 +    case    PAX_ASLR_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_ASLR) =3D=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    case    PAX_ASLR_GLOBAL_ENABLED:
 +#ifdef notyet
 +        if ((flags & ELF_NOTE_PAX_NOASLR) !=3D 0)
 +            return (false);
 +#endif /* notyet */
 +        break;
 +    default:
 +        return (true);
 +    }
 +
 +    return (true);
 +}
 +
 +struct prison *
 +pax_aslr_get_prison(struct thread *td, struct proc *proc)
 +{
 +    if ((td)) {
 +        if ((td->td_proc) && (td->td_proc->p_ucred))
 +            return td->td_proc->p_ucred->cr_prison;
 +
 +        return NULL;
 +    }
 +
 +    if (!(proc))
 +        return NULL;
 +
 +    return proc->p_ucred->cr_prison;
 +}
 +
 +void
 +pax_aslr_init_prison(struct prison *pr)
 +{
 +    if (!(pr))
 +        return;
 +
 +    if (pr->pr_pax_set)
 +        return;
 +
 +    if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] pax_aslr_init_prison: Setting prison %s =
 ASLR variables\n", pr->pr_name);
 +
 +    pr->pr_pax_aslr_status =3D pax_aslr_status;
 +    pr->pr_pax_aslr_debug =3D pax_aslr_debug;
 +    pr->pr_pax_aslr_mmap_len =3D pax_aslr_mmap_len;
 +    pr->pr_pax_aslr_stack_len =3D pax_aslr_stack_len;
 +    pr->pr_pax_aslr_exec_len =3D pax_aslr_exec_len;
 +
 +#ifdef COMPAT_FREEBSD32
 +    pr->pr_pax_aslr_compat_status =3D pax_aslr_compat_status;
 +    pr->pr_pax_aslr_compat_mmap_len =3D pax_aslr_compat_mmap_len;
 +    pr->pr_pax_aslr_compat_stack_len =3D pax_aslr_compat_stack_len;
 +    pr->pr_pax_aslr_compat_exec_len =3D pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
 +
 +    pr->pr_pax_set =3D 1;
 +}
 +
 +void
 +pax_aslr_init(struct thread *td, struct image_params *imgp)
 +{
 +    struct vmspace *vm;
 +    u_int sv_flags;
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if ((pr) && !(pr->pr_pax_set))
 +        pax_aslr_init_prison(pr);
 +
 +    if (imgp =3D=3D NULL) {
 +        panic("[PaX ASLR] pax_aslr_init - imgp =3D=3D NULL");
 +    }
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    vm =3D imgp->proc->p_vmspace;
 +    sv_flags =3D imgp->proc->p_sysent->sv_flags;
 +
 +#ifndef COMPAT_FREEBSD32
 +    vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +    vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +        PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +    vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +#else /* COMPAT_FREEBSD32 */
 +    if ((sv_flags & SV_LP64) !=3D 0) {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_stack_len : pax_aslr_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    } else {
 +        vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compat_mmap_len);
 +        vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(),
 +            PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr !=3D NULL) ? =
 pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len);
 +        vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack);
 +    }
 +#endif /* !COMPAT_FREEBSD32 */
 +}
 +
 +void
 +pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t =
 orig_addr, int flags)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    if (!(flags & MAP_FIXED) && ((orig_addr =3D=3D 0) || !(flags & =
 MAP_ANON))) {
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] applying to %p orig_addr=3D%p f=3D%x\n",
 +                (void *)*addr, (void *)orig_addr, flags);
 +        if (!(td->td_proc->p_vmspace->vm_map.flags & =
 MAP_ENTRY_GROWS_DOWN))
 +            *addr +=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        else
 +            *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap;
 +        if (pax_aslr_debug)
 +            uprintf("[PaX ASLR] result %p\n", (void *)*addr);
 +    }
 +    else if (pax_aslr_debug)
 +        uprintf("[PaX ASLR] not applying to %p orig_addr=3D%p f=3D%x\n",
 +        (void *)*addr, (void *)orig_addr, flags);
 +}
 +
 +void
 +pax_aslr_stack(struct thread *td, uintptr_t *addr, uintptr_t orig_addr)
 +{
 +    struct prison *pr=3DNULL;
 +
 +    pr =3D pax_aslr_get_prison(td, NULL);
 +
 +    if (!pax_aslr_active(td, NULL))
 +        return;
 +
 +    *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_stack;
 +    if ((pr) && pr->pr_pax_aslr_debug)
 +        uprintf("[PaX ASLR] orig_addr=3D%p, addr=3D%p\n",
 +            (void *)orig_addr, (void *)*addr);
 +}
 diff --git a/sys/sys/jail.h b/sys/sys/jail.h
 index 59d791c..f2bb97c 100644
 --- a/sys/sys/jail.h
 +++ b/sys/sys/jail.h
 @@ -184,6 +184,20 @@ struct prison {
  	char		 pr_hostname[MAXHOSTNAMELEN];	/* (p) jail =
 hostname */
  	char		 pr_domainname[MAXHOSTNAMELEN];	/* (p) jail =
 domainname */
  	char		 pr_hostuuid[HOSTUUIDLEN];	/* (p) jail =
 hostuuid */
 +#ifdef PAX_ASLR
 +    int pr_pax_set;
 +    int pr_pax_aslr_status;
 +    int pr_pax_aslr_debug;
 +    int pr_pax_aslr_mmap_len;
 +    int pr_pax_aslr_stack_len;
 +    int pr_pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +#if defined(PAX_ASLR) && defined(COMPAT_FREEBSD32)
 +    int pr_pax_aslr_compat_status;
 +    int pr_pax_aslr_compat_mmap_len;
 +    int pr_pax_aslr_compat_stack_len;
 +    int pr_pax_aslr_compat_exec_len;
 +#endif /* COMPAT_FREEBSD32 */
  };
 =20
  struct prison_racct {
 diff --git a/sys/sys/pax.h b/sys/sys/pax.h
 new file mode 100644
 index 0000000..b66e68b
 --- /dev/null
 +++ b/sys/sys/pax.h
 @@ -0,0 +1,166 @@
 +/*-
 + * Copyright (c) 2013, by Oliver Pinter <oliver.pntr at gmail.com>
 + * All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. The name of the developer may NOT be used to endorse or promote =
 products
 + *    derived from this software without specific prior written =
 permission.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, =
 THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS =
 INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF
 + * SUCH DAMAGE.
 + *
 + * $FreeBSD$
 + *
 + * Enhancements made by Shawn "lattera" Webb under the direction of =
 SoldierX.
 + */
 +
 +#ifndef	__SYS_PAX_H
 +#define	__SYS_PAX_H
 +
 +struct image_params;
 +struct thread;
 +struct vmspace;
 +struct vm_offset_t;
 +
 +/*
 + * used in sysctl handler
 + */
 +#define	PAX_ASLR_DISABLED		0
 +#define PAX_ASLR_ENABLED		1
 +#define PAX_ASLR_GLOBAL_ENABLED		2
 +#define	PAX_ASLR_FORCE_GLOBAL_ENABLED	3
 +
 +#ifndef PAX_ASLR_DELTA
 +#define	PAX_ASLR_DELTA(delta, lsb, len)	\
 +	(((delta) & ((1UL << (len)) - 1)) << (lsb))
 +#endif /* PAX_ASLR_DELTA */
 +
 +#ifdef PAX_ASLR
 +/*
 + * generic ASLR values
 + *
 + *  	MMAP	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  8 bit | 16 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 16 bit | 32 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	STACK	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + *  	EXEC	| 32 bit | 64 bit |
 + * 	+-------+--------+--------+
 + * 	| MIN	|  6 bit | 12 bit |
 + * 	+-------+--------+--------+
 + * 	| MAX   | 10 bit | 21 bit |
 + * 	+-------+--------+--------+
 + *
 + */
 +#ifndef PAX_ASLR_DELTA_MMAP_LSB
 +#define PAX_ASLR_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_DELTA_MMAP_MIN_LEN	((sizeof(void *) * NBBY) / 4)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_DELTA_MMAP_MAX_LEN	((sizeof(void *) * NBBY) / 2)
 +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_LSB
 +#define PAX_ASLR_DELTA_STACK_LSB	3
 +#endif /* PAX_ASLR_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_DELTA_STACK_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_DELTA_STACK_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_LSB
 +#define PAX_ASLR_DELTA_EXEC_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_DELTA_EXEC_LSB */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_DELTA_EXEC_MIN_LEN	((sizeof(void *) * NBBY) / 5)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_DELTA_EXEC_MAX_LEN	((sizeof(void *) * NBBY) / 3)
 +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
 +
 +/*
 + * ASLR values for COMPAT_FREEBSD32 and COMPAT_LINUX
 + */
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB		PAGE_SHIFT
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN	((sizeof(int) * NBBY) / =
 4)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN	((sizeof(int) * NBBY) / =
 2)
 +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB
 +#define PAX_ASLR_COMPAT_DELTA_STACK_LSB		3
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN	((sizeof(int) * NBBY) / =
 5)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN
 +#define PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN	((sizeof(int) * NBBY) / =
 3)
 +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
 +
 +extern int pax_aslr_status;
 +extern int pax_aslr_debug;
 +extern int pax_aslr_compat_status;
 +
 +extern int pax_aslr_mmap_len;
 +extern int pax_aslr_stack_len;
 +extern int pax_aslr_exec_len;
 +#endif /* PAX_ASLR */
 +
 +void pax_init(void);
 +void pax_aslr_init_prison(struct prison *pr);
 +bool pax_aslr_active(struct thread *td, struct proc *proc);
 +void pax_aslr_init(struct thread *td, struct image_params *imgp);
 +void pax_aslr_mmap(struct thread *td, vm_offset_t *addr,
 +			vm_offset_t orig_addr, int flags);
 +void pax_aslr_stack(struct thread *td, uintptr_t *addr, uintptr_t =
 orig_addr);
 +struct prison *pax_aslr_get_prison(struct thread *td, struct proc =
 *proc);
 +
 +#endif /* __SYS_PAX_H */
 diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
 index 34807ab..bbacdd7 100644
 --- a/sys/vm/vm_map.c
 +++ b/sys/vm/vm_map.c
 @@ -65,6 +65,8 @@
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD$");
 =20
 +#include "opt_pax.h"
 +
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/kernel.h>
 @@ -289,6 +291,10 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, =
 pmap_pinit_t pinit)
  	vm->vm_taddr =3D 0;
  	vm->vm_daddr =3D 0;
  	vm->vm_maxsaddr =3D 0;
 +#ifdef PAX_ASLR
 +	vm->vm_aslr_delta_mmap =3D 0;
 +	vm->vm_aslr_delta_stack =3D 0;
 +#endif /* PAX_ASLR */
  	return (vm);
  }
 =20
 diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
 index 850bf25..e4fbebd 100644
 --- a/sys/vm/vm_map.h
 +++ b/sys/vm/vm_map.h
 @@ -241,6 +241,8 @@ struct vmspace {
  	caddr_t vm_taddr;	/* (c) user virtual address of text */
  	caddr_t vm_daddr;	/* (c) user virtual address of data */
  	caddr_t vm_maxsaddr;	/* user VA at max stack growth */
 +	vm_size_t vm_aslr_delta_mmap;	/* mmap() random delta for ASLR =
 */
 +	vm_size_t vm_aslr_delta_stack;	/* stack random delta for ASLR =
 */
  	volatile int vm_refcnt;	/* number of references */
  	/*
  	 * Keep the PMAP last, so that CPU-specific variations of that
 diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
 index 272491e..3707c5a 100644
 --- a/sys/vm/vm_mmap.c
 +++ b/sys/vm/vm_mmap.c
 @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 =20
  #include "opt_compat.h"
  #include "opt_hwpmc_hooks.h"
 +#include "opt_pax.h"
 =20
  #include <sys/param.h>
  #include <sys/systm.h>
 @@ -91,6 +92,10 @@ __FBSDID("$FreeBSD$");
  #include <sys/pmckern.h>
  #endif
 =20
 +#ifdef PAX_ASLR
 +#include <sys/pax.h>
 +#endif /* PAX_ASLR */
 +
  int old_mlock =3D 0;
  SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, =
 &old_mlock, 0,
      "Do not apply RLIMIT_MEMLOCK on mlockall");
 @@ -203,6 +208,9 @@ sys_mmap(td, uap)
  	struct file *fp;
  	struct vnode *vp;
  	vm_offset_t addr;
 +#ifdef PAX_ASLR
 +	vm_offset_t orig_addr;
 +#endif /* PAX_ASLR */
  	vm_size_t size, pageoff;
  	vm_prot_t cap_maxprot, prot, maxprot;
  	void *handle;
 @@ -213,6 +221,9 @@ sys_mmap(td, uap)
  	cap_rights_t rights;
 =20
  	addr =3D (vm_offset_t) uap->addr;
 +#ifdef PAX_ASLR
 +	orig_addr =3D addr;
 +#endif /* PAX_ASLR */
  	size =3D uap->len;
  	prot =3D uap->prot & VM_PROT_ALL;
  	flags =3D uap->flags;
 @@ -309,9 +320,11 @@ sys_mmap(td, uap)
  		if (addr =3D=3D 0 ||
  		    (addr >=3D round_page((vm_offset_t)vms->vm_taddr) &&
  		    addr < round_page((vm_offset_t)vms->vm_daddr +
 -		    lim_max(td->td_proc, RLIMIT_DATA))))
 -			addr =3D round_page((vm_offset_t)vms->vm_daddr +
 -			    lim_max(td->td_proc, RLIMIT_DATA));
 +		    lim_max(td->td_proc, RLIMIT_DATA)))) {
 +                addr =3D round_page((vm_offset_t)vms->vm_daddr +
 +                    lim_max(td->td_proc, RLIMIT_DATA));
 +                addr =3D round_page(addr + =
 (arc4random()&(256*1024*1024-1)));
 +        }
  		PROC_UNLOCK(td->td_proc);
  	}
  	if (flags & MAP_ANON) {
 @@ -414,6 +427,9 @@ sys_mmap(td, uap)
  map:
  	td->td_fpop =3D fp;
  	maxprot &=3D cap_maxprot;
 +#ifdef PAX_ASLR
 +	pax_aslr_mmap(td, &addr, orig_addr, flags);
 +#endif /* PAX_ASLR */
  	error =3D vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
  	    flags, handle_type, handle, pos);
  	td->td_fpop =3D NULL;
 
 --Apple-Mail=_3B294110-F7A1-429D-BF98-4300F2774717--
>Unformatted:
