Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149037673
D473.1789425410.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
63 KB
Referenced Files
None
Subscribers
None
D473.1789425410.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D473: Base ASLR
Attached
Detach File
Event Timeline
Log In to Comment