From owner-freebsd-bugs@FreeBSD.ORG Sat Mar 22 00:50:01 2014 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.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 ESMTPS id 3BAA9F39 for ; Sat, 22 Mar 2014 00:50:01 +0000 (UTC) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 2574F9EB for ; Sat, 22 Mar 2014 00:50:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.8/8.14.8) with ESMTP id s2M0o0gm060361 for ; Sat, 22 Mar 2014 00:50:00 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.8/8.14.8/Submit) id s2M0o0cf060347; Sat, 22 Mar 2014 00:50:00 GMT (envelope-from gnats) Date: Sat, 22 Mar 2014 00:50:00 GMT Message-Id: <201403220050.s2M0o0cf060347@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Shawn Webb Subject: Re: kern/181497: [kernel] [patch] Add ASLR feature to kernel X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list Reply-To: Shawn Webb List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 22 Mar 2014 00:50:01 -0000 The following reply was made to PR kern/181497; it has been noted by GNATS. From: Shawn Webb 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 +#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 #include @@ -47,7 +48,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include @@ -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 @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$"); dtrace_execexit_func_t dtrace_fasttrap_exec; #endif =20 +#ifdef PAX_ASLR +#include +#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 #include @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include =20 #include #include @@ -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 + * 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 +__FBSDID("$FreeBSD$"); + +#include "opt_pax.h" +#include "opt_compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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 + * 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 __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include #include #include @@ -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 #include @@ -91,6 +92,10 @@ __FBSDID("$FreeBSD$"); #include #endif =20 +#ifdef PAX_ASLR +#include +#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--