Page MenuHomeFreeBSD

D473.1789425410.diff
No OneTemporary

Size
63 KB
Referenced Files
None
Subscribers
None

D473.1789425410.diff

Index: sys/amd64/amd64/elf_machdep.c
===================================================================
--- sys/amd64/amd64/elf_machdep.c
+++ sys/amd64/amd64/elf_machdep.c
@@ -26,12 +26,17 @@
#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>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
@@ -81,6 +86,11 @@
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
Index: sys/amd64/include/vmparam.h
===================================================================
--- sys/amd64/include/vmparam.h
+++ sys/amd64/include/vmparam.h
@@ -170,7 +170,7 @@
#define VM_MAXUSER_ADDRESS UVADDR(NUPML4E, 0, 0, 0)
#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
-#define USRSTACK SHAREDPAGE
+#define USRSTACK (SHAREDPAGE - 4*PAGE_SIZE)
#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
#define VM_MIN_ADDRESS (0)
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!"
@@ -84,6 +85,10 @@
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
MODULE_VERSION(linux, 1);
MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
@@ -1037,6 +1042,11 @@
.sv_shared_page_base = LINUX32_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init32,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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>
@@ -46,6 +48,10 @@
#include <machine/elf.h>
#include <machine/md_var.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
struct sysentvec elf32_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
.sv_table = sysent,
@@ -79,6 +85,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
static Elf32_Brandinfo freebsd_brand_info = {
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
@@ -113,6 +114,10 @@
FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
#ifndef __mips__
CTASSERT(sizeof(struct timeval32) == 8);
CTASSERT(sizeof(struct timespec32) == 8);
@@ -2766,6 +2771,10 @@
szsigcode = 0;
destp = (uintptr_t)arginfo;
+#ifdef PAX_ASLR
+ pax_aslr_stack(curthread, &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
@@ -74,6 +75,10 @@
#include <machine/pcb.h>
#include <machine/cpufunc.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
CTASSERT(sizeof(struct ia32_mcontext) == 640);
CTASSERT(sizeof(struct ia32_ucontext) == 704);
CTASSERT(sizeof(struct ia32_sigframe) == 800);
@@ -136,6 +141,11 @@
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init32,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
Index: sys/conf/NOTES
===================================================================
--- sys/conf/NOTES
+++ sys/conf/NOTES
@@ -2986,3 +2986,7 @@
# Module to enable execution of application via emulators like QEMU
options IMAGACT_BINMISC
+
+# Address Space Layout Randomization (ASLR)
+options PAX_ASLR
+options PAX_SYSCTLS
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2910,6 +2910,9 @@
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_pax_log.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
@@ -920,6 +920,12 @@
# Resource Limits
RCTL opt_global.h
+# PaX - hardening options
+PAX_ASLR opt_pax.h
+PAX_ASLR_MAX_SEC opt_pax.h
+PAX_MPROTECT 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
@@ -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>
@@ -46,6 +48,10 @@
#include <machine/elf.h>
#include <machine/md_var.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
struct sysentvec elf32_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
.sv_table = sysent,
@@ -81,6 +87,11 @@
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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>
@@ -50,6 +52,10 @@
#include <i386/ibcs2/ibcs2_syscall.h>
#include <i386/ibcs2/ibcs2_signal.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
MODULE_VERSION(ibcs2, 1);
extern int bsd_to_ibcs2_errno[];
@@ -89,6 +95,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init, /* XXXOP */
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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>
@@ -72,6 +74,10 @@
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
MODULE_VERSION(linux, 1);
MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
@@ -974,6 +980,11 @@
.sv_shared_page_base = LINUX_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init, /* XXXOP */
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
@@ -1012,6 +1023,11 @@
.sv_shared_page_base = LINUX_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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>
@@ -62,6 +64,10 @@
#include <compat/ia32/ia32_signal.h>
#endif
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
static int exec_aout_imgact(struct image_params *imgp);
static int aout_fixup(register_t **stack_base, struct image_params *imgp);
@@ -99,6 +105,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init, /* XXXOP */
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
#elif defined(__amd64__)
@@ -143,6 +154,11 @@
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init32, /* XXXOP */
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
#else
#error "Port me"
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -34,6 +34,7 @@
#include "opt_capsicum.h"
#include "opt_compat.h"
#include "opt_core.h"
+#include "opt_pax.h"
#include <sys/param.h>
#include <sys/capsicum.h>
@@ -48,6 +49,7 @@
#include <sys/mman.h>
#include <sys/namei.h>
#include <sys/pioctl.h>
+#include <sys/jail.h>
#include <sys/proc.h>
#include <sys/procfs.h>
#include <sys/racct.h>
@@ -81,6 +83,10 @@
#include <machine/elf.h>
#include <machine/md_var.h>
+#if defined(PAX_ASLR)
+#include <sys/pax.h>
+#endif
+
#define ELF_NOTE_ROUNDSIZE 4
#define OLD_EI_BRAND 8
@@ -653,16 +659,16 @@
hdr = (const Elf_Ehdr *)imgp->image_header;
if ((error = __elfN(check_header)(hdr)) != 0)
goto fail;
- if (hdr->e_type == ET_DYN)
+ if (hdr->e_type == ET_DYN) {
rbase = *addr;
- else if (hdr->e_type == ET_EXEC)
+ } else if (hdr->e_type == ET_EXEC) {
rbase = 0;
- else {
+ } else {
error = ENOEXEC;
goto fail;
}
- /* Only support headers that fit within first page for now */
+ /* Only support headers that fit within first page for now */
if ((hdr->e_phoff > PAGE_SIZE) ||
(u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) {
error = ENOEXEC;
@@ -787,16 +793,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;
@@ -817,6 +814,21 @@
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
+ if (pax_aslr_active(NULL, imgp->proc))
+ et_dyn_addr += imgp->proc->p_vmspace->vm_aslr_delta_exec;
+#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
@@ -410,6 +410,7 @@
.sv_fetch_syscall_args = null_fetch_syscall_args,
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
+ .sv_pax_aslr_init = NULL,
};
/*
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>
@@ -93,6 +94,10 @@
dtrace_execexit_func_t dtrace_fasttrap_exec;
#endif
+#if defined(PAX_ASLR)
+#include <sys/pax.h>
+#endif
+
SDT_PROVIDER_DECLARE(proc);
SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
@@ -402,6 +407,11 @@
imgp->pagesizes = 0;
imgp->pagesizeslen = 0;
imgp->stack_prot = 0;
+ imgp->pax_flags = 0;
+
+#if defined(PAX_MPROTECT) || defined(PAX_ASLR)
+ pax_elf(imgp, 0);
+#endif
#ifdef MAC
error = mac_execve_enter(imgp, mac_p);
@@ -1065,6 +1075,10 @@
map = &vmspace->vm_map;
}
+#ifdef PAX_ASLR
+ pax_aslr_init(curthread, imgp);
+#endif
+
/* Map a shared page */
obj = sv->sv_shared_page_obj;
if (obj != NULL) {
@@ -1099,6 +1113,9 @@
*/
vmspace->vm_ssize = sgrowsiz >> PAGE_SHIFT;
vmspace->vm_maxsaddr = (char *)sv->sv_usrstack - ssiz;
+#ifdef PAX_ASLR
+ vmspace->vm_maxsaddr -= vmspace->vm_aslr_delta_stack;
+#endif
return (0);
}
@@ -1258,6 +1275,9 @@
szsigcode = *(p->p_sysent->sv_szsigcode);
}
destp = (uintptr_t)arginfo;
+#ifdef PAX_ASLR
+ pax_aslr_stack(curthread, &destp);
+#endif
/*
* install sigcode
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -513,6 +513,11 @@
}
/*
+ * XXXOP: this is the right place?
+ */
+ p2->p_pax = p1->p_pax;
+
+ /*
* p_limit is copy-on-write. Bump its refcount.
*/
lim_fork(p1, p2);
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>
@@ -74,6 +75,10 @@
#endif /* INET6 */
#endif /* DDB */
+#if defined(PAX_ASLR)
+#include <sys/pax.h>
+#endif
+
#include <security/mac/mac_framework.h>
#define DEFAULT_HOSTUUID "00000000-0000-0000-0000-000000000000"
@@ -117,6 +122,10 @@
};
MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
+#if defined(PAX_ASLR)
+SYSINIT(pax, SI_SUB_PAX, SI_ORDER_MIDDLE, pax_init_prison, (void *) &prison0);
+#endif
+
/* allprison, allprison_racct and lastprid are protected by allprison_lock. */
struct sx allprison_lock;
SX_SYSINIT(allprison_lock, &allprison_lock, "allprison");
@@ -1307,6 +1316,10 @@
goto done_releroot;
}
+#if defined(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,214 @@
+/*-
+ * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
+ * Copyright (c) 2013-2014, by Oliver Pinter <oliver.pntr at gmail.com>
+ * Copyright (c) 2014, by Shawn Webb <lattera at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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$
+ */
+
+#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/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>
+
+#include <security/mac_bsdextended/mac_bsdextended.h>
+
+SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0,
+ "PaX (exploit mitigation) features.");
+
+struct prison *
+pax_get_prison(struct thread *td, struct proc *proc)
+{
+
+ if (td != NULL) {
+ if ((td->td_proc != NULL) && (td->td_proc->p_ucred != NULL))
+ return (td->td_proc->p_ucred->cr_prison);
+
+ return (NULL);
+ }
+ if ((proc == NULL) || (proc->p_ucred == NULL))
+ return (NULL);
+
+ return (proc->p_ucred->cr_prison);
+}
+
+void
+pax_elf(struct image_params *imgp, uint32_t mode)
+{
+ u_int flags = 0;
+
+ if ((mode & MBI_ALLPAX) == MBI_ALLPAX)
+ goto end;
+
+ if (mode & MBI_FORCE_ASLR_ENABLED)
+ flags |= PAX_NOTE_ASLR;
+ else if (mode & MBI_FORCE_ASLR_DISABLED)
+ flags |= PAX_NOTE_NOASLR;
+
+end:
+ if (imgp != NULL) {
+ imgp->pax_flags = flags;
+ if (imgp->proc != NULL) {
+ PROC_LOCK(imgp->proc);
+ imgp->proc->p_pax = flags;
+ PROC_UNLOCK(imgp->proc);
+ }
+ }
+}
+
+
+/*
+ * print out PaX settings on boot time, and validate some of them
+ */
+void
+pax_init(void)
+{
+#if defined(PAX_ASLR)
+ const char *status_str[] = {
+ [0] = "disabled",
+ [1] = "opt-in",
+ [2] = "opt-out",
+ [3] = "force enabled",
+ [4] = "UNKNOWN -> changed to \"force enabled\""
+ };
+#endif
+
+#ifdef PAX_ASLR
+ switch (pax_aslr_status) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ printf("[PAX ASLR] WARNING, invalid PAX settings in loader.conf!"
+ " (pax_aslr_status = %d)\n", pax_aslr_status);
+ pax_aslr_status = 3;
+ break;
+ }
+ printf("[PAX ASLR] status: %s\n", 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);
+
+#ifdef COMPAT_FREEBSD32
+ switch (pax_aslr_compat_status) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ printf("[PAX ASLR (compat)] WARNING, invalid PAX settings in loader.conf! "
+ "(pax_aslr_compat_status = %d)\n", pax_aslr_compat_status);
+ pax_aslr_compat_status = 3;
+ break;
+ }
+ printf("[PAX ASLR (compat)] status: %s\n", 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);
+#endif /* COMPAT_FREEBSD32 */
+#endif /* PAX_ASLR */
+
+ printf("[PAX LOG] logging to system: %d\n", pax_log_log);
+ printf("[PAX LOG] logging to user: %d\n", pax_log_ulog);
+}
+SYSINIT(pax, SI_SUB_PAX, SI_ORDER_FIRST, pax_init, NULL);
+
+void
+pax_init_prison(struct prison *pr)
+{
+
+ if (pr == NULL)
+ return;
+
+ if (pr->pr_pax_set)
+ return;
+
+ mtx_lock(&(pr->pr_mtx));
+
+ if (pax_aslr_debug)
+ uprintf("[PaX ASLR] %s: Setting prison %s ASLR variables\n",
+ __func__, pr->pr_name);
+
+#ifdef PAX_ASLR
+ pr->pr_pax_aslr_status = pax_aslr_status;
+ pr->pr_pax_aslr_debug = pax_aslr_debug;
+ pr->pr_pax_aslr_mmap_len = pax_aslr_mmap_len;
+ pr->pr_pax_aslr_stack_len = pax_aslr_stack_len;
+ pr->pr_pax_aslr_exec_len = pax_aslr_exec_len;
+
+#ifdef COMPAT_FREEBSD32
+ pr->pr_pax_aslr_compat_status = pax_aslr_compat_status;
+ pr->pr_pax_aslr_compat_mmap_len = pax_aslr_compat_mmap_len;
+ pr->pr_pax_aslr_compat_stack_len = pax_aslr_compat_stack_len;
+ pr->pr_pax_aslr_compat_exec_len = pax_aslr_compat_exec_len;
+#endif /* COMPAT_FREEBSD32 */
+#endif /* PAX_ASLR */
+
+ pr->pr_pax_log_log = pax_log_log;
+ pr->pr_pax_log_ulog = pax_log_ulog;
+
+ pr->pr_pax_set = 1;
+
+ mtx_unlock(&(pr->pr_mtx));
+}
Index: sys/kern/kern_pax_aslr.c
===================================================================
--- /dev/null
+++ sys/kern/kern_pax_aslr.c
@@ -0,0 +1,680 @@
+/*-
+ * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
+ * Copyright (c) 2013-2014, by Oliver Pinter <oliver.pntr at gmail.com>
+ * Copyright (c) 2014, by Shawn Webb <lattera at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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$
+ */
+
+#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/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 <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <machine/elf.h>
+
+#include <sys/pax.h>
+
+FEATURE(aslr, "Address Space Layout Randomization.");
+
+int pax_aslr_status = PAX_ASLR_OPTOUT;
+int pax_aslr_debug = 0;
+
+#ifdef PAX_ASLR_MAX_SEC
+int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_MAX_LEN;
+int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_MAX_LEN;
+int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_MAX_LEN;
+#else
+int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_DEF_LEN;
+int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_DEF_LEN;
+int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_DEF_LEN;
+#endif /* PAX_ASLR_MAX_SEC */
+
+#ifdef COMPAT_FREEBSD32
+int pax_aslr_compat_status = PAX_ASLR_OPTOUT;
+#ifdef PAX_ASLR_MAX_SEC
+int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN;
+int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN;
+int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN;
+#else
+int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN;
+int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN;
+int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN;
+#endif /* PAX_ASLR_MAX_SEC */
+#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.debug", &pax_aslr_debug);
+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", &pax_aslr_compat_mmap_len);
+TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_stack_len);
+TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_exec_len);
+#endif
+
+
+#ifdef PAX_SYSCTLS
+/*
+ * sysctls and tunables
+ */
+static int sysctl_pax_aslr_debug(SYSCTL_HANDLER_ARGS);
+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_DECL(_security_pax);
+
+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, debug,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_aslr_debug, "I",
+ "ASLR debug mode");
+
+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,16] 64 bit: [16,32]");
+
+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: [6,12] 64 bit: [12,21]");
+
+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: [6,12] 64 bit: [12,21]");
+
+static int
+sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_status : pax_aslr_status;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || (req->newptr == NULL))
+ return (err);
+
+ switch (val) {
+ case PAX_ASLR_DISABLED:
+ case PAX_ASLR_OPTIN:
+ case PAX_ASLR_OPTOUT:
+ case PAX_ASLR_FORCE_ENABLED:
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_status = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_status = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_debug(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr=NULL;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if ((pr != NULL) && !(pr->pr_pax_set))
+ pax_init_prison(pr);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_debug : pax_aslr_debug;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr)
+ return (err);
+
+ switch (val) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return (EINVAL);
+
+ }
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_debug = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_debug = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr=NULL;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if ((pr != NULL) && !(pr->pr_pax_set))
+ pax_init_prison(pr);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr)
+ return (err);
+
+ if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN ||
+ val > PAX_ASLR_DELTA_MMAP_MAX_LEN)
+ return (EINVAL);
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_mmap_len = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_mmap_len = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr=NULL;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if ((pr != NULL) && !(pr->pr_pax_set))
+ pax_init_prison(pr);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr)
+ return (err);
+
+ if (val < PAX_ASLR_DELTA_STACK_MIN_LEN ||
+ val > PAX_ASLR_DELTA_STACK_MAX_LEN)
+ return (EINVAL);
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_stack_len = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_stack_len = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr=NULL;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if ((pr != NULL) && !(pr->pr_pax_set))
+ pax_init_prison(pr);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_exec_len : pax_aslr_exec_len;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || (req->newptr == NULL))
+ return (err);
+
+ if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN ||
+ val > PAX_ASLR_DELTA_EXEC_MAX_LEN)
+ return (EINVAL);
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_exec_len = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_exec_len = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ 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: [6,12]");
+
+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: [6,12]");
+
+static int
+sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ val = (pr != NULL) ?pr->pr_pax_aslr_compat_status : pax_aslr_compat_status;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || (req->newptr == NULL))
+ return (err);
+
+ switch (val) {
+ case PAX_ASLR_DISABLED:
+ case PAX_ASLR_OPTIN:
+ case PAX_ASLR_OPTOUT:
+ case PAX_ASLR_FORCE_ENABLED:
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_compat_status = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_compat_status = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+ 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(req->td, NULL);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_compat_mmap_len : 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 == NULL) || (pr == &prison0))
+ pax_aslr_compat_mmap_len = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_compat_mmap_len = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ val = (pr != NULL) ? pr->pr_pax_aslr_compat_stack_len : pax_aslr_compat_stack_len;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr)
+ return (err);
+
+ if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN ||
+ val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN)
+ return (EINVAL);
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_aslr_compat_stack_len = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_compat_stack_len = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ return (0);
+}
+
+static int
+sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int err, val;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if (pr != NULL)
+ val = pr->pr_pax_aslr_compat_exec_len;
+ else
+ val = 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 == NULL) || (pr == &prison0))
+ pax_aslr_compat_exec_len = val;
+
+ if (pr != NULL) {
+ mtx_lock(&(pr->pr_mtx));
+ pr->pr_pax_aslr_compat_exec_len = val;
+ mtx_unlock(&(pr->pr_mtx));
+ }
+
+ return (0);
+}
+
+#endif /* COMPAT_FREEBSD32 */
+#endif /* PAX_SYSCTLS */
+
+
+/*
+ * ASLR functions
+ */
+bool
+pax_aslr_active(struct thread *td, struct proc *proc)
+{
+ int status;
+ struct prison *pr;
+ uint32_t flags;
+
+ if ((td == NULL) && (proc == NULL))
+ return (true);
+
+ pr = pax_get_prison(td, proc);
+
+ flags = (td != NULL) ? td->td_proc->p_pax : proc->p_pax;
+ if (((flags & 0xaaaaaaaa) & ((flags & 0x55555555) << 1)) != 0) {
+ pax_log_aslr(pr, __func__, "inconsistent paxflags: %x\n", flags);
+ pax_ulog_aslr(pr, NULL, "inconsistent paxflags: %x\n", flags);
+ return (true);
+ }
+
+ if (pr != NULL)
+ status = pr->pr_pax_aslr_status;
+ else
+ status = pax_aslr_status;
+
+ switch (status) {
+ case PAX_ASLR_DISABLED:
+ return (false);
+ case PAX_ASLR_FORCE_ENABLED:
+ return (true);
+ case PAX_ASLR_OPTIN:
+ if ((flags & PAX_NOTE_ASLR) == 0) {
+ pax_log_aslr(pr, __func__,
+ "ASLR is opt-in, and executable does not have ASLR enabled\n");
+ pax_ulog_aslr(pr, NULL,
+ "ASLR is opt-in, and executable does not have ASLR enabled\n");
+ return (false);
+ }
+ break;
+ case PAX_ASLR_OPTOUT:
+ if ((flags & PAX_NOTE_NOASLR) != 0) {
+ pax_log_aslr(pr, __func__,
+ "ASLR is opt-out, and executable explicitly disabled ASLR\n");
+ pax_ulog_aslr(pr, NULL,
+ "ASLR is opt-out, and executable explicitly disabled ASLR\n");
+ return (false);
+ }
+ break;
+ default:
+ return (true);
+ }
+
+ return (true);
+}
+
+void
+_pax_aslr_init(struct vmspace *vm, struct prison *pr)
+{
+ if (vm == NULL)
+ panic("[PaX ASLR] %s: vm == NULL", __func__);
+
+ vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_DELTA_MMAP_LSB, (pr != NULL) ?
+ pr->pr_pax_aslr_mmap_len :
+ pax_aslr_mmap_len);
+ vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_DELTA_STACK_LSB, (pr != NULL) ?
+ pr->pr_pax_aslr_stack_len :
+ pax_aslr_stack_len);
+ vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
+ vm->vm_aslr_delta_exec = PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_DELTA_EXEC_LSB, (pr != NULL) ?
+ pr->pr_pax_aslr_exec_len :
+ pax_aslr_exec_len);
+
+ if ((pr != NULL) && pr->pr_pax_aslr_debug) {
+ pax_log_aslr(pr, __func__, "vm_aslr_delta_mmap=%p\n",
+ (void *) vm->vm_aslr_delta_mmap);
+ pax_log_aslr(pr, __func__, "vm_aslr_delta_stack=%p\n",
+ (void *) vm->vm_aslr_delta_stack);
+ pax_log_aslr(pr, __func__, "vm_aslr_delta_exec=%p\n",
+ (void *) vm->vm_aslr_delta_exec);
+ pax_ulog_aslr(pr, NULL, "vm_aslr_delta_mmap=%p\n",
+ (void *) vm->vm_aslr_delta_mmap);
+ pax_ulog_aslr(pr, NULL, "vm_aslr_delta_stack=%p\n",
+ (void *) vm->vm_aslr_delta_stack);
+ pax_ulog_aslr(pr, NULL, "vm_aslr_delta_exec=%p\n",
+ (void *) vm->vm_aslr_delta_exec);
+ }
+}
+
+#ifdef COMPAT_FREEBSD32
+void
+_pax_aslr_init32(struct vmspace *vm, struct prison *pr)
+{
+ if (vm == NULL)
+ panic("[PaX ASLR] %s: vm == NULL", __func__);
+
+ vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr != NULL) ?
+ pr->pr_pax_aslr_compat_mmap_len :
+ pax_aslr_compat_mmap_len);
+ vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr != NULL) ?
+ pr->pr_pax_aslr_compat_stack_len :
+ pax_aslr_compat_stack_len);
+ vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
+ vm->vm_aslr_delta_exec = PAX_ASLR_DELTA(arc4random(),
+ PAX_ASLR_DELTA_EXEC_LSB, (pr != NULL) ?
+ pr->pr_pax_aslr_compat_exec_len :
+ pax_aslr_compat_exec_len);
+
+ if ((pr != NULL) && pr->pr_pax_aslr_debug) {
+ pax_log_aslr(pr, __func__, "vm_aslr_delta_mmap=%p\n",
+ (void *) vm->vm_aslr_delta_mmap);
+ pax_log_aslr(pr, __func__, "vm_aslr_delta_stack=%p\n",
+ (void *) vm->vm_aslr_delta_stack);
+ pax_log_aslr(pr, __func__, "vm_aslr_delta_exec=%p\n",
+ (void *) vm->vm_aslr_delta_exec);
+ pax_ulog_aslr(pr, NULL, "vm_aslr_delta_mmap=%p\n",
+ (void *) vm->vm_aslr_delta_mmap);
+ pax_ulog_aslr(pr, NULL, "vm_aslr_delta_stack=%p\n",
+ (void *) vm->vm_aslr_delta_stack);
+ pax_ulog_aslr(pr, NULL, "vm_aslr_delta_exec=%p\n",
+ (void *) vm->vm_aslr_delta_exec);
+ }
+}
+#endif
+
+void
+pax_aslr_init(struct thread *td, struct image_params *imgp)
+{
+ struct prison *pr;
+ struct vmspace *vm;
+
+ pr = pax_get_prison(td, NULL);
+
+ if (imgp == NULL)
+ panic("[PaX ASLR] %s: imgp == NULL", __func__);
+
+ if (!pax_aslr_active(td, NULL))
+ return;
+
+ vm = imgp->proc->p_vmspace;
+
+ if (imgp->sysent->sv_pax_aslr_init != NULL)
+ imgp->sysent->sv_pax_aslr_init(vm, pr);
+}
+
+void
+pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t orig_addr, int flags)
+{
+ struct prison *pr;
+
+ if (!pax_aslr_active(td, NULL))
+ return;
+
+ pr = pax_get_prison(td, NULL);
+
+ if (!(flags & MAP_FIXED) && ((orig_addr == 0) || !(flags & MAP_ANON))) {
+ pax_log_aslr(pr, __func__, "applying to %p orig_addr=%p flags=%x\n",
+ (void *)*addr, (void *)orig_addr, flags);
+
+ *addr += td->td_proc->p_vmspace->vm_aslr_delta_mmap;
+ pax_log_aslr(pr, __func__, "result %p\n", (void *)*addr);
+ } else {
+ pax_log_aslr(pr, __func__, "not applying to %p orig_addr=%p flags=%x\n",
+ (void *)*addr, (void *)orig_addr, flags);
+ }
+}
+
+void
+pax_aslr_stack(struct thread *td, uintptr_t *addr)
+{
+ struct prison *pr;
+ uintptr_t orig_addr;
+
+ if (!pax_aslr_active(td, NULL))
+ return;
+
+ pr = pax_get_prison(td, NULL);
+
+ orig_addr = *addr;
+ *addr -= td->td_proc->p_vmspace->vm_aslr_delta_stack;
+ pax_log_aslr(pr, __func__, "orig_addr=%p, new_addr=%p\n",
+ (void *)orig_addr, (void *)*addr);
+ pax_ulog_aslr(pr, NULL, "orig_addr=%p, new_addr=%p\n",
+ (void *)orig_addr, (void *)*addr);
+}
Index: sys/kern/kern_pax_log.c
===================================================================
--- /dev/null
+++ sys/kern/kern_pax_log.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 2014, by Oliver Pinter <oliver.pntr at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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$
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/pax.h>
+#include <sys/sbuf.h>
+#include <sys/jail.h>
+#include <machine/stdarg.h>
+
+#define __PAX_LOG_TEMPLATE(SUBJECT, name) \
+void \
+pax_log_##name(struct prison *pr, const char *caller_name, const char* fmt, ...)\
+{ \
+ struct sbuf *sb; \
+ va_list args; \
+ \
+ if ((pr != NULL) && (pr->pr_pax_log_log == 0)) \
+ return; \
+ \
+ sb = sbuf_new_auto(); \
+ if (sb == NULL) \
+ panic("%s: Could not allocate memory", __func__); \
+ sbuf_printf(sb, "[PAX "#SUBJECT"] "); \
+ if (caller_name != NULL) \
+ sbuf_printf(sb, "%s: ", caller_name); \
+ va_start(args, fmt); \
+ sbuf_vprintf(sb, fmt, args); \
+ va_end(args); \
+ if (sbuf_finish(sb) != 0) \
+ panic("%s: Could not generate message", __func__); \
+ \
+ printf("%s", sbuf_data(sb)); \
+ sbuf_delete(sb); \
+} \
+ \
+void \
+pax_ulog_##name(struct prison *pr, const char *caller_name, const char* fmt, ...)\
+{ \
+ struct sbuf *sb; \
+ va_list args; \
+ \
+ if ((pr != NULL) && (pr->pr_pax_log_ulog == 0)) \
+ return; \
+ \
+ sb = sbuf_new_auto(); \
+ if (sb == NULL) \
+ panic("%s: Could not allocate memory", __func__); \
+ sbuf_printf(sb, "[PAX "#SUBJECT"] "); \
+ if (caller_name != NULL) \
+ sbuf_printf(sb, "%s: ", caller_name); \
+ va_start(args, fmt); \
+ sbuf_vprintf(sb, fmt, args); \
+ va_end(args); \
+ if (sbuf_finish(sb) != 0) \
+ panic("%s: Could not generate message", __func__); \
+ \
+ uprintf("%s", sbuf_data(sb)); \
+ sbuf_delete(sb); \
+}
+
+
+static int sysctl_pax_log_log(SYSCTL_HANDLER_ARGS);
+static int sysctl_pax_log_ulog(SYSCTL_HANDLER_ARGS);
+
+int pax_log_log = PAX_LOG_LOG;
+int pax_log_ulog = PAX_LOG_ULOG;
+
+SYSCTL_DECL(_security_pax);
+
+SYSCTL_NODE(_security_pax, OID_AUTO, log, CTLFLAG_RD, 0,
+ "PAX related logging facility.");
+
+SYSCTL_PROC(_security_pax_log, OID_AUTO, log,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_log_log, "I",
+ "log to syslog "
+ "0 - disabled, "
+ "1 - enabled ");
+TUNABLE_INT("security.pax.log.log", &pax_log_log);
+
+SYSCTL_PROC(_security_pax_log, OID_AUTO, ulog,
+ CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
+ NULL, 0, sysctl_pax_log_ulog, "I",
+ "log to user terminal"
+ "0 - disabled, "
+ "1 - enabled ");
+TUNABLE_INT("security.pax.log.ulog", &pax_log_ulog);
+
+static int
+sysctl_pax_log_log(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+ int val;
+ struct prison *pr=NULL;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if ((pr != NULL) && !(pr->pr_pax_set))
+ pax_init_prison(pr);
+
+ val = (pr != NULL) ? pr->pr_pax_log_log : pax_log_log;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr)
+ return (err);
+
+ switch (val) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return (EINVAL);
+
+ }
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_log_log = val;
+ if (pr != NULL)
+ pr->pr_pax_log_log = val;
+
+ return (0);
+}
+
+static int
+sysctl_pax_log_ulog(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+ int val;
+ struct prison *pr=NULL;
+
+ pr = pax_get_prison(req->td, NULL);
+
+ if ((pr != NULL) && !(pr->pr_pax_set))
+ pax_init_prison(pr);
+
+ val = (pr != NULL) ? pr->pr_pax_log_ulog : pax_log_ulog;
+ err = sysctl_handle_int(oidp, &val, sizeof(int), req);
+ if (err || !req->newptr)
+ return (err);
+
+ switch (val) {
+ case 0:
+ case 1:
+ break;
+ default:
+ return (EINVAL);
+
+ }
+
+ if ((pr == NULL) || (pr == &prison0))
+ pax_log_ulog = val;
+ if (pr != NULL)
+ pr->pr_pax_log_ulog = val;
+
+ return (0);
+}
+
+
+__PAX_LOG_TEMPLATE(ASLR, aslr)
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>
@@ -49,6 +51,10 @@
#include <machine/md_var.h>
#include <machine/cache.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
#ifdef __mips_n64
struct sysentvec elf64_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
@@ -83,6 +89,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
static Elf64_Brandinfo freebsd_brand_info = {
@@ -139,6 +150,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init32,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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
@@ -66,6 +67,10 @@
#include <compat/freebsd32/freebsd32_util.h>
#include <compat/freebsd32/freebsd32_proto.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
static void freebsd32_exec_setregs(struct thread *, struct image_params *, u_long);
static int get_mcontext32(struct thread *, mcontext32_t *, int);
static int set_mcontext32(struct thread *, const mcontext32_t *);
@@ -106,6 +111,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init32,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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>
@@ -52,6 +54,10 @@
#include <machine/reg.h>
#include <machine/md_var.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
#ifdef __powerpc64__
#include <compat/freebsd32/freebsd32_proto.h>
#include <compat/freebsd32/freebsd32_util.h>
@@ -107,6 +113,11 @@
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init32,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
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,6 +25,8 @@
* $FreeBSD$
*/
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -48,6 +50,10 @@
#include <machine/elf.h>
#include <machine/md_var.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
struct sysentvec elf64_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
.sv_table = sysent,
@@ -83,6 +89,11 @@
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
Index: sys/security/mac_bsdextended/mac_bsdextended.h
===================================================================
--- sys/security/mac_bsdextended/mac_bsdextended.h
+++ sys/security/mac_bsdextended/mac_bsdextended.h
@@ -51,6 +51,9 @@
#define MBI_ADMIN 010000
#define MBI_STAT 020000
#define MBI_APPEND 040000
+#define MBI_FORCE_ASLR_ENABLED 0x01
+#define MBI_FORCE_ASLR_DISABLED 0x02
+#define MBI_ALLPAX (MBI_FORCE_ASLR_ENABLED | MBI_FORCE_ASLR_DISABLED)
#define MBI_ALLPERM (MBI_EXEC | MBI_WRITE | MBI_READ | MBI_ADMIN | \
MBI_STAT | MBI_APPEND)
Index: sys/sparc64/sparc64/elf_machdep.c
===================================================================
--- sys/sparc64/sparc64/elf_machdep.c
+++ sys/sparc64/sparc64/elf_machdep.c
@@ -34,6 +34,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_pax.h"
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -52,6 +54,10 @@
#include <machine/elf.h>
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
#include "linker_if.h"
static struct sysentvec elf64_freebsd_sysvec = {
@@ -87,6 +93,11 @@
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
+#ifdef PAX_ASLR
+ .sv_pax_aslr_init = _pax_aslr_init,
+#else
+ .sv_pax_aslr_init = NULL,
+#endif
};
static Elf64_Brandinfo freebsd_brand_info = {
Index: sys/sys/imgact.h
===================================================================
--- sys/sys/imgact.h
+++ sys/sys/imgact.h
@@ -78,6 +78,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
@@ -184,6 +184,19 @@
char pr_hostname[MAXHOSTNAMELEN]; /* (p) jail hostname */
char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */
char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */
+ /* Lock only needed for pax_* if pr_pax_set == 0 */
+ int pr_pax_set; /* (p) PaX settings initialized */
+ int pr_pax_aslr_status; /* (p) PaX ASLR enabled */
+ int pr_pax_aslr_debug; /* (p) PaX ASLR debug */
+ int pr_pax_aslr_mmap_len; /* (p) Number of bits randomized with mmap */
+ int pr_pax_aslr_stack_len; /* (p) Number of bits randomized with stack */
+ int pr_pax_aslr_exec_len; /* (p) Number of bits randomized with the execbase */
+ int pr_pax_aslr_compat_status; /* (p) PaX ASLR enabled (compat32) */
+ int pr_pax_aslr_compat_mmap_len; /* (p) Number of bits randomized with mmap (compat32) */
+ int pr_pax_aslr_compat_stack_len; /* (p) Number of bits randomized with stack (compat32) */
+ int pr_pax_aslr_compat_exec_len; /* (p) Number of bits randomized with the execbase (compat32) */
+ int pr_pax_log_log; /* (p) XXX */
+ int pr_pax_log_ulog; /* (p) XXX */
};
struct prison_racct {
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 = 0x1B50000, /* 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/pax.h
===================================================================
--- /dev/null
+++ sys/sys/pax.h
@@ -0,0 +1,226 @@
+/*-
+ * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
+ * Copyright (c) 2013-2014, by Oliver Pinter <oliver.pntr at gmail.com>
+ * Copyright (c) 2014, by Shawn Webb <lattera at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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$
+ */
+
+#ifndef __SYS_PAX_H
+#define __SYS_PAX_H
+
+struct image_params;
+struct prison;
+struct thread;
+struct vnode;
+struct vmspace;
+struct vm_offset_t;
+
+/*
+ * used in sysctl handler
+ */
+#define PAX_ASLR_DISABLED 0
+#define PAX_ASLR_OPTIN 1
+#define PAX_ASLR_OPTOUT 2
+#define PAX_ASLR_FORCE_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 |
+ * +-------+--------+--------+
+ * | DEF | 8 bit | 21 bit |
+ * +-------+--------+--------+
+ * | MAX | 16 bit | 32 bit |
+ * +-------+--------+--------+
+ *
+ * STACK | 32 bit | 64 bit |
+ * +-------+--------+--------+
+ * | MIN | 6 bit | 12 bit |
+ * +-------+--------+--------+
+ * | DEF | 6 bit | 16 bit |
+ * +-------+--------+--------+
+ * | MAX | 10 bit | 21 bit |
+ * +-------+--------+--------+
+ *
+ * EXEC | 32 bit | 64 bit |
+ * +-------+--------+--------+
+ * | MIN | 6 bit | 12 bit |
+ * +-------+--------+--------+
+ * | DEF | 6 bit | 21 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 default values for native host
+ */
+#ifdef __amd64__
+#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 21
+#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */
+#else
+#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN
+#define PAX_ASLR_DELTA_MMAP_DEF_LEN PAX_ASLR_DELTA_MMAP_MIN_LEN
+#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 PAX_ASLR_DELTA_EXEC_MIN_LEN
+#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */
+#endif /* __amd64__ */
+
+/*
+ * 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_mmap_len;
+extern int pax_aslr_stack_len;
+extern int pax_aslr_exec_len;
+#ifdef COMPAT_FREEBSD32
+extern int pax_aslr_compat_status;
+extern int pax_aslr_compat_mmap_len;
+extern int pax_aslr_compat_stack_len;
+extern int pax_aslr_compat_exec_len;
+#endif /* COMPAT_FREEBSD32 */
+#endif /* PAX_ASLR */
+
+extern int pax_log_log;
+extern int pax_log_ulog;
+
+#define ELF_NOTE_TYPE_PAX_TAG 3
+#define PAX_NOTE_MPROTECT 0x01
+#define PAX_NOTE_NOMPROTECT 0x02
+#define PAX_NOTE_GUARD 0x04
+#define PAX_NOTE_NOGUARD 0x08
+#define PAX_NOTE_ASLR 0x10
+#define PAX_NOTE_NOASLR 0x20
+
+#define PAX_LOG_LOG 0
+#define PAX_LOG_ULOG 0
+
+void pax_init(void);
+void pax_init_prison(struct prison *pr);
+bool pax_aslr_active(struct thread *td, struct proc *proc);
+void _pax_aslr_init(struct vmspace *vm, struct prison *pr);
+void _pax_aslr_init32(struct vmspace *vm, struct prison *pr);
+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);
+struct prison *pax_get_prison(struct thread *td, struct proc *proc);
+void pax_elf(struct image_params *, uint32_t);
+
+void pax_log_aslr(struct prison *pr, const char *func, const char *fmt, ...);
+void pax_ulog_aslr(struct prison *pr, const char *func, const char *fmt, ...);
+
+#endif /* __SYS_PAX_H */
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -539,6 +539,7 @@
u_int p_stops; /* (c) Stop event bitmask. */
u_int p_stype; /* (c) Stop event type. */
char p_step; /* (c) Process is stopped. */
+ u_int p_pax; /* (b) PaX is enabled to this process */
u_char p_pfsflags; /* (c) Procfs flags. */
struct nlminfo *p_nlminfo; /* (?) Only used by/for lockd. */
struct kaioinfo *p_aioinfo; /* (y) ASYNC I/O info. */
Index: sys/sys/sysent.h
===================================================================
--- sys/sys/sysent.h
+++ sys/sys/sysent.h
@@ -77,9 +77,11 @@
#define SY_THR_INCR 0x8
struct image_params;
+struct prison;
struct __sigset;
struct syscall_args;
struct trapframe;
+struct vmspace;
struct vnode;
struct sysentvec {
@@ -130,6 +132,7 @@
uint32_t sv_timekeep_gen;
void *sv_shared_page_obj;
void (*sv_schedtail)(struct thread *);
+ void (*sv_pax_aslr_init)(struct vmspace *vm, struct prison *pr);
};
#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_size_t vm_aslr_delta_mmap; /* mmap() random delta for ASLR */
+ vm_size_t vm_aslr_delta_stack; /* stack random delta for ASLR */
+ vm_size_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>
@@ -292,6 +294,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);
}
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>
@@ -91,6 +92,10 @@
#include <sys/pmckern.h>
#endif
+#ifdef PAX_ASLR
+#include <sys/pax.h>
+#endif
+
int old_mlock = 0;
SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RWTUN, &old_mlock, 0,
"Do not apply RLIMIT_MEMLOCK on mlockall");
@@ -202,6 +207,9 @@
struct file *fp;
struct vnode *vp;
vm_offset_t addr;
+#ifdef PAX_ASLR
+ vm_offset_t orig_addr;
+#endif
vm_size_t size, pageoff;
vm_prot_t cap_maxprot, prot, maxprot;
void *handle;
@@ -212,6 +220,9 @@
cap_rights_t rights;
addr = (vm_offset_t) uap->addr;
+#ifdef PAX_ASLR
+ orig_addr = addr;
+#endif
size = uap->len;
prot = uap->prot & VM_PROT_ALL;
flags = uap->flags;
@@ -294,6 +305,12 @@
* do not bother moving the mapping past the heap (since
* the heap is usually above 2GB).
*/
+#ifdef PAX_ASLR
+ /* Ugly hack for adding ASLR to 32bit mappings */
+ pax_aslr_mmap(td, &addr, orig_addr, flags);
+ if (addr != orig_addr)
+ addr = trunc_page(addr&0x0fffffff);
+#endif
if (addr + size > MAP_32BIT_MAX_ADDR)
addr = 0;
#endif
@@ -307,6 +324,9 @@
* location.
*/
PROC_LOCK(td->td_proc);
+#ifdef PAX_ASLR
+ pax_aslr_mmap(td, &addr, orig_addr, flags);
+#endif
if (addr == 0 ||
(addr >= round_page((vm_offset_t)vms->vm_taddr) &&
addr < round_page((vm_offset_t)vms->vm_daddr +

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 14, 10:36 PM (8 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29634396
Default Alt Text
D473.1789425410.diff (63 KB)

Event Timeline