kern/181497: [kernel] [patch] Add ASLR feature to kernel
Shawn Webb
lattera at gmail.com
Fri Mar 21 12:00:01 UTC 2014
The following reply was made to PR kern/181497; it has been noted by GNATS.
From: Shawn Webb <lattera at gmail.com>
To: bug-followup at 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--
More information about the freebsd-bugs
mailing list