Page MenuHomeFreeBSD

D473.id4321.diff
No OneTemporary

D473.id4321.diff

Index: share/man/man4/Makefile
===================================================================
--- share/man/man4/Makefile
+++ share/man/man4/Makefile
@@ -51,6 +51,7 @@
${_aout.4} \
${_apic.4} \
arcmsr.4 \
+ aslr.4 \
${_asmc.4} \
ata.4 \
ath.4 \
Index: share/man/man4/aslr.4
===================================================================
--- /dev/null
+++ share/man/man4/aslr.4
@@ -0,0 +1,255 @@
+.\"-
+.\" Copyright (c) 2014,2015 Shawn Webb <shawn.webb@hardenedbsd.org>
+.\" 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. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" 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$
+.\"
+.Dd February 21, 2015
+.Dt ASLR 4
+.Os
+.Sh NAME
+.Nm aslr
+.Nd Address Space Layout Randomization
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/pax.h
+.Pp
+In the kernel configuration file:
+.Cd "options PAX_ASLR"
+.Sh DESCRIPTION
+.Ss Introduction
+Security in
+.Fx
+is based primarily in policy-based technologies.
+Existing tools such as
+.Xr jail 4 ,
+.Xr capsicum 4 ,
+.Xr VNET 9 , and the
+.Xr mac 4
+framework can make
+.Fx Ns -based systems quite resilient against
+attacks.
+ASLR Randomizes the address space layout of an application, making
+exploitation difficult for an attacker.
+This manual page and the associated implementation aim to
+provide a secure, robust, extensible, and easily-managed form of ASLR
+fit for production use in
+.Fx Ns .
+.Ss General Overview
+When compiled with the PAX_ASLR option, systems will have ASLR
+enabled.
+For systems with that kernel option enabled, if a user wants
+to disable ASLR for a given application, the user must force that
+application to opt-out.
+.Pp
+Another kernel option,
+.Cd PAX_SYSCTLS ,
+exposes additional
+.Xr sysctl 8
+tunables, allowing ASLR behavior control without requiring a reboot.
+By default, the sysctl security.pax.aslr.status can only be changed
+at boot time via /boot/loader.conf.
+Enabling the PAX_SYSCTLS kernel option allows a root user to modify
+security.pax.aslr.status.
+See Appendix A for a list of all the tunables.
+.Pp
+ASLR tunables are per-jail and each jail inherits its parent jail's
+settings.
+Having per-jail tunables allows more flexibility in shared-hosting
+environments.
+This structure also allows a user to selectively disable ASLR for
+applications that misbehave.
+ASLR-disabled applications will still have policy-based security
+applied to it by virtue of being jailed.
+.Ss Implementation Details
+A new sysinit subroutine ID, SI_SUB_PAX, initializes ASLR system
+variables.
+Upon system boot, tunables from /boot/loader.conf are checked for
+validity.
+Any invalid values generate a warning message to the console and the
+tunable is set to a sensible default.
+.Pp
+For the sake of performance, the ASLR system relies on per-process
+deltas rather than calling
+.Xr arc4random 3
+for each mapping.
+When a process calls
+.Xr execve 2
+.Ns , the ASLR deltas are initialized.
+Deltas are randomly generated for the execution base,
+.Xr mmap 2
+.Ns , and stack addresses.
+Only the execution base of applications compiled as Position
+Independent Executables (PIEs) is randomized.
+The execution base of non-PIE applications is not modified.
+The mappings of shared objects are randomized for both PIE and non-PIE
+applications.
+.Pp
+The deltas are used as a hint to the Virtual Memory (VM) system.
+The VM system may modify the hint to make a better fit for superpages
+and other alignment constraints.
+.Pp
+The delta applied to the PIE execbase is different than the delta
+applied to the base address of shared objects.
+In the Executable and Linkable File (ELF) image handler, the
+execution base of PIE applications is randomized by adding the delta
+controlled by the security.pax.aslr.exec_len tunable to et_dyn_addr,
+which is initialized to be ET_DYN_LOAD_ADDR (an architecture-
+dependent macro).
+The base address of shared objects loaded by the dynamic linker are
+randomized by applying the delta controlled by the
+security.pax.aslr.mmap_len tunable in
+.Fn sys_mmap
+.Ns .
+Stack randomization is implemented using a stack gap.
+On executable image activation, the stack delta is computed and
+subtracted from the top of the stack.
+.Ss APPENDIX A
+NOTE: All tunables can only be changed during boot-time via
+.Fa /boot/loader.conf
+unless the kernel has been compiled with
+.Cd PAX_SYSCTLS
+.Ns .
+.Bl -bullet
+.It
+security.pax.aslr.status
+.Bl -dash -compact
+.It
+Type: integer
+.It
+Description: Toggle system-wide ASLR protection.
+.It
+Values:
+.br
+0 - ASLR disabled system-wide. Individual applications may
+.Em NOT
+opt in.
+.br
+1 - ASLR disabled but applications may opt in.
+.br
+2 - ASLR enabled and applications may opt out.
+.br
+3 - ASLR enabled for all applications. Applications may not opt out.
+.It
+Default: 2
+.El
+.It
+security.pax.aslr.exec_len
+.Bl -dash -compact
+.It
+Type: integer
+.It
+Description: Set the number of bits to be randomized for the PIE
+execbase.
+.It
+Values:
+.br
+For 32-bit systems, minimum of 8, maximum of 21. For 64-bit systems,
+minimum of 16, maximum of 42.
+.It
+Default: For 32-bit systems: 14. For 64-bit systems: 16.
+.El
+.It
+security.pax.aslr.mmap_len
+.Bl -dash -compact
+.It
+Type: integer
+.It
+Description: Set the number of bits to be randomized for
+.Xr mmap 2
+calls.
+.It
+Values:
+.br
+For 32-bit systems, minimum of 8, maximum of 21. For 64-bit systems,
+minimum of 16, maximum of 42.
+.It
+Default: For 32-bit systems: 14. For 64-bit systems: 21.
+.El
+.It
+security.pax.aslr.stack_len
+.Bl -dash -compact
+.It
+Type: integer
+.It
+Description: Set the number of bits to be randomized for the stack.
+.It
+Values:
+.br
+For 32-bit systems, minimum of 8, maximum of 21. For 64-bit systems,
+minimum of 16, maximum of 42.
+.It
+Default: For 32-bit systems: 8. For 64-bit systems: 16.
+.El
+.El
+.Sh SEE ALSO
+.Xr mmap 2 ,
+.Xr elf 3 ,
+.Xr mac 4
+.Rs
+.%T "PaX ASLR"
+.%U http://pax.grsecurity.net/docs/aslr.txt
+.Re
+.Rs
+.%T "FreeBSD ASLR Bug Report"
+.%U https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=181497
+.Re
+.Rs
+.%T "HardenedBSD"
+.%U http://hardenedbsd.org/
+.Re
+.Rs
+.%T "secadm"
+.%U https://github.com/HardenedBSD/secadm
+.Re
+.Sh AUTHORS
+This manual page was written by
+.An -nosplit
+.An Shawn Webb .
+The ASLR implementation was written by
+.An Oliver Pinter and
+.An Shawn Webb .
+.Sh BUGS
+The existing gap-based stack randomization is not optimal.
+Mapping-base stack randomization is more robust, but hard-coded kernel
+structures and addresses, especially
+.Va PS_STRINGS
+, will need to be
+modified.
+The required changes to
+.Va PS_STRINGS
+are major and will likely touch
+userland along with the kernel.
+The original PaX implementation, from which the
+.Fx
+implementation is inspired, uses a special ELF process header which
+requires modification of executable files.
+The authors of the
+.Fx
+implementation have deliberately chosen to go a different route based
+on the
+.Xr mac 4
+framework.
+Support for filesystem extended attributes will be added at a later
+time.
Index: sys/amd64/amd64/elf_machdep.c
===================================================================
--- sys/amd64/amd64/elf_machdep.c
+++ sys/amd64/amd64/elf_machdep.c
@@ -26,12 +26,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
@@ -82,6 +85,7 @@
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
Index: sys/amd64/conf/GENERIC
===================================================================
--- sys/amd64/conf/GENERIC
+++ sys/amd64/conf/GENERIC
@@ -69,6 +69,8 @@
options CAPABILITY_MODE # Capsicum capability mode
options CAPABILITIES # Capsicum capabilities
options MAC # TrustedBSD MAC Framework
+#options PAX_ASLR # Address Space Layout Randomization
+#options PAX_SYSCTLS # Run-time settings for PAX and Hardening
options KDTRACE_FRAME # Ensure frames are compiled in
options KDTRACE_HOOKS # Kernel DTrace hooks
options DDB_CTF # Kernel ELF linker loads CTF data
Index: sys/amd64/include/vmparam.h
===================================================================
--- sys/amd64/include/vmparam.h
+++ sys/amd64/include/vmparam.h
@@ -178,7 +178,8 @@
#define VM_MAXUSER_ADDRESS UVADDR(NUPML4E, 0, 0, 0)
#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
-#define USRSTACK SHAREDPAGE
+#define SHAREDPAGE_GUARD (4 * PAGE_SIZE)
+#define USRSTACK (SHAREDPAGE - SHAREDPAGE_GUARD)
#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
#define VM_MIN_ADDRESS (0)
Index: sys/amd64/linux32/linux32_sysvec.c
===================================================================
--- sys/amd64/linux32/linux32_sysvec.c
+++ sys/amd64/linux32/linux32_sysvec.c
@@ -33,6 +33,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
+#include "opt_pax.h"
#ifndef COMPAT_FREEBSD32
#error "Unable to compile Linux-emulator due to missing COMPAT_FREEBSD32 option!"
@@ -51,6 +52,7 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
@@ -1037,6 +1039,7 @@
.sv_shared_page_base = LINUX32_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace32,
};
INIT_SYSENTVEC(elf_sysvec, &elf_linux_sysvec);
Index: sys/arm/arm/elf_machdep.c
===================================================================
--- sys/arm/arm/elf_machdep.c
+++ sys/arm/arm/elf_machdep.c
@@ -26,6 +26,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -34,6 +36,7 @@
#include <sys/linker.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
@@ -81,6 +84,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
static Elf32_Brandinfo freebsd_brand_info = {
Index: sys/arm/arm/machdep.c
===================================================================
--- sys/arm/arm/machdep.c
+++ sys/arm/arm/machdep.c
@@ -47,6 +47,7 @@
#include "opt_platform.h"
#include "opt_sched.h"
#include "opt_timer.h"
+#include "opt_pax.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -116,6 +117,10 @@
#include <ddb/ddb.h>
#endif
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
#ifdef DEBUG
#define debugf(fmt, args...) printf(fmt, ##args)
#else
@@ -281,6 +286,9 @@
tf->tf_pc = (register_t)catcher;
tf->tf_usr_sp = (register_t)fp;
tf->tf_usr_lr = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
+#ifdef PAX_ASLR
+ pax_aslr_stack(p, &tf->tf_usr_lr);
+#endif
CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr,
tf->tf_usr_sp);
Index: sys/compat/freebsd32/freebsd32_misc.c
===================================================================
--- sys/compat/freebsd32/freebsd32_misc.c
+++ sys/compat/freebsd32/freebsd32_misc.c
@@ -30,6 +30,7 @@
#include "opt_compat.h"
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_pax.h"
#define __ELF_WORD_SIZE 32
@@ -55,6 +56,7 @@
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/procctl.h>
#include <sys/reboot.h>
@@ -2801,6 +2803,10 @@
szsigcode = 0;
destp = (uintptr_t)arginfo;
+#ifdef PAX_ASLR
+ pax_aslr_stack(imgp->proc, &destp);
+#endif
+
/*
* install sigcode
*/
Index: sys/compat/ia32/ia32_sysvec.c
===================================================================
--- sys/compat/ia32/ia32_sysvec.c
+++ sys/compat/ia32/ia32_sysvec.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
+#include "opt_pax.h"
#define __ELF_WORD_SIZE 32
@@ -43,6 +44,7 @@
#include <sys/mman.h>
#include <sys/namei.h>
#include <sys/pioctl.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/procfs.h>
#include <sys/resourcevar.h>
@@ -136,6 +138,7 @@
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace32,
};
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
Index: sys/conf/NOTES
===================================================================
--- sys/conf/NOTES
+++ sys/conf/NOTES
@@ -2980,6 +2980,9 @@
# Module to enable execution of application via emulators like QEMU
options IMAGACT_BINMISC
+# Address Space Layout Randomization (ASLR)
+options PAX_ASLR # Address Space Layout Randomization
+options PAX_SYSCTLS # Run-time settings for PAX and Hardening
# zlib I/O stream support
# This enables support for compressed core dumps.
options GZIO
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3027,6 +3027,8 @@
kern/kern_mutex.c standard
kern/kern_ntptime.c standard
kern/kern_osd.c standard
+kern/kern_pax.c optional pax_aslr
+kern/kern_pax_aslr.c optional pax_aslr
kern/kern_physio.c standard
kern/kern_pmc.c standard
kern/kern_poll.c optional device_polling
Index: sys/conf/options
===================================================================
--- sys/conf/options
+++ sys/conf/options
@@ -931,6 +931,10 @@
# Resource Limits
RCTL opt_global.h
+# PaX - hardening options
+PAX_ASLR opt_pax.h
+PAX_SYSCTLS opt_pax.h
+
# Random number generator(s)
RANDOM_YARROW opt_random.h
RANDOM_FORTUNA opt_random.h
Index: sys/i386/i386/elf_machdep.c
===================================================================
--- sys/i386/i386/elf_machdep.c
+++ sys/i386/i386/elf_machdep.c
@@ -27,6 +27,7 @@
__FBSDID("$FreeBSD$");
#include "opt_cpu.h"
+#include "opt_pax.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -34,6 +35,7 @@
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
@@ -88,6 +90,7 @@
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/i386/ibcs2/ibcs2_sysvec.c
===================================================================
--- sys/i386/ibcs2/ibcs2_sysvec.c
+++ sys/i386/ibcs2/ibcs2_sysvec.c
@@ -31,6 +31,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -40,6 +42,7 @@
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/signalvar.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/sx.h>
@@ -89,6 +92,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
static int
Index: sys/i386/linux/linux_sysvec.c
===================================================================
--- sys/i386/linux/linux_sysvec.c
+++ sys/i386/linux/linux_sysvec.c
@@ -29,6 +29,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/exec.h>
@@ -41,6 +43,7 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
@@ -973,6 +976,7 @@
.sv_shared_page_base = LINUX_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
@@ -1011,6 +1015,7 @@
.sv_shared_page_base = LINUX_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
INIT_SYSENTVEC(elf_sysvec, &elf_linux_sysvec);
Index: sys/kern/imgact_aout.c
===================================================================
--- sys/kern/imgact_aout.c
+++ sys/kern/imgact_aout.c
@@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/imgact.h>
@@ -36,6 +38,7 @@
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
@@ -99,6 +102,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
#elif defined(__amd64__)
@@ -143,6 +147,7 @@
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace32,
};
#else
#error "Port me"
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -33,6 +33,7 @@
#include "opt_capsicum.h"
#include "opt_compat.h"
+#include "opt_pax.h"
#include "opt_gzio.h"
#include <sys/param.h>
@@ -50,6 +51,7 @@
#include <sys/mman.h>
#include <sys/namei.h>
#include <sys/pioctl.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/procfs.h>
#include <sys/racct.h>
@@ -796,16 +798,7 @@
if (hdr->e_type == ET_DYN) {
if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
return (ENOEXEC);
- /*
- * Honour the base load address from the dso if it is
- * non-zero for some reason.
- */
- if (baddr == 0)
- et_dyn_addr = ET_DYN_LOAD_ADDR;
- else
- et_dyn_addr = 0;
- } else
- et_dyn_addr = 0;
+ }
sv = brand_info->sysvec;
if (interp != NULL && brand_info->interp_newpath != NULL)
newinterp = brand_info->interp_newpath;
@@ -826,6 +819,20 @@
error = exec_new_vmspace(imgp, sv);
imgp->proc->p_sysent = sv;
+ et_dyn_addr = 0;
+ if (hdr->e_type == ET_DYN) {
+ /*
+ * Honour the base load address from the dso if it is
+ * non-zero for some reason.
+ */
+ if (baddr == 0) {
+ et_dyn_addr = ET_DYN_LOAD_ADDR;
+#ifdef PAX_ASLR
+ pax_aslr_execbase(imgp->proc, &et_dyn_addr);
+#endif
+ }
+ }
+
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
if (error)
return (error);
Index: sys/kern/init_main.c
===================================================================
--- sys/kern/init_main.c
+++ sys/kern/init_main.c
@@ -46,6 +46,7 @@
#include "opt_ddb.h"
#include "opt_init_path.h"
+#include "opt_pax.h"
#include "opt_verbose_sysinit.h"
#include <sys/param.h>
@@ -61,6 +62,7 @@
#include <sys/mutex.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
@@ -411,6 +413,7 @@
.sv_fetch_syscall_args = null_fetch_syscall_args,
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = NULL,
};
/*
@@ -478,6 +481,9 @@
p->p_flag = P_SYSTEM | P_INMEM;
p->p_flag2 = 0;
p->p_state = PRS_NORMAL;
+#if defined(PAX_ASLR)
+ p->p_pax = PAX_NOTE_ALL_DISABLED;
+#endif
knlist_init_mtx(&p->p_klist, &p->p_mtx);
STAILQ_INIT(&p->p_ktr);
p->p_nice = NZERO;
@@ -495,6 +501,9 @@
td->td_flags = TDF_INMEM;
td->td_pflags = TDP_KTHREAD;
td->td_cpuset = cpuset_thread0();
+#if defined(PAX_ASLR)
+ td->td_pax = PAX_NOTE_ALL_DISABLED;
+#endif
prison0_init();
p->p_peers = 0;
p->p_leader = p;
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -30,6 +30,7 @@
#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>
@@ -50,6 +51,7 @@
#include <sys/imgact_elf.h>
#include <sys/wait.h>
#include <sys/malloc.h>
+#include <sys/pax.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/pioctl.h>
@@ -65,6 +67,7 @@
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <sys/stat.h>
+#include <sys/jail.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -130,6 +133,10 @@
SYSCTL_INT(_security_bsd, OID_AUTO, map_at_zero, CTLFLAG_RWTUN, &map_at_zero, 0,
"Permit processes to map an object at virtual address 0.");
+#ifdef PAX_ASLR
+static int exec_check_aslr(struct image_params *imgp);
+#endif
+
static int
sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS)
{
@@ -383,6 +390,7 @@
imgp->proc = p;
imgp->attr = &attr;
imgp->args = args;
+ imgp->pax_flags = 0;
#ifdef MAC
error = mac_execve_enter(imgp, mac_p);
@@ -1045,6 +1053,10 @@
map = &vmspace->vm_map;
}
+#ifdef PAX_ASLR
+ pax_aslr_init(imgp);
+#endif
+
/* Map a shared page */
obj = sv->sv_shared_page_obj;
if (obj != NULL) {
@@ -1079,6 +1091,9 @@
*/
vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT;
vmspace->vm_maxsaddr = (char *)sv->sv_usrstack - ssiz;
+#ifdef PAX_ASLR
+ pax_aslr_stack_fixup(imgp->proc);
+#endif
return (0);
}
@@ -1246,6 +1261,9 @@
szsigcode = *(p->p_sysent->sv_szsigcode);
}
destp = (uintptr_t)arginfo;
+#ifdef PAX_ASLR
+ pax_aslr_stack(p, &destp);
+#endif
/*
* install sigcode
@@ -1366,6 +1384,38 @@
return (stack_base);
}
+#ifdef PAX_ASLR
+/*
+ * If we've disabled ASLR via ptrace, do not allow execution of
+ * setuid/setgid binaries.
+ */
+static int
+exec_check_aslr(struct image_params *imgp)
+{
+ struct proc *p = imgp->proc;
+ struct ucred *oldcred = p->p_ucred;
+ struct vattr *attr = imgp->attr;
+ int error, credential_changing;
+
+ credential_changing = 0;
+ credential_changing |= (attr->va_mode & S_ISUID) && oldcred->cr_uid !=
+ attr->va_uid;
+ credential_changing |= (attr->va_mode & S_ISGID) && oldcred->cr_gid !=
+ attr->va_gid;
+
+ if (credential_changing) {
+ if ((p->p_paxdebug & PAX_NOTE_NOASLR) == PAX_NOTE_NOASLR) {
+ if (pax_aslr_active(imgp->proc))
+ return (EPERM);
+ }
+ }
+
+ error = pax_elf(imgp, p->p_paxdebug);
+ return (error);
+}
+#endif /* PAX_ASLR */
+
+
/*
* Check permissions of file to execute.
* Called with imgp->vp locked.
@@ -1387,6 +1437,12 @@
if (error)
return (error);
+#if defined(PAX_ASLR)
+ error = exec_check_aslr(imgp);
+ if (error)
+ return (error);
+#endif
+
#ifdef MAC
error = mac_vnode_check_exec(td->td_ucred, imgp->vp, imgp);
if (error)
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -474,6 +474,7 @@
__rangeof(struct thread, td_startcopy, td_endcopy));
bcopy(&p2->p_comm, &td2->td_name, sizeof(td2->td_name));
+ td2->td_pax = p2->p_pax;
td2->td_sigstk = td->td_sigstk;
td2->td_flags = TDF_INMEM;
td2->td_lend_user_pri = PRI_MAX;
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c
+++ sys/kern/kern_jail.c
@@ -33,6 +33,7 @@
#include "opt_ddb.h"
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_pax.h"
#include <sys/param.h>
#include <sys/types.h>
@@ -42,6 +43,7 @@
#include <sys/sysproto.h>
#include <sys/malloc.h>
#include <sys/osd.h>
+#include <sys/pax.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/taskqueue.h>
@@ -250,6 +252,10 @@
prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset);
prison0.pr_osreldate = osreldate;
strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease));
+
+#ifdef PAX_ASLR
+ pax_init_prison(&prison0);
+#endif
}
#ifdef INET
@@ -1362,6 +1368,10 @@
goto done_releroot;
}
+#ifdef PAX_ASLR
+ pax_init_prison(pr);
+#endif
+
mtx_lock(&pr->pr_mtx);
/*
* New prisons do not yet have a reference, because we do not
Index: sys/kern/kern_pax.c
===================================================================
--- /dev/null
+++ sys/kern/kern_pax.c
@@ -0,0 +1,209 @@
+/*-
+ * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
+ * Copyright (c) 2013-2015, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
+ * Copyright (c) 2014-2015, by Shawn Webb <shawn.webb@hardenedbsd.org>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author 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 ``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 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$
+ *
+ * HardenedBSD-version: 2fba75c32739bd7f7c80163ec88e3655c3130753
+ * HardenedBSD-version: v16
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_pax.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/imgact.h>
+#include <sys/imgact_elf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/sysent.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/elf_common.h>
+#include <sys/mount.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 <sys/kthread.h>
+
+#include <sys/syslimits.h>
+#include <sys/param.h>
+
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <machine/elf.h>
+
+#include <sys/pax.h>
+
+static int pax_validate_flags(uint32_t flags);
+static int pax_check_conflicting_modes(uint32_t mode);
+
+SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
+ "PaX (exploit mitigation) features.");
+
+const char *pax_status_str[] = {
+ [PAX_FEATURE_DISABLED] = "disabled",
+ [PAX_FEATURE_OPTIN] = "opt-in",
+ [PAX_FEATURE_OPTOUT] = "opt-out",
+ [PAX_FEATURE_FORCE_ENABLED] = "force enabled",
+ [PAX_FEATURE_UNKNOWN_STATUS] = "UNKNOWN -> changed to \"force enabled\""
+};
+
+const char *pax_status_simple_str[] = {
+ [PAX_FEATURE_SIMPLE_DISABLED] = "disabled",
+ [PAX_FEATURE_SIMPLE_ENABLED] = "enabled"
+};
+
+struct prison *
+pax_get_prison(struct proc *p)
+{
+
+ /* p can be NULL with kernel threads, so use prison0 */
+ if (p == NULL || p->p_ucred == NULL)
+ return (&prison0);
+
+ return (p->p_ucred->cr_prison);
+}
+
+struct prison *
+pax_get_prison_td(struct thread *td)
+{
+
+ if (td == NULL || td->td_ucred == NULL)
+ return (&prison0);
+
+ return (td->td_ucred->cr_prison);
+}
+
+void
+pax_get_flags(struct proc *p, uint32_t *flags)
+{
+
+ *flags = p->p_pax;
+}
+
+void
+pax_get_flags_td(struct thread *td, uint32_t *flags)
+{
+
+ *flags = td->td_pax;
+}
+
+static int
+pax_validate_flags(uint32_t flags)
+{
+
+ if ((flags & ~PAX_NOTE_ALL) != 0)
+ return (1);
+
+ return (0);
+}
+
+static int
+pax_check_conflicting_modes(uint32_t mode)
+{
+
+ if (((mode & PAX_NOTE_ALL_ENABLED) & ((mode & PAX_NOTE_ALL_DISABLED) >> 1)) != 0)
+ return (1);
+
+ return (0);
+}
+
+int
+pax_elf(struct image_params *imgp, uint32_t mode)
+{
+ uint32_t flags, flags_aslr;
+
+ flags = mode;
+ flags_aslr = 0;
+
+ if (pax_validate_flags(flags) != 0) {
+ printf("%s: unknown paxflags: %x\n", __func__, flags);
+ return (ENOEXEC);
+ }
+
+ if (pax_check_conflicting_modes(mode) != 0) {
+ /*
+ * indicate flags inconsistencies in dmesg and in user terminal
+ */
+ printf("%s: inconsistent paxflags: %x\n", __func__, flags);
+ return (ENOEXEC);
+ }
+
+#ifdef PAX_ASLR
+ flags_aslr = pax_aslr_setup_flags(imgp, mode);
+#endif
+
+ flags = flags_aslr;
+
+ CTR3(KTR_PAX, "%s : flags = %x mode = %x",
+ __func__, flags, mode);
+
+ imgp->proc->p_pax = flags;
+
+ return (0);
+}
+
+
+/*
+ * print out PaX settings on boot time, and validate some of them
+ */
+static void
+pax_sysinit(void)
+{
+ if (bootverbose)
+ printf("pax: initialize and check PaX and HardeneBSD features.\n");
+}
+SYSINIT(pax, SI_SUB_PAX, SI_ORDER_FIRST, pax_sysinit, NULL);
+
+void
+pax_init_prison(struct prison *pr)
+{
+
+ CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
+ __func__, pr->pr_name);
+
+ pax_aslr_init_prison(pr);
+#ifdef COMPAT_FREEBSD32
+ pax_aslr_init_prison32(pr);
+#endif
+}
Index: sys/kern/kern_pax_aslr.c
===================================================================
--- /dev/null
+++ sys/kern/kern_pax_aslr.c
@@ -0,0 +1,877 @@
+/*-
+ * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
+ * Copyright (c) 2013-2015, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
+ * Copyright (c) 2014-2015, by Shawn Webb <shawn.webb@hardenedbsd.org>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author 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 ``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 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$
+ *
+ * HardenedBSD-version: 2fba75c32739bd7f7c80163ec88e3655c3130753
+ * HardenedBSD-version: v16
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_pax.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/imgact.h>
+#include <sys/imgact_elf.h>
+#include <sys/sysent.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/elf_common.h>
+#include <sys/mount.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 <sys/kthread.h>
+
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <machine/elf.h>
+
+#ifndef PAX_ASLR_DELTA
+#define PAX_ASLR_DELTA(delta, lsb, len) \
+ (((delta) & ((1UL << (len)) - 1)) << (lsb))
+#endif /* PAX_ASLR_DELTA */
+
+/*
+ * generic ASLR values
+ *
+ * MMAP | 32 bit | 64 bit | compat |
+ * +-------+--------+--------+--------+
+ * | MIN | 8 bit | 16 bit | 8 bit |
+ * +-------+--------+--------+--------+
+ * | DEF | 14 bit | 21 bit | 14 bit |
+ * +-------+--------+--------+--------+
+ * | MAX | 21 bit | 42 bit | 21 bit |
+ * +-------+--------+--------+--------+
+ *
+ * STACK | 32 bit | 64 bit | 32 bit |
+ * +-------+--------+--------+--------+
+ * | MIN | 8 bit | 16 bit | 8 bit |
+ * +-------+--------+--------+--------+
+ * | DEF | 8 bit | 16 bit | 8 bit |
+ * +-------+--------+--------+--------+
+ * | MAX | 21 bit | 42 bit | 21 bit |
+ * +-------+--------+--------+--------+
+ *
+ * EXEC | 32 bit | 64 bit | 32 bit |
+ * +-------+--------+--------+--------+
+ * | MIN | 8 bit | 16 bit | 8 bit |
+ * +-------+--------+--------+--------+
+ * | DEF | 14 bit | 16 bit | 14 bit |
+ * +-------+--------+--------+--------+
+ * | MAX | 21 bit | 42 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) / 3)
+#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) / 4)
+#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */
+
+#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN
+#define PAX_ASLR_DELTA_STACK_MAX_LEN (((sizeof(void *) * NBBY) * 2) / 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) / 4)
+#endif /* PAX_ASLR_DELTA_EXEC_MIN_LEN */
+
+#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN
+#define PAX_ASLR_DELTA_EXEC_MAX_LEN (((sizeof(void *) * NBBY) * 2) / 3)
+#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */
+
+/*
+ * ASLR default values for native host
+ */
+#ifdef __LP64__
+#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN
+#define PAX_ASLR_DELTA_MMAP_DEF_LEN 21
+#endif /* PAX_ASLR_DELTA_MMAP_DEF_LEN */
+#ifndef PAX_ASLR_DELTA_STACK_DEF_LEN
+#define PAX_ASLR_DELTA_STACK_DEF_LEN 16
+#endif /* PAX_ASLR_DELTA_STACK_DEF_LEN */
+#ifndef PAX_ASLR_DELTA_EXEC_DEF_LEN
+#define PAX_ASLR_DELTA_EXEC_DEF_LEN 16
+#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */
+#else /* ! __LP64__ */
+#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN
+#define PAX_ASLR_DELTA_MMAP_DEF_LEN 14
+#endif /* PAX_ASLR_DELTA_MMAP_DEF_LEN */
+#ifndef PAX_ASLR_DELTA_STACK_DEF_LEN
+#define PAX_ASLR_DELTA_STACK_DEF_LEN PAX_ASLR_DELTA_STACK_MIN_LEN
+#endif /* PAX_ASLR_DELTA_STACK_DEF_LEN */
+#ifndef PAX_ASLR_DELTA_EXEC_DEF_LEN
+#define PAX_ASLR_DELTA_EXEC_DEF_LEN 14
+#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */
+#endif /* __LP64__ */
+
+/*
+ * ASLR values for COMPAT_FREEBSD32, COMPAT_LINUX and MAP_32BIT
+ */
+#if defined(COMPAT_LINUX) || defined(COMPAT_FREEBSD32) || defined(MAP_32BIT)
+#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) / 3)
+#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) / 4)
+#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) * 2) / 3)
+#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */
+
+#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_LSB
+#define PAX_ASLR_COMPAT_DELTA_EXEC_LSB PAGE_SHIFT
+#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_LSB */
+
+#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN
+#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN ((sizeof(int) * NBBY) / 4)
+#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) * 2) / 3)
+#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */
+#endif
+
+FEATURE(aslr, "Address Space Layout Randomization.");
+
+static int pax_aslr_status = PAX_FEATURE_OPTOUT;
+static int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_DEF_LEN;
+static int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_DEF_LEN;
+static int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_DEF_LEN;
+
+#ifdef COMPAT_FREEBSD32
+static int pax_aslr_compat_status = PAX_FEATURE_OPTOUT;
+static int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
+static int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
+static int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
+#endif /* COMPAT_FREEBSD32 */
+
+TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status);
+TUNABLE_INT("security.pax.aslr.mmap_len", &pax_aslr_mmap_len);
+TUNABLE_INT("security.pax.aslr.stack_len", &pax_aslr_stack_len);
+TUNABLE_INT("security.pax.aslr.exec_len", &pax_aslr_exec_len);
+#ifdef COMPAT_FREEBSD32
+TUNABLE_INT("security.pax.aslr.compat.status", &pax_aslr_compat_status);
+TUNABLE_INT("security.pax.aslr.compat.mmap_len", &pax_aslr_compat_mmap_len);
+TUNABLE_INT("security.pax.aslr.compat.stack_len", &pax_aslr_compat_stack_len);
+TUNABLE_INT("security.pax.aslr.compat.exec_len", &pax_aslr_compat_exec_len);
+#endif
+
+#ifdef PAX_SYSCTLS
+SYSCTL_DECL(_security_pax);
+
+/*
+ * sysctls
+ */
+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);
+
+
+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_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_aslr_status, "I",
+ "Restrictions status. "
+ "0 - disabled, "
+ "1 - opt-in, "
+ "2 - opt-out, "
+ "3 - force enabled");
+
+SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_aslr_mmap, "I",
+ "Number of bits randomized for mmap(2) calls. "
+ "32 bit: [8,21] 64 bit: [16,42]");
+
+SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_aslr_stack, "I",
+ "Number of bits randomized for the stack. "
+ "32 bit: [8,21] 64 bit: [16,42]");
+
+SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_aslr_exec, "I",
+ "Number of bits randomized for the PIE exec base. "
+ "32 bit: [8,21] 64 bit: [16,42]");
+
+static int
+sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_pax_aslr_status;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || (req->newptr == NULL))
+ return (err);
+
+ switch (val) {
+ case PAX_FEATURE_DISABLED:
+ case PAX_FEATURE_OPTIN:
+ case PAX_FEATURE_OPTOUT:
+ case PAX_FEATURE_FORCE_ENABLED:
+ if (pr == &prison0)
+ pax_aslr_status = val;
+
+ pr->pr_hardening.hr_pax_aslr_status = val;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_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);
+
+ if (pr == &prison0)
+ pax_aslr_mmap_len = val;
+
+ pr->pr_hardening.hr_pax_aslr_mmap_len = val;
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_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);
+
+ if (pr == &prison0)
+ pax_aslr_stack_len = val;
+
+ pr->pr_hardening.hr_pax_aslr_stack_len = val;
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_pax_aslr_exec_len;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || (req->newptr == NULL))
+ return (err);
+
+ if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN ||
+ val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
+ return (EINVAL);
+
+ if (pr == &prison0)
+ pax_aslr_exec_len = val;
+
+ pr->pr_hardening.hr_pax_aslr_exec_len = val;
+
+ return (0);
+}
+
+/* COMPAT_FREEBSD32 and linuxulator. */
+#ifdef COMPAT_FREEBSD32
+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);
+
+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_RWTUN|CTLFLAG_PRISON,
+ NULL, 0, sysctl_pax_aslr_compat_status, "I",
+ "Restrictions status. "
+ "0 - disabled, "
+ "1 - enabled, "
+ "2 - global enabled, "
+ "3 - force global enabled");
+
+SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON,
+ NULL, 0, sysctl_pax_aslr_compat_mmap, "I",
+ "Number of bits randomized for mmap(2) calls. "
+ "32 bit: [8,16]");
+
+SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON,
+ NULL, 0, sysctl_pax_aslr_compat_stack, "I",
+ "Number of bits randomized for the stack. "
+ "32 bit: [8,16]");
+
+SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON,
+ NULL, 0, sysctl_pax_aslr_compat_exec, "I",
+ "Number of bits randomized for the PIE exec base. "
+ "32 bit: [8,16]");
+
+static int
+sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_pax_aslr_compat_status;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || (req->newptr == NULL))
+ return (err);
+
+ switch (val) {
+ case PAX_FEATURE_DISABLED:
+ case PAX_FEATURE_OPTIN:
+ case PAX_FEATURE_OPTOUT:
+ case PAX_FEATURE_FORCE_ENABLED:
+ if (pr == &prison0)
+ pax_aslr_compat_status = val;
+
+ pr->pr_hardening.hr_pax_aslr_compat_status = val;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_pax_aslr_compat_mmap_len;
+ 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);
+
+ if (pr == &prison0)
+ pax_aslr_compat_mmap_len = val;
+
+ pr->pr_hardening.hr_pax_aslr_compat_mmap_len = val;
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_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);
+
+ if (pr == &prison0)
+ pax_aslr_compat_stack_len = val;
+
+ pr->pr_hardening.hr_pax_aslr_compat_stack_len = val;
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison_td(req->td);
+
+ val = pr->pr_hardening.hr_pax_aslr_compat_exec_len;
+ 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);
+
+ if (pr == &prison0)
+ pax_aslr_compat_exec_len = val;
+
+ pr->pr_hardening.hr_pax_aslr_compat_exec_len = val;
+
+ return (0);
+}
+
+#endif /* COMPAT_FREEBSD32 */
+#endif /* PAX_SYSCTLS */
+
+
+/*
+ * ASLR functions
+ */
+
+static void
+pax_aslr_sysinit(void)
+{
+
+ switch (pax_aslr_status) {
+ case PAX_FEATURE_DISABLED:
+ case PAX_FEATURE_OPTIN:
+ case PAX_FEATURE_OPTOUT:
+ case PAX_FEATURE_FORCE_ENABLED:
+ break;
+ default:
+ printf("warning: invalid settings in loader.conf:"
+ " (pax_aslr_status = %d)\n", pax_aslr_status);
+ pax_aslr_status = PAX_FEATURE_FORCE_ENABLED;
+ break;
+ }
+ if (bootverbose) {
+ printf("PAX ASLR status: %s\n", pax_status_str[pax_aslr_status]);
+ printf("PAX ASLR mmap: %d bit\n", pax_aslr_mmap_len);
+ printf("PAX ASLR exec base: %d bit\n", pax_aslr_exec_len);
+ printf("PAX ASLR stack: %d bit\n", pax_aslr_stack_len);
+ }
+}
+SYSINIT(pax_aslr, SI_SUB_PAX, SI_ORDER_SECOND, pax_aslr_sysinit, NULL);
+
+int
+pax_aslr_active(struct proc *p)
+{
+ uint32_t flags;
+
+ pax_get_flags(p, &flags);
+
+ CTR3(KTR_PAX, "%s: pid = %d p_pax = %x",
+ __func__, p->p_pid, flags);
+
+ if ((flags & PAX_NOTE_ASLR) == PAX_NOTE_ASLR)
+ return (true);
+
+ if ((flags & PAX_NOTE_NOASLR) == PAX_NOTE_NOASLR)
+ return (false);
+
+ return (true);
+}
+
+void
+pax_aslr_init_vmspace(struct proc *p)
+{
+ struct prison *pr;
+ struct vmspace *vm;
+ unsigned long rand_buf;
+
+ vm = p->p_vmspace;
+
+ pr = pax_get_prison(p);
+ arc4rand(&rand_buf, sizeof(rand_buf), 0);
+ vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(rand_buf,
+ PAX_ASLR_DELTA_MMAP_LSB,
+ pr->pr_hardening.hr_pax_aslr_mmap_len);
+
+ arc4rand(&rand_buf, sizeof(rand_buf), 0);
+ vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(rand_buf,
+ PAX_ASLR_DELTA_STACK_LSB,
+ pr->pr_hardening.hr_pax_aslr_stack_len);
+ vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
+
+ arc4rand(&rand_buf, sizeof(rand_buf), 0);
+ vm->vm_aslr_delta_exec = PAX_ASLR_DELTA(rand_buf,
+ PAX_ASLR_DELTA_EXEC_LSB,
+ pr->pr_hardening.hr_pax_aslr_exec_len);
+
+ CTR2(KTR_PAX, "%s: vm_aslr_delta_mmap=%p\n",
+ __func__, (void *)vm->vm_aslr_delta_mmap);
+ CTR2(KTR_PAX, "%s: vm_aslr_delta_stack=%p\n",
+ __func__, (void *)vm->vm_aslr_delta_stack);
+ CTR2(KTR_PAX, "%s: vm_aslr_delta_exec=%p\n",
+ __func__, (void *)vm->vm_aslr_delta_exec);
+}
+
+#ifdef COMPAT_FREEBSD32
+static void
+pax_compat_aslr_sysinit(void)
+{
+
+ switch (pax_aslr_compat_status) {
+ case PAX_FEATURE_DISABLED:
+ case PAX_FEATURE_OPTIN:
+ case PAX_FEATURE_OPTOUT:
+ case PAX_FEATURE_FORCE_ENABLED:
+ break;
+ default:
+ printf("warning: invalid settings in loader.conf! "
+ "(pax_aslr_compat_status = %d)\n", pax_aslr_compat_status);
+ pax_aslr_compat_status = PAX_FEATURE_FORCE_ENABLED;
+ break;
+ }
+ if (bootverbose) {
+ printf("PAX ASLR (compat) status: %s\n", pax_status_str[pax_aslr_compat_status]);
+ printf("PAX ASLR (compat) mmap: %d bit\n", pax_aslr_compat_mmap_len);
+ printf("PAX ASLR (compat) exec base: %d bit\n", pax_aslr_compat_exec_len);
+ printf("PAX ASLR (compat) stack: %d bit\n", pax_aslr_compat_stack_len);
+ }
+}
+SYSINIT(pax_compat_aslr, SI_SUB_PAX, SI_ORDER_SECOND, pax_compat_aslr_sysinit, NULL);
+
+void
+pax_aslr_init_vmspace32(struct proc *p)
+{
+ struct prison *pr;
+ struct vmspace *vm;
+ long rand_buf;
+
+ vm = p->p_vmspace;
+
+ pr = pax_get_prison(p);
+ arc4rand(&rand_buf, sizeof(rand_buf), 0);
+ vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(rand_buf,
+ PAX_ASLR_COMPAT_DELTA_MMAP_LSB,
+ pr->pr_hardening.hr_pax_aslr_compat_mmap_len);
+
+ arc4rand(&rand_buf, sizeof(rand_buf), 0);
+ vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(rand_buf,
+ PAX_ASLR_COMPAT_DELTA_STACK_LSB,
+ pr->pr_hardening.hr_pax_aslr_compat_stack_len);
+ vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
+
+ arc4rand(&rand_buf, sizeof(rand_buf), 0);
+ vm->vm_aslr_delta_exec = PAX_ASLR_DELTA(rand_buf,
+ PAX_ASLR_COMPAT_DELTA_EXEC_LSB,
+ pr->pr_hardening.hr_pax_aslr_compat_exec_len);
+
+ CTR2(KTR_PAX, "%s: vm_aslr_delta_mmap=%p\n",
+ __func__, (void *)vm->vm_aslr_delta_mmap);
+ CTR2(KTR_PAX, "%s: vm_aslr_delta_stack=%p\n",
+ __func__, (void *)vm->vm_aslr_delta_stack);
+ CTR2(KTR_PAX, "%s: vm_aslr_delta_exec=%p\n",
+ __func__, (void *)vm->vm_aslr_delta_exec);
+}
+#endif
+
+void
+pax_aslr_init(struct image_params *imgp)
+{
+ struct proc *p;
+
+ p = imgp->proc;
+
+ if (!pax_aslr_active(p))
+ return;
+
+ if (imgp->sysent->sv_pax_aslr_init != NULL)
+ imgp->sysent->sv_pax_aslr_init(p);
+}
+
+void
+pax_aslr_init_prison(struct prison *pr)
+{
+ struct prison *pr_p;
+
+ CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
+ __func__, pr->pr_name);
+
+ if (pr == &prison0) {
+ /* prison0 has no parent, use globals */
+ pr->pr_hardening.hr_pax_aslr_status = pax_aslr_status;
+ pr->pr_hardening.hr_pax_aslr_mmap_len =
+ pax_aslr_mmap_len;
+ pr->pr_hardening.hr_pax_aslr_stack_len =
+ pax_aslr_stack_len;
+ pr->pr_hardening.hr_pax_aslr_exec_len =
+ pax_aslr_exec_len;
+ } else {
+ KASSERT(pr->pr_parent != NULL,
+ ("%s: pr->pr_parent == NULL", __func__));
+ pr_p = pr->pr_parent;
+
+ pr->pr_hardening.hr_pax_aslr_status =
+ pr_p->pr_hardening.hr_pax_aslr_status;
+ pr->pr_hardening.hr_pax_aslr_mmap_len =
+ pr_p->pr_hardening.hr_pax_aslr_mmap_len;
+ pr->pr_hardening.hr_pax_aslr_stack_len =
+ pr_p->pr_hardening.hr_pax_aslr_stack_len;
+ pr->pr_hardening.hr_pax_aslr_exec_len =
+ pr_p->pr_hardening.hr_pax_aslr_exec_len;
+ }
+}
+
+#ifdef COMPAT_FREEBSD32
+void
+pax_aslr_init_prison32(struct prison *pr)
+{
+ struct prison *pr_p;
+
+ CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
+ __func__, pr->pr_name);
+
+ if (pr == &prison0) {
+ /* prison0 has no parent, use globals */
+
+ pr->pr_hardening.hr_pax_aslr_compat_status =
+ pax_aslr_compat_status;
+ pr->pr_hardening.hr_pax_aslr_compat_mmap_len =
+ pax_aslr_compat_mmap_len;
+ pr->pr_hardening.hr_pax_aslr_compat_stack_len =
+ pax_aslr_compat_stack_len;
+ pr->pr_hardening.hr_pax_aslr_compat_exec_len =
+ pax_aslr_compat_exec_len;
+ } else {
+ KASSERT(pr->pr_parent != NULL,
+ ("%s: pr->pr_parent == NULL", __func__));
+ pr_p = pr->pr_parent;
+
+ pr->pr_hardening.hr_pax_aslr_compat_status =
+ pr_p->pr_hardening.hr_pax_aslr_compat_status;
+ pr->pr_hardening.hr_pax_aslr_compat_mmap_len =
+ pr_p->pr_hardening.hr_pax_aslr_compat_mmap_len;
+ pr->pr_hardening.hr_pax_aslr_compat_stack_len =
+ pr_p->pr_hardening.hr_pax_aslr_compat_stack_len;
+ pr->pr_hardening.hr_pax_aslr_compat_exec_len =
+ pr_p->pr_hardening.hr_pax_aslr_compat_exec_len;
+ }
+}
+#endif /* COMPAT_FREEBSD32 */
+
+void
+pax_aslr_mmap(struct proc *p, vm_offset_t *addr, vm_offset_t orig_addr, int flags)
+{
+
+ if (!pax_aslr_active(p))
+ return;
+
+ if (!(flags & MAP_FIXED) && ((orig_addr == 0) || !(flags & MAP_ANON))) {
+ CTR4(KTR_PAX, "%s: applying to %p orig_addr=%p flags=%x\n",
+ __func__, (void *)*addr, (void *)orig_addr, flags);
+
+#ifdef MAP_32BIT
+ if (flags & MAP_32BIT) {
+ int len_32bit;
+
+#ifdef COMPAT_FREEBSD32
+ len_32bit = pax_aslr_compat_mmap_len;
+#else
+ len_32bit = PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
+#endif
+ *addr += PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_COMPAT_DELTA_MMAP_LSB,
+ len_32bit);
+ } else
+#endif /* MAP_32BIT */
+ *addr += p->p_vmspace->vm_aslr_delta_mmap;
+ CTR2(KTR_PAX, "%s: result %p\n", __func__, (void *)*addr);
+ } else
+ CTR4(KTR_PAX, "%s: not applying to %p orig_addr=%p flags=%x\n",
+ __func__, (void *)*addr, (void *)orig_addr, flags);
+}
+
+void
+pax_aslr_stack(struct proc *p, uintptr_t *addr)
+{
+ uintptr_t orig_addr;
+
+ if (!pax_aslr_active(p))
+ return;
+
+ orig_addr = *addr;
+ *addr -= p->p_vmspace->vm_aslr_delta_stack;
+ CTR3(KTR_PAX, "%s: orig_addr=%p, new_addr=%p\n",
+ __func__, (void *)orig_addr, (void *)*addr);
+}
+
+void
+pax_aslr_stack_fixup(struct proc *p)
+{
+
+ if (!pax_aslr_active(p))
+ return;
+
+ p->p_vmspace->vm_maxsaddr -= p->p_vmspace->vm_aslr_delta_stack;
+}
+
+void
+pax_aslr_execbase(struct proc *p, u_long *et_dyn_addr)
+{
+
+ if (!pax_aslr_active(p))
+ return;
+
+ *et_dyn_addr += p->p_vmspace->vm_aslr_delta_exec;
+}
+
+uint32_t
+pax_aslr_setup_flags(struct image_params *imgp, uint32_t mode)
+{
+ struct prison *pr;
+ uint32_t flags, status;
+
+ flags = 0;
+ status = 0;
+
+ pr = pax_get_prison(imgp->proc);
+ status = pr->pr_hardening.hr_pax_aslr_status;
+
+ if (status == PAX_FEATURE_DISABLED) {
+ flags &= ~PAX_NOTE_ASLR;
+ flags |= PAX_NOTE_NOASLR;
+
+ return (flags);
+ }
+
+ if (status == PAX_FEATURE_FORCE_ENABLED) {
+ flags |= PAX_NOTE_ASLR;
+ flags &= ~PAX_NOTE_NOASLR;
+
+ return (flags);
+ }
+
+ if (status == PAX_FEATURE_OPTIN) {
+ if (mode & PAX_NOTE_ASLR) {
+ flags |= PAX_NOTE_ASLR;
+ flags &= ~PAX_NOTE_NOASLR;
+ } else {
+ flags &= ~PAX_NOTE_ASLR;
+ flags |= PAX_NOTE_NOASLR;
+ }
+
+ return (flags);
+ }
+
+ if (status == PAX_FEATURE_OPTOUT) {
+ if (mode & PAX_NOTE_NOASLR) {
+ flags &= ~PAX_NOTE_ASLR;
+ flags |= PAX_NOTE_NOASLR;
+ } else {
+ flags |= PAX_NOTE_ASLR;
+ flags &= ~PAX_NOTE_NOASLR;
+ }
+
+ return (flags);
+ }
+
+ /*
+ * unknown status, force ASLR
+ */
+ flags |= PAX_NOTE_ASLR;
+ flags &= ~PAX_NOTE_NOASLR;
+
+ return (flags);
+}
+
Index: sys/kern/kern_thr.c
===================================================================
--- sys/kern/kern_thr.c
+++ sys/kern/kern_thr.c
@@ -254,6 +254,7 @@
td->td_proc->p_flag |= P_HADTHREADS;
thread_link(newtd, p);
bcopy(p->p_comm, newtd->td_name, sizeof(newtd->td_name));
+ newtd->td_pax = p->p_pax;
thread_lock(td);
/* let the scheduler know about these things. */
sched_fork_thread(td, newtd);
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
+#include "opt_pax.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -41,6 +42,7 @@
#include <sys/syscallsubr.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
+#include <sys/pax.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/vnode.h>
@@ -651,6 +653,7 @@
/* Lock proctree before locking the process. */
switch (req) {
+ case PT_PAX:
case PT_TRACE_ME:
case PT_ATTACH:
case PT_STEP:
@@ -668,7 +671,7 @@
}
write = 0;
- if (req == PT_TRACE_ME) {
+ if (req == PT_TRACE_ME || req == PT_PAX) {
p = td->td_proc;
PROC_LOCK(p);
} else {
@@ -735,6 +738,15 @@
* Permissions check
*/
switch (req) {
+ case PT_PAX:
+ /* securelevel should be 0 to allow this */
+ if ((data & PAX_NOTE_NOASLR) == PAX_NOTE_NOASLR) {
+ if (securelevel_gt(p->p_ucred, 0) != 0) {
+ error = EPERM;
+ goto fail;
+ }
+ }
+ break;
case PT_TRACE_ME:
/* Always legal. */
break;
@@ -820,6 +832,9 @@
td->td_retval[0] = 0;
switch (req) {
+ case PT_PAX:
+ p->p_paxdebug = data;
+ break;
case PT_TRACE_ME:
/* set my trace flag and "owner" so it can read/write me */
p->p_flag |= P_TRACED;
Index: sys/mips/mips/elf_machdep.c
===================================================================
--- sys/mips/mips/elf_machdep.c
+++ sys/mips/mips/elf_machdep.c
@@ -28,6 +28,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -36,6 +38,7 @@
#include <sys/linker.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
@@ -83,6 +86,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
static Elf64_Brandinfo freebsd_brand_info = {
@@ -139,6 +143,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace32,
};
static Elf32_Brandinfo freebsd_brand_info = {
Index: sys/mips/mips/freebsd32_machdep.c
===================================================================
--- sys/mips/mips/freebsd32_machdep.c
+++ sys/mips/mips/freebsd32_machdep.c
@@ -31,6 +31,7 @@
*/
#include "opt_compat.h"
+#include "opt_pax.h"
#define __ELF_WORD_SIZE 32
@@ -45,6 +46,7 @@
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
+#include <sys/pax.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -106,6 +108,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace32,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/powerpc/powerpc/elf32_machdep.c
===================================================================
--- sys/powerpc/powerpc/elf32_machdep.c
+++ sys/powerpc/powerpc/elf32_machdep.c
@@ -25,6 +25,8 @@
* $FreeBSD$
*/
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -34,6 +36,7 @@
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/malloc.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
@@ -108,6 +111,7 @@
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace32,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/powerpc/powerpc/elf64_machdep.c
===================================================================
--- sys/powerpc/powerpc/elf64_machdep.c
+++ sys/powerpc/powerpc/elf64_machdep.c
@@ -25,12 +25,15 @@
* $FreeBSD$
*/
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/malloc.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
@@ -84,6 +87,7 @@
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
Index: sys/sparc64/sparc64/elf_machdep.c
===================================================================
--- sys/sparc64/sparc64/elf_machdep.c
+++ sys/sparc64/sparc64/elf_machdep.c
@@ -34,12 +34,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/pax.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
@@ -87,6 +90,7 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = pax_aslr_init_vmspace,
};
static Elf64_Brandinfo freebsd_brand_info = {
Index: sys/sys/imgact.h
===================================================================
--- sys/sys/imgact.h
+++ sys/sys/imgact.h
@@ -80,6 +80,7 @@
unsigned long pagesizes;
int pagesizeslen;
vm_prot_t stack_prot;
+ int pax_flags;
};
#ifdef _KERNEL
Index: sys/sys/jail.h
===================================================================
--- sys/sys/jail.h
+++ sys/sys/jail.h
@@ -30,6 +30,10 @@
#ifndef _SYS_JAIL_H_
#define _SYS_JAIL_H_
+#if defined(_KERNEL) || defined(_WANT_PRISON)
+#include <sys/pax.h>
+#endif
+
#ifdef _KERNEL
struct jail_v0 {
u_int32_t version;
@@ -186,6 +190,7 @@
char pr_hostname[MAXHOSTNAMELEN]; /* (p) jail hostname */
char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */
char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */
+ struct hardening_features pr_hardening; /* (p) PaX-inspired hardening features */
char pr_osrelease[OSRELEASELEN]; /* (c) kern.osrelease value */
};
Index: sys/sys/kernel.h
===================================================================
--- sys/sys/kernel.h
+++ sys/sys/kernel.h
@@ -102,6 +102,7 @@
SI_SUB_WITNESS = 0x1A80000, /* witness initialization */
SI_SUB_MTX_POOL_DYNAMIC = 0x1AC0000, /* dynamic mutex pool */
SI_SUB_LOCK = 0x1B00000, /* various locks */
+ SI_SUB_PAX = 0x1B80000, /* pax setup */
SI_SUB_EVENTHANDLER = 0x1C00000, /* eventhandler init */
SI_SUB_VNET_PRELINK = 0x1E00000, /* vnet init before modules */
SI_SUB_KLD = 0x2000000, /* KLD and module setup */
Index: sys/sys/ktr_class.h
===================================================================
--- sys/sys/ktr_class.h
+++ sys/sys/ktr_class.h
@@ -71,7 +71,8 @@
#define KTR_INET6 0x10000000 /* IPv6 stack */
#define KTR_SCHED 0x20000000 /* Machine parsed sched info. */
#define KTR_BUF 0x40000000 /* Buffer cache */
-#define KTR_ALL 0x7fffffff
+#define KTR_PAX 0x80000000 /* PaX */
+#define KTR_ALL 0xffffffff
/* KTR trace classes to compile in */
#ifdef KTR
Index: sys/sys/pax.h
===================================================================
--- /dev/null
+++ sys/sys/pax.h
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
+ * Copyright (c) 2013-2015, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
+ * Copyright (c) 2014-2015, by Shawn Webb <shawn.webb@hardenedbsd.org>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author 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 ``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 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$
+ *
+ * HardenedBSD-version: 2fba75c32739bd7f7c80163ec88e3655c3130753
+ * HardenedBSD-version: v16
+ *
+ */
+
+#ifndef __SYS_PAX_H
+#define __SYS_PAX_H
+
+#if defined(_KERNEL) || defined(_WANT_PRISON)
+struct hardening_features {
+ int hr_pax_aslr_status; /* (p) PaX ASLR enabled */
+ int hr_pax_aslr_mmap_len; /* (p) Number of bits randomized with mmap */
+ int hr_pax_aslr_stack_len; /* (p) Number of bits randomized with stack */
+ int hr_pax_aslr_exec_len; /* (p) Number of bits randomized with the execbase */
+ int hr_pax_aslr_compat_status; /* (p) PaX ASLR enabled (compat32) */
+ int hr_pax_aslr_compat_mmap_len; /* (p) Number of bits randomized with mmap (compat32) */
+ int hr_pax_aslr_compat_stack_len; /* (p) Number of bits randomized with stack (compat32) */
+ int hr_pax_aslr_compat_exec_len; /* (p) Number of bits randomized with the execbase (compat32) */
+};
+#endif
+
+#ifdef _KERNEL
+#ifdef PAX_ASLR
+struct image_params;
+struct prison;
+struct thread;
+struct proc;
+struct vnode;
+struct vm_offset_t;
+
+/*
+ * used in sysctl handler
+ */
+#define PAX_FEATURE_DISABLED 0
+#define PAX_FEATURE_OPTIN 1
+#define PAX_FEATURE_OPTOUT 2
+#define PAX_FEATURE_FORCE_ENABLED 3
+#define PAX_FEATURE_UNKNOWN_STATUS 4
+
+extern const char *pax_status_str[];
+
+#define PAX_FEATURE_SIMPLE_DISABLED 0
+#define PAX_FEATURE_SIMPLE_ENABLED 1
+
+extern const char *pax_status_simple_str[];
+
+/*
+ * generic pax functions
+ */
+int pax_elf(struct image_params *, uint32_t);
+void pax_get_flags(struct proc *p, uint32_t *flags);
+void pax_get_flags_td(struct thread *td, uint32_t *flags);
+struct prison *pax_get_prison(struct proc *p);
+struct prison *pax_get_prison_td(struct thread *td);
+void pax_init_prison(struct prison *pr);
+
+/*
+ * ASLR related functions
+ */
+int pax_aslr_active(struct proc *p);
+
+void pax_aslr_init_vmspace(struct proc *p);
+void pax_aslr_init_vmspace32(struct proc *p);
+void pax_aslr_init_prison(struct prison *pr);
+void pax_aslr_init_prison32(struct prison *pr);
+void pax_aslr_init(struct image_params *imgp);
+void pax_aslr_execbase(struct proc *p, u_long *et_dyn_addr);
+void pax_aslr_mmap(struct proc *p, vm_offset_t *addr,
+ vm_offset_t orig_addr, int flags);
+uint32_t pax_aslr_setup_flags(struct image_params *imgp, uint32_t mode);
+void pax_aslr_stack(struct proc *p, uintptr_t *addr);
+void pax_aslr_stack_fixup(struct proc *p);
+
+#else /* PAX_ASLR */
+
+#define pax_aslr_init_vmspace NULL
+#define pax_aslr_init_vmspace32 NULL
+#define pax_aslr_init_prison(pr) do {} while (0)
+#define pax_aslr_init_prison32(pr) do {} while (0)
+
+#endif /* PAX_ASLR */
+
+/*
+ * Keep these values to keep compatibility with HardenedBSD
+ */
+#define PAX_NOTE_ASLR 0x00000040
+#define PAX_NOTE_NOASLR 0x00000080
+
+#define PAX_NOTE_ALL_ENABLED (PAX_NOTE_ASLR)
+#define PAX_NOTE_ALL_DISABLED (PAX_NOTE_NOASLR)
+#define PAX_NOTE_ALL (PAX_NOTE_ALL_ENABLED | PAX_NOTE_ALL_DISABLED)
+
+#endif /* _KERNEL */
+
+#endif /* __SYS_PAX_H */
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -288,6 +288,7 @@
u_char td_pri_class; /* (t) Scheduling class. */
u_char td_user_pri; /* (t) User pri from estcpu and nice. */
u_char td_base_user_pri; /* (t) Base user pri */
+ uint32_t td_pax; /* (b) cached PaX settings from process */
#define td_endcopy td_pcb
/*
@@ -578,6 +579,8 @@
pid_t p_reapsubtree; /* (e) Pid of the direct child of the
reaper which spawned
our subtree. */
+ u_int p_pax; /* (b) PaX is enabled to this process */
+ u_int p_paxdebug; /* (b) PaX flags set via PTrace */
/* End area that is copied on creation. */
#define p_endcopy p_xstat
Index: sys/sys/ptrace.h
===================================================================
--- sys/sys/ptrace.h
+++ sys/sys/ptrace.h
@@ -76,6 +76,7 @@
#define PT_VM_ENTRY 41 /* Get VM map (entry) */
#define PT_FIRSTMACH 64 /* for machine-specific requests */
+#define PT_PAX 65 /* Toggle PaX-inspired hardening features */
#include <machine/ptrace.h> /* machine-specific requests, if any */
struct ptrace_io_desc {
Index: sys/sys/sysent.h
===================================================================
--- sys/sys/sysent.h
+++ sys/sys/sysent.h
@@ -38,6 +38,7 @@
struct sysent;
struct thread;
struct ksiginfo;
+struct proc;
typedef int sy_call_t(struct thread *, void *);
@@ -136,6 +137,7 @@
uint32_t sv_timekeep_gen;
void *sv_shared_page_obj;
void (*sv_schedtail)(struct thread *);
+ void (*sv_pax_aslr_init)(struct proc *p);
};
#define SV_ILP32 0x000100
Index: sys/vm/vm_map.h
===================================================================
--- sys/vm/vm_map.h
+++ sys/vm/vm_map.h
@@ -241,6 +241,9 @@
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_offset_t vm_aslr_delta_mmap; /* mmap() random delta for ASLR */
+ vm_offset_t vm_aslr_delta_stack; /* stack random delta for ASLR */
+ vm_offset_t vm_aslr_delta_exec; /* exec base random delta for ASLR */
volatile int vm_refcnt; /* number of references */
/*
* Keep the PMAP last, so that CPU-specific variations of that
Index: sys/vm/vm_map.c
===================================================================
--- sys/vm/vm_map.c
+++ 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>
@@ -297,6 +299,12 @@
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;
+ vm->vm_aslr_delta_exec = 0;
+#endif
+
return (vm);
}
@@ -3260,6 +3268,11 @@
vm2->vm_taddr = vm1->vm_taddr;
vm2->vm_daddr = vm1->vm_daddr;
vm2->vm_maxsaddr = vm1->vm_maxsaddr;
+#ifdef PAX_ASLR
+ vm2->vm_aslr_delta_exec = vm1->vm_aslr_delta_exec;
+ vm2->vm_aslr_delta_mmap = vm1->vm_aslr_delta_mmap;
+ vm2->vm_aslr_delta_stack = vm1->vm_aslr_delta_stack;
+#endif
vm_map_lock(old_map);
if (old_map->busy)
vm_map_wait_busy(old_map);
Index: sys/vm/vm_mmap.c
===================================================================
--- sys/vm/vm_mmap.c
+++ sys/vm/vm_mmap.c
@@ -45,6 +45,7 @@
#include "opt_compat.h"
#include "opt_hwpmc_hooks.h"
+#include "opt_pax.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -54,6 +55,7 @@
#include <sys/mutex.h>
#include <sys/sysproto.h>
#include <sys/filedesc.h>
+#include <sys/pax.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/procctl.h>
@@ -439,6 +441,9 @@
td->td_fpop = fp;
maxprot &= cap_maxprot;
+#ifdef PAX_ASLR
+ pax_aslr_mmap(td->td_proc, &addr, (vm_offset_t)uap->addr, flags);
+#endif
/* This relies on VM_PROT_* matching PROT_*. */
error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
flags, handle_type, handle, pos);

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 18, 2:01 PM (1 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14249938
Default Alt Text
D473.id4321.diff (70 KB)

Event Timeline