mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
HBSD OPNsense: Separate out the ASLR code.
On OPNsense's 16.7 roadmap is HardenedBSD's ASLR code. This commit separates out the ASLR code from the rest of our exploit mitigation and system hardening code. Testing and verification still need to be performed. Initial testing (compile + boot + `procstat -v PIDofPIEapplication) has been performed. More thorough testing should occur. Shared object load order randomization in the RTLD is not included in this patch. That will be discussed with the fine folks at OPNsense at a later time. Since OPNsense is based on FreeBSD 10.x, this patch will need to be backported to 10-STABLE. However, a "horizontal port" to 11-CURRENT, which is what this commit is, needed to be done first. Signed-off-by: Shawn Webb <shawn.webb@hardenedbsd.org>
This commit is contained in:
parent
e0977fd0da
commit
e13c0d42eb
55 changed files with 2259 additions and 82 deletions
|
|
@ -26,12 +26,15 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
|
|
@ -82,6 +85,7 @@ struct sysentvec elf64_freebsd_sysvec = {
|
|||
.sv_shared_page_base = SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
}
|
||||
|
||||
regs->tf_rsp = (long)sfp;
|
||||
regs->tf_rip = p->p_sysent->sv_sigcode_base;
|
||||
regs->tf_rip = p->p_sigcode_base;
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucodesel;
|
||||
regs->tf_ds = _udatasel;
|
||||
|
|
|
|||
|
|
@ -364,3 +364,6 @@ device xenpci # Xen HVM Hypervisor services driver
|
|||
|
||||
# VMware support
|
||||
device vmx # VMware VMXNET3 Ethernet
|
||||
|
||||
options PAX
|
||||
options PAX_ASLR
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
}
|
||||
|
||||
regs->tf_rsp = (uintptr_t)fp;
|
||||
regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode;
|
||||
regs->tf_rip = p->p_ps_strings - sz_ia32_osigcode;
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucode32sel;
|
||||
regs->tf_ds = _udatasel;
|
||||
|
|
@ -534,7 +534,7 @@ freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
}
|
||||
|
||||
regs->tf_rsp = (uintptr_t)sfp;
|
||||
regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode -
|
||||
regs->tf_rip = p->p_sigcode_base + sz_ia32_sigcode -
|
||||
sz_freebsd4_ia32_sigcode;
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucode32sel;
|
||||
|
|
@ -682,7 +682,7 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
}
|
||||
|
||||
regs->tf_rsp = (uintptr_t)sfp;
|
||||
regs->tf_rip = p->p_sysent->sv_sigcode_base;
|
||||
regs->tf_rip = p->p_sigcode_base;
|
||||
regs->tf_rflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucode32sel;
|
||||
regs->tf_ss = _udatasel;
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ setup_lcall_gate(void)
|
|||
bzero(&uap, sizeof(uap));
|
||||
uap.start = 0;
|
||||
uap.num = 1;
|
||||
lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp;
|
||||
lcall_addr = curproc->p_psstrings - sz_lcall_tramp;
|
||||
bzero(&desc, sizeof(desc));
|
||||
desc.sd_type = SDT_MEMERA;
|
||||
desc.sd_dpl = SEL_UPL;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
#define DFLSSIZ (8UL*1024*1024) /* initial stack size limit */
|
||||
#endif
|
||||
#ifndef MAXSSIZ
|
||||
#define MAXSSIZ (512UL*1024*1024) /* max stack size */
|
||||
#define MAXSSIZ (1UL*1024*1024*1024) /* max stack size */
|
||||
#endif
|
||||
#ifndef SGROWSIZ
|
||||
#define SGROWSIZ (128UL*1024) /* amount to grow stack */
|
||||
|
|
@ -178,10 +178,11 @@
|
|||
#define VM_MAXUSER_ADDRESS UVADDR(NUPML4E, 0, 0, 0)
|
||||
|
||||
#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
|
||||
#define USRSTACK SHAREDPAGE
|
||||
#define SHAREDPAGE_GUARD (4 * PAGE_SIZE)
|
||||
#define USRSTACK (SHAREDPAGE - SHAREDPAGE_GUARD)
|
||||
|
||||
#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
|
||||
#define VM_MIN_ADDRESS (0)
|
||||
#define VM_MIN_ADDRESS (65536)
|
||||
|
||||
#define PHYS_TO_DMAP(x) ((x) | DMAP_MIN_ADDRESS)
|
||||
#define DMAP_TO_PHYS(x) ((x) & ~DMAP_MIN_ADDRESS)
|
||||
|
|
|
|||
|
|
@ -635,7 +635,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
|
|||
* mmap's return value.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK -
|
||||
p->p_vmspace->vm_maxsaddr = (char *)p->p_usrstack -
|
||||
lim_cur(p, RLIMIT_STACK);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include "opt_compat.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#ifndef COMPAT_FREEBSD32
|
||||
#error "Unable to compile Linux-emulator due to missing COMPAT_FREEBSD32 option!"
|
||||
|
|
@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/signalvar.h>
|
||||
|
|
@ -250,11 +252,11 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
|||
struct linux32_ps_strings *arginfo;
|
||||
int issetugid;
|
||||
|
||||
arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
|
||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform);
|
||||
|
||||
KASSERT(curthread->td_proc == imgp->proc,
|
||||
("unsafe elf_linux_fixup(), should be curproc"));
|
||||
|
||||
arginfo = (struct linux32_ps_strings *)imgp->proc->p_psstrings;
|
||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform);
|
||||
base = (Elf32_Addr *)*stack_base;
|
||||
args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
pos = base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
|
|
@ -869,7 +871,7 @@ linux_copyout_strings(struct image_params *imgp)
|
|||
* Calculate string base and vector table pointers.
|
||||
* Also deal with signal trampoline code for this exec type.
|
||||
*/
|
||||
arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
|
||||
arginfo = (struct linux32_ps_strings *)imgp->proc->p_psstrings;
|
||||
destp = (caddr_t)arginfo - SPARE_USRSPACE - linux_szplatform -
|
||||
roundup((ARG_MAX - imgp->args->stringspace),
|
||||
sizeof(char *));
|
||||
|
|
@ -1039,6 +1041,7 @@ struct sysentvec elf_linux_sysvec = {
|
|||
.sv_shared_page_base = LINUX32_SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = linux_schedtail,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace32,
|
||||
};
|
||||
INIT_SYSENTVEC(elf_sysvec, &elf_linux_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -34,6 +36,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/linker.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/signalvar.h>
|
||||
|
|
@ -79,6 +82,7 @@ struct sysentvec elf32_freebsd_sysvec = {
|
|||
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
|
||||
.sv_syscallnames = syscallnames,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
|
||||
static Elf32_Brandinfo freebsd_brand_info = {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_pax.h"
|
||||
#include "opt_platform.h"
|
||||
#include "opt_sched.h"
|
||||
#include "opt_timer.h"
|
||||
|
|
@ -69,6 +70,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/malloc.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/pcpu.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/rwlock.h>
|
||||
|
|
@ -278,7 +280,7 @@ sendsig(catcher, ksi, mask)
|
|||
tf->tf_r5 = (register_t)&fp->sf_uc;
|
||||
tf->tf_pc = (register_t)catcher;
|
||||
tf->tf_usr_sp = (register_t)fp;
|
||||
tf->tf_usr_lr = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
|
||||
tf->tf_usr_lr = (register_t)(p->p_psstrings - *(p->p_sysent->sv_szsigcode));
|
||||
|
||||
CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr,
|
||||
tf->tf_usr_sp);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include "opt_compat.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#define __ELF_WORD_SIZE 32
|
||||
|
||||
|
|
@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/mount.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procctl.h>
|
||||
#include <sys/reboot.h>
|
||||
|
|
@ -2865,12 +2867,16 @@ freebsd32_copyout_strings(struct image_params *imgp)
|
|||
execpath_len = strlen(imgp->execpath) + 1;
|
||||
else
|
||||
execpath_len = 0;
|
||||
arginfo = (struct freebsd32_ps_strings *)curproc->p_sysent->
|
||||
sv_psstrings;
|
||||
if (imgp->proc->p_sysent->sv_sigcode_base == 0)
|
||||
arginfo = (struct freebsd32_ps_strings *)curproc->p_psstrings;
|
||||
imgp->proc->p_sigcode_base = imgp->proc->p_sysent->sv_sigcode_base;
|
||||
if (imgp->proc->p_sigcode_base == 0)
|
||||
szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
|
||||
else
|
||||
else {
|
||||
szsigcode = 0;
|
||||
#ifdef PAX_ASLR
|
||||
pax_aslr_vdso(imgp->proc, &(imgp->proc->p_sigcode_base));
|
||||
#endif
|
||||
}
|
||||
destp = (uintptr_t)arginfo;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#define __ELF_WORD_SIZE 32
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/mutex.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procfs.h>
|
||||
|
|
@ -139,6 +141,7 @@ struct sysentvec ia32_freebsd_sysvec = {
|
|||
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace32,
|
||||
};
|
||||
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -2993,3 +2993,8 @@ options RANDOM_RWFILE # Read and write entropy cache
|
|||
|
||||
# Intel em(4) driver
|
||||
options EM_MULTIQUEUE # Activate multiqueue features/disable MSI-X
|
||||
|
||||
# PAX and HardenedBSD related knobs
|
||||
options PAX
|
||||
options PAX_ASLR
|
||||
options PAX_SYSCTLS
|
||||
|
|
|
|||
|
|
@ -2957,6 +2957,10 @@ gnu/fs/reiserfs/reiserfs_stree.c optional reiserfs
|
|||
gnu/fs/reiserfs/reiserfs_vfsops.c optional reiserfs
|
||||
gnu/fs/reiserfs/reiserfs_vnops.c optional reiserfs
|
||||
#
|
||||
hardenedbsd/hbsd_pax_common.c optional pax
|
||||
hardenedbsd/hbsd_pax_log.c optional pax
|
||||
hardenedbsd/hbsd_pax_aslr.c optional pax pax_aslr
|
||||
#
|
||||
isa/isa_if.m standard
|
||||
isa/isa_common.c optional isa
|
||||
isa/isahint.c optional isa
|
||||
|
|
|
|||
|
|
@ -930,6 +930,21 @@ RACCT_DEFAULT_TO_DISABLED opt_global.h
|
|||
# Resource Limits
|
||||
RCTL opt_global.h
|
||||
|
||||
# PaX-inspired hardening features
|
||||
PAX opt_pax.h
|
||||
PAX_ASLR opt_pax.h
|
||||
PAX_SYSCTLS opt_pax.h
|
||||
|
||||
# ASLR overwritable defaults
|
||||
PAX_ASLR_DELTA_MMAP_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_STACK_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_VDSO_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_EXEC_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_COMPAT_DELTA_MMAP_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_COMPAT_DELTA_STACK_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_COMPAT_DELTA_EXEC_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_COMPAT_DELTA_VDSO_DEF_LEN opt_pax.h
|
||||
|
||||
# Random number generator(s)
|
||||
RANDOM_YARROW opt_random.h
|
||||
RANDOM_FORTUNA opt_random.h
|
||||
|
|
|
|||
|
|
@ -71,3 +71,9 @@ HYPERV opt_global.h
|
|||
|
||||
# options for the Intel C600 SAS driver (isci)
|
||||
ISCI_LOGGING opt_isci.h
|
||||
|
||||
# HardenedBSD ASLR options
|
||||
PAX_ASLR_DELTA_MAP32BIT_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_MAP32BIT_MIN_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_MAP32BIT_MAX_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_MAP32BIT_LSB opt_pax.h
|
||||
|
|
|
|||
|
|
@ -29,3 +29,9 @@ SCHIZO_DEBUG opt_schizo.h
|
|||
|
||||
SUNKBD_DFLT_KEYMAP opt_sunkbd.h
|
||||
SUNKBD_EMULATE_ATKBD opt_sunkbd.h
|
||||
|
||||
# HardenedBSD ASLR options
|
||||
PAX_ASLR_DELTA_MAP32BIT_DEF_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_MAP32BIT_MIN_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_MAP32BIT_MAX_LEN opt_pax.h
|
||||
PAX_ASLR_DELTA_MAP32BIT_LSB opt_pax.h
|
||||
|
|
|
|||
|
|
@ -30,10 +30,13 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -316,6 +319,9 @@ DB_SHOW_COMMAND(thread, db_show_thread)
|
|||
(void *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 1));
|
||||
db_printf(" flags: %#x ", td->td_flags);
|
||||
db_printf(" pflags: %#x\n", td->td_pflags);
|
||||
#ifdef PAX
|
||||
pax_db_printf_flags_td(td, PAX_LOG_DEFAULT);
|
||||
#endif
|
||||
db_printf(" state: ");
|
||||
switch (td->td_state) {
|
||||
case TDS_INACTIVE:
|
||||
|
|
@ -423,6 +429,9 @@ DB_SHOW_COMMAND(proc, db_show_proc)
|
|||
if (p->p_args != NULL)
|
||||
db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length,
|
||||
p->p_args->ar_args);
|
||||
#ifdef PAX
|
||||
pax_db_printf_flags(p, PAX_LOG_DEFAULT);
|
||||
#endif
|
||||
db_printf(" threads: %d\n", p->p_numthreads);
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
dumpthread(p, td, 1);
|
||||
|
|
|
|||
858
sys/hardenedbsd/hbsd_pax_aslr.c
Normal file
858
sys/hardenedbsd/hbsd_pax_aslr.c
Normal file
|
|
@ -0,0 +1,858 @@
|
|||
/*-
|
||||
* Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
|
||||
* Copyright (c) 2013-2016, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
|
||||
* Copyright (c) 2014-2015, by Shawn Webb <shawn.webb@hardenedbsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#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/elf_common.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sysent.h>
|
||||
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_extern.h>
|
||||
|
||||
#include "hbsd_pax_internal.h"
|
||||
|
||||
#ifndef PAX_ASLR_DELTA
|
||||
#define PAX_ASLR_DELTA(delta, lsb, len) \
|
||||
(((delta) & ((1UL << (len)) - 1)) << (lsb))
|
||||
#endif /* PAX_ASLR_DELTA */
|
||||
|
||||
/*-
|
||||
* generic ASLR values
|
||||
*
|
||||
* | 32 bit | 64 bit | compat |
|
||||
* +-------+--------+--------+--------+
|
||||
* | MMAP | 14 bit | 30 bit | 14 bit |
|
||||
* +-------+--------+--------+--------+
|
||||
* | STACK | 10 bit | 42 bit | 10 bit |
|
||||
* +-------+--------+--------+--------+
|
||||
* | EXEC | 14 bit | 30 bit | 14 bit |
|
||||
* +-------+--------+--------+--------+
|
||||
* | VDSO | 10 bit | 28 bit | 10 bit |
|
||||
* +-------+--------+--------+--------+
|
||||
* | M32B | N.A. | 18 bit | N.A. |
|
||||
* +-------+--------+--------+--------+
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_MMAP_LSB
|
||||
#define PAX_ASLR_DELTA_MMAP_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_DELTA_MMAP_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_STACK_LSB
|
||||
#define PAX_ASLR_DELTA_STACK_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_DELTA_STACK_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_STACK_WITH_GAP_LSB
|
||||
#define PAX_ASLR_DELTA_STACK_WITH_GAP_LSB 3
|
||||
#endif /* PAX_ASLR_DELTA_STACK_WITH_GAP_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_EXEC_LSB
|
||||
#define PAX_ASLR_DELTA_EXEC_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_DELTA_EXEC_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_VDSO_LSB
|
||||
#define PAX_ASLR_DELTA_VDSO_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_DELTA_VDSO_LSB */
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
#ifndef PAX_ASLR_DELTA_MAP32BIT_LSB
|
||||
#define PAX_ASLR_DELTA_MAP32BIT_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_DELTA_MAP32BIT_LSB */
|
||||
#endif /* MAP_32BIT */
|
||||
|
||||
/*
|
||||
* ASLR default values for native host
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_MMAP_DEF_LEN 30
|
||||
#endif /* PAX_ASLR_DELTA_MMAP_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_STACK_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_STACK_DEF_LEN 42
|
||||
#endif /* PAX_ASLR_DELTA_STACK_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_EXEC_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_EXEC_DEF_LEN 30
|
||||
#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_VDSO_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_VDSO_DEF_LEN 28
|
||||
#endif /* PAX_ASLR_DELTA_VDSO_DEF_LEN */
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
#ifndef PAX_ASLR_DELTA_MAP32BIT_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_MAP32BIT_DEF_LEN 18
|
||||
#endif /* PAX_ASLR_DELTA_MAP32BIT_DEF_LEN */
|
||||
#endif /* MAP_32BIT */
|
||||
|
||||
#else /* ! __LP64__ */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_MMAP_DEF_LEN 14
|
||||
#endif /* PAX_ASLR_DELTA_MMAP_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_STACK_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_STACK_DEF_LEN 10
|
||||
#endif /* PAX_ASLR_DELTA_STACK_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_EXEC_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_EXEC_DEF_LEN 14
|
||||
#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_DELTA_VDSO_DEF_LEN
|
||||
#define PAX_ASLR_DELTA_VDSO_DEF_LEN 10
|
||||
#endif /* PAX_ASLR_DELTA_VDSO_DEF_LEN */
|
||||
|
||||
#endif /* __LP64__ */
|
||||
|
||||
/*
|
||||
* ASLR values for COMPAT_FREEBSD32, COMPAT_LINUX and MAP_32BIT
|
||||
*/
|
||||
#if defined(COMPAT_LINUX) || defined(COMPAT_FREEBSD32) || defined(MAP_32BIT)
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB
|
||||
#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB
|
||||
#define PAX_ASLR_COMPAT_DELTA_STACK_LSB 3
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_LSB
|
||||
#define PAX_ASLR_COMPAT_DELTA_EXEC_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_VDSO_LSB
|
||||
#define PAX_ASLR_COMPAT_DELTA_VDSO_LSB PAGE_SHIFT
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_VDSO_LSB */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_DEF_LEN
|
||||
#define PAX_ASLR_COMPAT_DELTA_MMAP_DEF_LEN 14
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_STACK_DEF_LEN
|
||||
#define PAX_ASLR_COMPAT_DELTA_STACK_DEF_LEN 10
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_STACK_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_DEF_LEN
|
||||
#define PAX_ASLR_COMPAT_DELTA_EXEC_DEF_LEN 14
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_DEF_LEN */
|
||||
|
||||
#ifndef PAX_ASLR_COMPAT_DELTA_VDSO_DEF_LEN
|
||||
#define PAX_ASLR_COMPAT_DELTA_VDSO_DEF_LEN 10
|
||||
#endif /* PAX_ASLR_COMPAT_DELTA_VDSO_DEF_LEN */
|
||||
|
||||
#endif
|
||||
|
||||
FEATURE(hbsd_aslr, "Address Space Layout Randomization.");
|
||||
|
||||
static int pax_aslr_status = PAX_FEATURE_OPTOUT;
|
||||
static int pax_aslr_mmap_len = PAX_ASLR_DELTA_MMAP_DEF_LEN;
|
||||
static int pax_aslr_stack_len = PAX_ASLR_DELTA_STACK_DEF_LEN;
|
||||
static int pax_aslr_exec_len = PAX_ASLR_DELTA_EXEC_DEF_LEN;
|
||||
static int pax_aslr_vdso_len = PAX_ASLR_DELTA_VDSO_DEF_LEN;
|
||||
#ifdef MAP_32BIT
|
||||
static int pax_aslr_map32bit_len = PAX_ASLR_DELTA_MAP32BIT_DEF_LEN;
|
||||
#ifdef PAX_HARDENING
|
||||
static int pax_disallow_map32bit_status_global = PAX_FEATURE_OPTOUT;
|
||||
#else
|
||||
static int pax_disallow_map32bit_status_global = PAX_FEATURE_OPTIN;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
static int pax_aslr_compat_status = PAX_FEATURE_OPTOUT;
|
||||
static int pax_aslr_compat_mmap_len = PAX_ASLR_COMPAT_DELTA_MMAP_DEF_LEN;
|
||||
static int pax_aslr_compat_stack_len = PAX_ASLR_COMPAT_DELTA_STACK_DEF_LEN;
|
||||
static int pax_aslr_compat_exec_len = PAX_ASLR_COMPAT_DELTA_EXEC_DEF_LEN;
|
||||
static int pax_aslr_compat_vdso_len = PAX_ASLR_COMPAT_DELTA_VDSO_DEF_LEN;
|
||||
#endif /* COMPAT_FREEBSD32 */
|
||||
|
||||
TUNABLE_INT("hardening.pax.aslr.status", &pax_aslr_status);
|
||||
TUNABLE_INT("hardening.pax.aslr.mmap_len", &pax_aslr_mmap_len);
|
||||
TUNABLE_INT("hardening.pax.aslr.stack_len", &pax_aslr_stack_len);
|
||||
TUNABLE_INT("hardening.pax.aslr.exec_len", &pax_aslr_exec_len);
|
||||
TUNABLE_INT("hardening.pax.aslr.vdso_len", &pax_aslr_vdso_len);
|
||||
#ifdef MAP_32BIT
|
||||
TUNABLE_INT("hardening.pax.aslr.map32bit_len", &pax_aslr_map32bit_len);
|
||||
TUNABLE_INT("hardening.pax.disallow_map32bit.status", &pax_disallow_map32bit_status_global);
|
||||
#endif
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
TUNABLE_INT("hardening.pax.aslr.compat.status", &pax_aslr_compat_status);
|
||||
TUNABLE_INT("hardening.pax.aslr.compat.mmap_len", &pax_aslr_compat_mmap_len);
|
||||
TUNABLE_INT("hardening.pax.aslr.compat.stack_len", &pax_aslr_compat_stack_len);
|
||||
TUNABLE_INT("hardening.pax.aslr.compat.exec_len", &pax_aslr_compat_exec_len);
|
||||
TUNABLE_INT("hardening.pax.aslr.compat.vdso_len", &pax_aslr_compat_vdso_len);
|
||||
#endif
|
||||
|
||||
#ifdef PAX_SYSCTLS
|
||||
SYSCTL_DECL(_hardening_pax);
|
||||
|
||||
SYSCTL_NODE(_hardening_pax, OID_AUTO, aslr, CTLFLAG_RD, 0,
|
||||
"Address Space Layout Randomization.");
|
||||
SYSCTL_HBSD_4STATE(pax_aslr_status, pr_hbsd.aslr.status,
|
||||
_hardening_pax_aslr, status,
|
||||
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE);
|
||||
|
||||
/* COMPAT_FREEBSD32 and linuxulator. */
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
SYSCTL_NODE(_hardening_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0,
|
||||
"Settings for COMPAT_FREEBSD32 and linuxulator.");
|
||||
SYSCTL_HBSD_4STATE(pax_aslr_compat_status, pr_hbsd.aslr.compat_status,
|
||||
_hardening_pax_aslr_compat, status,
|
||||
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON);
|
||||
#endif /* COMPAT_FREEBSD32 */
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
SYSCTL_NODE(_hardening_pax, OID_AUTO, disallow_map32bit, CTLFLAG_RD, 0,
|
||||
"Disallow MAP_32BIT mode mmap(2) calls.");
|
||||
SYSCTL_HBSD_4STATE(pax_disallow_map32bit_status_global, pr_hbsd.aslr.disallow_map32bit_status,
|
||||
_hardening_pax_disallow_map32bit, status,
|
||||
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE);
|
||||
#endif /* MAP_32BIT */
|
||||
|
||||
#endif /* PAX_SYSCTLS */
|
||||
|
||||
|
||||
/*
|
||||
* ASLR functions
|
||||
*/
|
||||
|
||||
static void
|
||||
pax_aslr_sysinit(void)
|
||||
{
|
||||
|
||||
switch (pax_aslr_status) {
|
||||
case PAX_FEATURE_DISABLED:
|
||||
case PAX_FEATURE_OPTIN:
|
||||
case PAX_FEATURE_OPTOUT:
|
||||
case PAX_FEATURE_FORCE_ENABLED:
|
||||
break;
|
||||
default:
|
||||
printf("[HBSD ASLR] WARNING, invalid PAX settings in loader.conf!"
|
||||
" (pax_aslr_status = %d)\n", pax_aslr_status);
|
||||
pax_aslr_status = PAX_FEATURE_FORCE_ENABLED;
|
||||
break;
|
||||
}
|
||||
printf("[HBSD ASLR] status: %s\n", pax_status_str[pax_aslr_status]);
|
||||
printf("[HBSD ASLR] mmap: %d bit\n", pax_aslr_mmap_len);
|
||||
printf("[HBSD ASLR] exec base: %d bit\n", pax_aslr_exec_len);
|
||||
printf("[HBSD ASLR] stack: %d bit\n", pax_aslr_stack_len);
|
||||
printf("[HBSD ASLR] vdso: %d bit\n", pax_aslr_vdso_len);
|
||||
#ifdef MAP_32BIT
|
||||
printf("[HBSD ASLR] map32bit: %d bit\n", pax_aslr_map32bit_len);
|
||||
|
||||
switch (pax_disallow_map32bit_status_global) {
|
||||
case PAX_FEATURE_DISABLED:
|
||||
case PAX_FEATURE_OPTIN:
|
||||
case PAX_FEATURE_OPTOUT:
|
||||
case PAX_FEATURE_FORCE_ENABLED:
|
||||
break;
|
||||
default:
|
||||
printf("[HBSD ASLR] WARNING, invalid settings in loader.conf!"
|
||||
" (hardening.pax.disallow_map32bit.status = %d)\n",
|
||||
pax_disallow_map32bit_status_global);
|
||||
pax_disallow_map32bit_status_global = PAX_FEATURE_FORCE_ENABLED;
|
||||
}
|
||||
printf("[HBSD ASLR] disallow MAP_32BIT mode mmap: %s\n",
|
||||
pax_status_str[pax_disallow_map32bit_status_global]);
|
||||
#endif
|
||||
}
|
||||
SYSINIT(pax_aslr, SI_SUB_PAX, SI_ORDER_SECOND, pax_aslr_sysinit, NULL);
|
||||
|
||||
bool
|
||||
pax_aslr_active(struct proc *p)
|
||||
{
|
||||
pax_flag_t flags;
|
||||
|
||||
pax_get_flags(p, &flags);
|
||||
|
||||
CTR3(KTR_PAX, "%s: pid = %d p_pax = %x",
|
||||
__func__, p->p_pid, flags);
|
||||
|
||||
if ((flags & PAX_NOTE_ASLR) == PAX_NOTE_ASLR)
|
||||
return (true);
|
||||
|
||||
if ((flags & PAX_NOTE_NOASLR) == PAX_NOTE_NOASLR)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_init_vmspace(struct proc *p)
|
||||
{
|
||||
struct vmspace *vm;
|
||||
unsigned long rand_buf;
|
||||
int try;
|
||||
|
||||
vm = p->p_vmspace;
|
||||
KASSERT(vm != NULL, ("%s: vm is null", __func__));
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_DELTA_MMAP_LSB,
|
||||
pax_aslr_mmap_len);
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_exec = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_DELTA_EXEC_LSB,
|
||||
pax_aslr_exec_len);
|
||||
|
||||
try = 3;
|
||||
try_again:
|
||||
/*
|
||||
* In stack case we generate a bigger random, which consists
|
||||
* of two parts.
|
||||
* The first upper part [pax_aslr_stack_len .. PAGE_SHIFT+1]
|
||||
* applied to mapping, the second lower part [PAGE_SHIFT .. 3]
|
||||
* applied in the mapping as gap.
|
||||
*/
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_DELTA_STACK_WITH_GAP_LSB,
|
||||
pax_aslr_stack_len);
|
||||
vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
rand_buf = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_DELTA_VDSO_LSB,
|
||||
pax_aslr_vdso_len);
|
||||
|
||||
/*
|
||||
* Place the vdso between the stacktop and
|
||||
* vm_max_user-PAGE_SIZE.
|
||||
*
|
||||
* In future this will change, to place them between the
|
||||
* stack and heap.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This check required to handle the case
|
||||
* when PAGE_ALIGN(vm->vm_aslr_delta_stack) == 0.
|
||||
*/
|
||||
if ((vm->vm_aslr_delta_stack & (-1UL << PAX_ASLR_DELTA_VDSO_LSB)) != 0) {
|
||||
if (rand_buf > vm->vm_aslr_delta_stack) {
|
||||
rand_buf = rand_buf %
|
||||
((unsigned long)vm->vm_aslr_delta_stack &
|
||||
(-1UL << PAX_ASLR_DELTA_STACK_LSB));
|
||||
rand_buf &= (-1UL << PAX_ASLR_DELTA_VDSO_LSB);
|
||||
}
|
||||
} else if (try > 0) {
|
||||
try--;
|
||||
goto try_again;
|
||||
} else {
|
||||
/* XXX: Instead of 0, should we place them at the end of heap? */
|
||||
pax_log_aslr(p, PAX_LOG_DEFAULT, "%s check your /boot/loader.conf ...", __func__);
|
||||
rand_buf = 0;
|
||||
}
|
||||
vm->vm_aslr_delta_vdso = rand_buf;
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_map32bit = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_DELTA_MAP32BIT_LSB,
|
||||
pax_aslr_map32bit_len);
|
||||
#endif
|
||||
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_mmap=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_mmap);
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_stack=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_stack);
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_exec=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_exec);
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_vdso=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_vdso);
|
||||
#ifdef MAP_32BIT
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_map32bit=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_map32bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
static void
|
||||
pax_compat_aslr_sysinit(void)
|
||||
{
|
||||
|
||||
switch (pax_aslr_compat_status) {
|
||||
case PAX_FEATURE_DISABLED:
|
||||
case PAX_FEATURE_OPTIN:
|
||||
case PAX_FEATURE_OPTOUT:
|
||||
case PAX_FEATURE_FORCE_ENABLED:
|
||||
break;
|
||||
default:
|
||||
printf("[HBSD ASLR (compat)] WARNING, invalid PAX settings in loader.conf! "
|
||||
"(pax_aslr_compat_status = %d)\n", pax_aslr_compat_status);
|
||||
pax_aslr_compat_status = PAX_FEATURE_FORCE_ENABLED;
|
||||
break;
|
||||
}
|
||||
printf("[HBSD ASLR (compat)] status: %s\n", pax_status_str[pax_aslr_compat_status]);
|
||||
printf("[HBSD ASLR (compat)] mmap: %d bit\n", pax_aslr_compat_mmap_len);
|
||||
printf("[HBSD ASLR (compat)] exec base: %d bit\n", pax_aslr_compat_exec_len);
|
||||
printf("[HBSD ASLR (compat)] stack: %d bit\n", pax_aslr_compat_stack_len);
|
||||
printf("[HBSD ASLR (compat)] vdso: %d bit\n", pax_aslr_compat_vdso_len);
|
||||
}
|
||||
SYSINIT(pax_compat_aslr, SI_SUB_PAX, SI_ORDER_SECOND, pax_compat_aslr_sysinit, NULL);
|
||||
|
||||
void
|
||||
pax_aslr_init_vmspace32(struct proc *p)
|
||||
{
|
||||
struct vmspace *vm;
|
||||
long rand_buf;
|
||||
|
||||
vm = p->p_vmspace;
|
||||
KASSERT(vm != NULL, ("%s: vm is null", __func__));
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_COMPAT_DELTA_MMAP_LSB,
|
||||
pax_aslr_compat_mmap_len);
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_stack = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_COMPAT_DELTA_STACK_LSB,
|
||||
pax_aslr_compat_stack_len);
|
||||
vm->vm_aslr_delta_stack = ALIGN(vm->vm_aslr_delta_stack);
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_exec = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_COMPAT_DELTA_EXEC_LSB,
|
||||
pax_aslr_compat_exec_len);
|
||||
|
||||
arc4rand(&rand_buf, sizeof(rand_buf), 0);
|
||||
vm->vm_aslr_delta_vdso = PAX_ASLR_DELTA(rand_buf,
|
||||
PAX_ASLR_COMPAT_DELTA_VDSO_LSB,
|
||||
pax_aslr_compat_vdso_len);
|
||||
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_mmap=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_mmap);
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_stack=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_stack);
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_exec=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_exec);
|
||||
CTR2(KTR_PAX, "%s: vm_aslr_delta_vdso=%p\n",
|
||||
__func__, (void *)vm->vm_aslr_delta_vdso);
|
||||
}
|
||||
#endif /* COMPAT_FREEBSD32 */
|
||||
|
||||
void
|
||||
pax_aslr_init(struct image_params *imgp)
|
||||
{
|
||||
struct proc *p;
|
||||
|
||||
KASSERT(imgp != NULL, ("%s: imgp is null", __func__));
|
||||
p = imgp->proc;
|
||||
|
||||
if (!pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
if (imgp->sysent->sv_pax_aslr_init != NULL)
|
||||
imgp->sysent->sv_pax_aslr_init(p);
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_init_prison(struct prison *pr)
|
||||
{
|
||||
struct prison *pr_p;
|
||||
|
||||
CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
|
||||
__func__, pr->pr_name);
|
||||
|
||||
if (pr == &prison0) {
|
||||
/* prison0 has no parent, use globals */
|
||||
pr->pr_hbsd.aslr.status = pax_aslr_status;
|
||||
#ifdef MAP_32BIT
|
||||
pr->pr_hbsd.aslr.disallow_map32bit_status =
|
||||
pax_disallow_map32bit_status_global;
|
||||
#endif
|
||||
} else {
|
||||
KASSERT(pr->pr_parent != NULL,
|
||||
("%s: pr->pr_parent == NULL", __func__));
|
||||
pr_p = pr->pr_parent;
|
||||
|
||||
pr->pr_hbsd.aslr.status = pr_p->pr_hbsd.aslr.status;
|
||||
#ifdef MAP_32BIT
|
||||
pr->pr_hbsd.aslr.disallow_map32bit_status =
|
||||
pr_p->pr_hbsd.aslr.disallow_map32bit_status;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
void
|
||||
pax_aslr_init_prison32(struct prison *pr)
|
||||
{
|
||||
struct prison *pr_p;
|
||||
|
||||
CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
|
||||
__func__, pr->pr_name);
|
||||
|
||||
if (pr == &prison0) {
|
||||
/* prison0 has no parent, use globals */
|
||||
|
||||
pr->pr_hbsd.aslr.compat_status = pax_aslr_compat_status;
|
||||
} else {
|
||||
KASSERT(pr->pr_parent != NULL,
|
||||
("%s: pr->pr_parent == NULL", __func__));
|
||||
pr_p = pr->pr_parent;
|
||||
|
||||
pr->pr_hbsd.aslr.compat_status = pr_p->pr_hbsd.aslr.compat_status;
|
||||
}
|
||||
}
|
||||
#endif /* COMPAT_FREEBSD32 */
|
||||
|
||||
void
|
||||
pax_aslr_mmap(struct proc *p, vm_offset_t *addr, vm_offset_t orig_addr, int mmap_flags)
|
||||
{
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
if (((mmap_flags & MAP_32BIT) == MAP_32BIT) || !pax_aslr_active(p))
|
||||
#else
|
||||
if (!pax_aslr_active(p))
|
||||
#endif
|
||||
return;
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
KASSERT((mmap_flags & MAP_32BIT) != MAP_32BIT,
|
||||
("%s: we can't handle MAP_32BIT mapping here", __func__));
|
||||
#endif
|
||||
KASSERT((mmap_flags & MAP_FIXED) != MAP_FIXED,
|
||||
("%s: we can't randomize MAP_FIXED mapping", __func__));
|
||||
|
||||
/*
|
||||
* From original PaX doc:
|
||||
*
|
||||
* PaX applies randomization (delta_mmap) to TASK_UNMAPPED_BASE in bits 12-27
|
||||
* (16 bits) and ignores the hint for file mappings (unfortunately there is
|
||||
* a 'feature' in linuxthreads where the thread stack mappings do not specify
|
||||
* MAP_FIXED but still expect that behaviour so the hint cannot be overriden
|
||||
* for anonymous mappings).
|
||||
*
|
||||
* https://github.com/HardenedBSD/pax-docs-mirror/blob/master/randmmap.txt#L30
|
||||
*/
|
||||
if ((orig_addr == 0) || !(mmap_flags & MAP_ANON)) {
|
||||
CTR4(KTR_PAX, "%s: applying to %p orig_addr=%p mmap_flags=%x\n",
|
||||
__func__, (void *)*addr, (void *)orig_addr, mmap_flags);
|
||||
*addr += p->p_vmspace->vm_aslr_delta_mmap;
|
||||
CTR2(KTR_PAX, "%s: result %p\n", __func__, (void *)*addr);
|
||||
} else
|
||||
CTR4(KTR_PAX, "%s: not applying to %p orig_addr=%p mmap_flags=%x\n",
|
||||
__func__, (void *)*addr, (void *)orig_addr, mmap_flags);
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_rtld(struct proc *p, u_long *addr)
|
||||
{
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
|
||||
if (!pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
*addr += p->p_vmspace->vm_aslr_delta_mmap;
|
||||
CTR2(KTR_PAX, "%s: result %p\n", __func__, (void *)*addr);
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_stack(struct proc *p, vm_offset_t *addr)
|
||||
{
|
||||
uintptr_t orig_addr;
|
||||
uintptr_t random;
|
||||
|
||||
if (!pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
orig_addr = *addr;
|
||||
|
||||
/*
|
||||
* Apply the random offset to the mapping.
|
||||
* This should page aligned.
|
||||
*/
|
||||
random = p->p_vmspace->vm_aslr_delta_stack;
|
||||
random &= (-1UL << PAX_ASLR_DELTA_STACK_LSB);
|
||||
*addr -= random;
|
||||
|
||||
CTR3(KTR_PAX, "%s: orig_addr=%p, new_addr=%p\n",
|
||||
__func__, (void *)orig_addr, (void *)*addr);
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_stack_with_gap(struct proc *p, vm_offset_t *addr)
|
||||
{
|
||||
uintptr_t orig_addr;
|
||||
uintptr_t random;
|
||||
|
||||
if (!pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
orig_addr = *addr;
|
||||
/*
|
||||
* Apply the random gap offset withing the page.
|
||||
*/
|
||||
random = p->p_vmspace->vm_aslr_delta_stack;
|
||||
*addr -= random;
|
||||
|
||||
CTR3(KTR_PAX, "%s: orig_addr=%p, new_addr=%p\n",
|
||||
__func__, (void *)orig_addr, (void *)*addr);
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_execbase(struct proc *p, u_long *et_dyn_addrp)
|
||||
{
|
||||
|
||||
if (!pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
*et_dyn_addrp += p->p_vmspace->vm_aslr_delta_exec;
|
||||
}
|
||||
|
||||
void
|
||||
pax_aslr_vdso(struct proc *p, vm_offset_t *addr)
|
||||
{
|
||||
uintptr_t orig_addr;
|
||||
|
||||
if (!pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
orig_addr = *addr;
|
||||
*addr -= p->p_vmspace->vm_aslr_delta_vdso;
|
||||
|
||||
CTR3(KTR_PAX, "%s: orig_addr=%p, new_addr=%p\n",
|
||||
__func__, (void *)orig_addr, (void *)*addr);
|
||||
}
|
||||
|
||||
pax_flag_t
|
||||
pax_aslr_setup_flags(struct image_params *imgp, struct thread *td, pax_flag_t mode)
|
||||
{
|
||||
struct prison *pr;
|
||||
pax_flag_t flags;
|
||||
uint32_t status;
|
||||
|
||||
KASSERT(imgp->proc == td->td_proc,
|
||||
("%s: imgp->proc != td->td_proc", __func__));
|
||||
|
||||
flags = 0;
|
||||
status = 0;
|
||||
|
||||
pr = pax_get_prison_td(td);
|
||||
status = pr->pr_hbsd.aslr.status;
|
||||
|
||||
if (status == PAX_FEATURE_DISABLED) {
|
||||
flags &= ~PAX_NOTE_ASLR;
|
||||
flags |= PAX_NOTE_NOASLR;
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
if (status == PAX_FEATURE_FORCE_ENABLED) {
|
||||
flags |= PAX_NOTE_ASLR;
|
||||
flags &= ~PAX_NOTE_NOASLR;
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
if (status == PAX_FEATURE_OPTIN) {
|
||||
if (mode & PAX_NOTE_ASLR) {
|
||||
flags |= PAX_NOTE_ASLR;
|
||||
flags &= ~PAX_NOTE_NOASLR;
|
||||
} else {
|
||||
flags &= ~PAX_NOTE_ASLR;
|
||||
flags |= PAX_NOTE_NOASLR;
|
||||
}
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
if (status == PAX_FEATURE_OPTOUT) {
|
||||
if (mode & PAX_NOTE_NOASLR) {
|
||||
flags &= ~PAX_NOTE_ASLR;
|
||||
flags |= PAX_NOTE_NOASLR;
|
||||
} else {
|
||||
flags |= PAX_NOTE_ASLR;
|
||||
flags &= ~PAX_NOTE_NOASLR;
|
||||
}
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unknown status, force ASLR.
|
||||
*/
|
||||
flags |= PAX_NOTE_ASLR;
|
||||
flags &= ~PAX_NOTE_NOASLR;
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
#ifdef MAP_32BIT
|
||||
void
|
||||
pax_aslr_mmap_map_32bit(struct proc *p, vm_offset_t *addr, vm_offset_t orig_addr, int mmap_flags)
|
||||
{
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
|
||||
if (((mmap_flags & MAP_32BIT) != MAP_32BIT) || !pax_aslr_active(p))
|
||||
return;
|
||||
|
||||
KASSERT((mmap_flags & MAP_32BIT) == MAP_32BIT,
|
||||
("%s: we can't handle not MAP_32BIT mapping here", __func__));
|
||||
KASSERT((mmap_flags & MAP_FIXED) != MAP_FIXED,
|
||||
("%s: we can't randomize MAP_FIXED mapping", __func__));
|
||||
|
||||
/*
|
||||
* From original PaX doc:
|
||||
*
|
||||
* PaX applies randomization (delta_mmap) to TASK_UNMAPPED_BASE in bits 12-27
|
||||
* (16 bits) and ignores the hint for file mappings (unfortunately there is
|
||||
* a 'feature' in linuxthreads where the thread stack mappings do not specify
|
||||
* MAP_FIXED but still expect that behaviour so the hint cannot be overriden
|
||||
* for anonymous mappings).
|
||||
*
|
||||
* https://github.com/HardenedBSD/pax-docs-mirror/blob/master/randmmap.txt#L30
|
||||
*/
|
||||
if ((orig_addr == 0) || !(mmap_flags & MAP_ANON)) {
|
||||
CTR4(KTR_PAX, "%s: applying to %p orig_addr=%p mmap_flags=%x\n",
|
||||
__func__, (void *)*addr, (void *)orig_addr, mmap_flags);
|
||||
|
||||
*addr += p->p_vmspace->vm_aslr_delta_map32bit;
|
||||
CTR2(KTR_PAX, "%s: result %p\n", __func__, (void *)*addr);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
pax_disallow_map32bit_active(struct thread *td, int mmap_flags)
|
||||
{
|
||||
pax_flag_t flags;
|
||||
|
||||
if ((mmap_flags & MAP_32BIT) != MAP_32BIT)
|
||||
/*
|
||||
* Fast path, the mmap request does not
|
||||
* contains MAP_32BIT flag.
|
||||
*/
|
||||
return (false);
|
||||
|
||||
pax_get_flags_td(td, &flags);
|
||||
|
||||
CTR3(KTR_PAX, "%S: pid = %d p_pax = %x",
|
||||
__func__, td->td_proc->p_pid, flags);
|
||||
|
||||
if ((flags & PAX_NOTE_DISALLOWMAP32BIT) == PAX_NOTE_DISALLOWMAP32BIT)
|
||||
return (true);
|
||||
|
||||
if ((flags & PAX_NOTE_NODISALLOWMAP32BIT) == PAX_NOTE_NODISALLOWMAP32BIT)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
pax_flag_t
|
||||
pax_disallow_map32bit_setup_flags(struct image_params *imgp, struct thread *td, pax_flag_t mode)
|
||||
{
|
||||
struct prison *pr;
|
||||
pax_flag_t flags;
|
||||
uint32_t status;
|
||||
|
||||
KASSERT(imgp->proc == td->td_proc,
|
||||
("%s: imgp->proc != td->td_proc", __func__));
|
||||
|
||||
flags = 0;
|
||||
status = 0;
|
||||
|
||||
pr = pax_get_prison_td(td);
|
||||
status = pr->pr_hbsd.aslr.disallow_map32bit_status;
|
||||
|
||||
if (status == PAX_FEATURE_DISABLED) {
|
||||
flags &= ~PAX_NOTE_DISALLOWMAP32BIT;
|
||||
flags |= PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
if (status == PAX_FEATURE_FORCE_ENABLED) {
|
||||
flags &= ~PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
flags |= PAX_NOTE_DISALLOWMAP32BIT;
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
if (status == PAX_FEATURE_OPTIN) {
|
||||
if (mode & PAX_NOTE_DISALLOWMAP32BIT) {
|
||||
flags |= PAX_NOTE_DISALLOWMAP32BIT;
|
||||
flags &= ~PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
} else {
|
||||
flags &= ~PAX_NOTE_DISALLOWMAP32BIT;
|
||||
flags |= PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
}
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
if (status == PAX_FEATURE_OPTOUT) {
|
||||
if (mode & PAX_NOTE_NODISALLOWMAP32BIT) {
|
||||
flags |= PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
flags &= ~PAX_NOTE_DISALLOWMAP32BIT;
|
||||
} else {
|
||||
flags &= ~PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
flags |= PAX_NOTE_DISALLOWMAP32BIT;
|
||||
}
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
/* Unknown status, force MAP32 restriction. */
|
||||
flags |= PAX_NOTE_DISALLOWMAP32BIT;
|
||||
flags &= ~PAX_NOTE_NODISALLOWMAP32BIT;
|
||||
|
||||
return (flags);
|
||||
}
|
||||
#endif /* MAP_32BIT */
|
||||
|
||||
334
sys/hardenedbsd/hbsd_pax_common.c
Normal file
334
sys/hardenedbsd/hbsd_pax_common.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/*-
|
||||
* Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
|
||||
* Copyright (c) 2013-2016, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
|
||||
* Copyright (c) 2014-2015, by Shawn Webb <shawn.webb@hardenedbsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#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/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/_inttypes.h>
|
||||
|
||||
static void pax_set_flags(struct proc *p, struct thread *td, const pax_flag_t flags);
|
||||
static void pax_set_flags_td(struct thread *td, const pax_flag_t flags);
|
||||
static int pax_validate_flags(const pax_flag_t flags);
|
||||
static int pax_check_conflicting_modes(const pax_flag_t mode);
|
||||
|
||||
CTASSERT((sizeof((struct proc *)NULL)->p_pax) == sizeof(pax_flag_t));
|
||||
CTASSERT((sizeof((struct thread *)NULL)->td_pax) == sizeof(pax_flag_t));
|
||||
|
||||
SYSCTL_NODE(_hardening, OID_AUTO, pax, CTLFLAG_RD, 0,
|
||||
"PaX (exploit mitigation) features.");
|
||||
|
||||
const char *pax_status_str[] = {
|
||||
[PAX_FEATURE_DISABLED] = "disabled",
|
||||
[PAX_FEATURE_OPTIN] = "opt-in",
|
||||
[PAX_FEATURE_OPTOUT] = "opt-out",
|
||||
[PAX_FEATURE_FORCE_ENABLED] = "force enabled",
|
||||
};
|
||||
|
||||
const char *pax_status_simple_str[] = {
|
||||
[PAX_FEATURE_SIMPLE_DISABLED] = "disabled",
|
||||
[PAX_FEATURE_SIMPLE_ENABLED] = "enabled"
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* @brief Get the current process prison.
|
||||
*
|
||||
* @param p The current process pointer.
|
||||
*
|
||||
* @return prion0's address if failed or kernel process
|
||||
* the actual process' prison's address else
|
||||
*
|
||||
*/
|
||||
struct prison *
|
||||
pax_get_prison(struct proc *p)
|
||||
{
|
||||
|
||||
KASSERT(p != NULL, ("%s: p == NULL", __func__));
|
||||
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
|
||||
if (p->p_ucred == NULL)
|
||||
return (&prison0);
|
||||
|
||||
return (p->p_ucred->cr_prison);
|
||||
}
|
||||
|
||||
struct prison *
|
||||
pax_get_prison_td(struct thread *td)
|
||||
{
|
||||
|
||||
if (td == NULL || td->td_ucred == NULL)
|
||||
return (&prison0);
|
||||
|
||||
return (td->td_ucred->cr_prison);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Get the current PaX status from process.
|
||||
*
|
||||
* @param p The controlled process pointer.
|
||||
* @param flags Where to write the current state.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void
|
||||
pax_get_flags(struct proc *p, pax_flag_t *flags)
|
||||
{
|
||||
|
||||
KASSERT(p == curthread->td_proc,
|
||||
("%s: p != curthread->td_proc", __func__));
|
||||
|
||||
#ifdef HBSD_DEBUG
|
||||
struct thread *td;
|
||||
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
KASSERT(td->td_pax == p->p_pax, ("%s: td->td_pax != p->p_pax",
|
||||
__func__));
|
||||
}
|
||||
#endif
|
||||
|
||||
*flags = p->p_pax;
|
||||
}
|
||||
|
||||
void
|
||||
pax_get_flags_td(struct thread *td, pax_flag_t *flags)
|
||||
{
|
||||
|
||||
KASSERT(td == curthread,
|
||||
("%s: td != curthread", __func__));
|
||||
|
||||
#ifdef HBSD_DEBUG
|
||||
struct proc *p;
|
||||
struct thread *td0;
|
||||
|
||||
p = td->td_proc;
|
||||
|
||||
FOREACH_THREAD_IN_PROC(p, td0) {
|
||||
KASSERT(td0->td_proc == p,
|
||||
("%s: td0->td_proc != p", __func__));
|
||||
KASSERT(td0->td_pax == p->p_pax, ("%s: td0->td_pax != p->p_pax",
|
||||
__func__));
|
||||
}
|
||||
#endif
|
||||
|
||||
*flags = td->td_pax;
|
||||
}
|
||||
|
||||
void
|
||||
pax_set_flags(struct proc *p, struct thread *td, const pax_flag_t flags)
|
||||
{
|
||||
struct thread *td0;
|
||||
|
||||
KASSERT(td == curthread,
|
||||
("%s: td != curthread", __func__));
|
||||
KASSERT(td->td_proc == p,
|
||||
("%s: td->td_proc != p", __func__));
|
||||
|
||||
PROC_LOCK(p);
|
||||
p->p_pax = flags;
|
||||
FOREACH_THREAD_IN_PROC(p, td0) {
|
||||
pax_set_flags_td(td0, flags);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
|
||||
void
|
||||
pax_set_flags_td(struct thread *td, const pax_flag_t flags)
|
||||
{
|
||||
|
||||
td->td_pax = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* rename to pax_valid_flags, and change return values and type to bool
|
||||
*/
|
||||
static int
|
||||
pax_validate_flags(const pax_flag_t flags)
|
||||
{
|
||||
|
||||
if ((flags & ~PAX_NOTE_ALL) != 0)
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* same as pax_valid_flags
|
||||
*/
|
||||
static int
|
||||
pax_check_conflicting_modes(const pax_flag_t mode)
|
||||
{
|
||||
|
||||
if (((mode & PAX_NOTE_ALL_ENABLED) & ((mode & PAX_NOTE_ALL_DISABLED) >> 1)) != 0)
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* @bried Initialize the new process PaX state
|
||||
*
|
||||
* @param imgp Executable image's structure.
|
||||
* @param mode Requested mode.
|
||||
*
|
||||
* @return ENOEXEC on fail
|
||||
* 0 on success
|
||||
*/
|
||||
int
|
||||
pax_elf(struct image_params *imgp, struct thread *td, pax_flag_t mode)
|
||||
{
|
||||
pax_flag_t flags;
|
||||
|
||||
if (pax_validate_flags(mode) != 0) {
|
||||
pax_log_internal_imgp(imgp, PAX_LOG_DEFAULT,
|
||||
"unknown paxflags: %x", mode);
|
||||
pax_ulog_internal("unknown paxflags: %x\n", mode);
|
||||
|
||||
return (ENOEXEC);
|
||||
}
|
||||
|
||||
if (pax_check_conflicting_modes(mode) != 0) {
|
||||
/*
|
||||
* indicate flags inconsistencies in dmesg and in user terminal
|
||||
*/
|
||||
pax_log_internal_imgp(imgp, PAX_LOG_DEFAULT,
|
||||
"inconsistent paxflags: %x", mode);
|
||||
pax_ulog_internal("inconsistent paxflags: %x\n", mode);
|
||||
|
||||
return (ENOEXEC);
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
|
||||
#ifdef PAX_ASLR
|
||||
flags |= pax_aslr_setup_flags(imgp, td, mode);
|
||||
#ifdef MAP_32BIT
|
||||
flags |= pax_disallow_map32bit_setup_flags(imgp, td, mode);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CTR3(KTR_PAX, "%s : flags = %x mode = %x",
|
||||
__func__, flags, mode);
|
||||
|
||||
/*
|
||||
* Recheck the flags after the parsing: prevent broken setups.
|
||||
*/
|
||||
if (pax_validate_flags(flags) != 0) {
|
||||
pax_log_internal_imgp(imgp, PAX_LOG_DEFAULT,
|
||||
"unknown paxflags after the setup: %x", flags);
|
||||
pax_ulog_internal("unknown paxflags after the setup: %x\n", flags);
|
||||
|
||||
return (ENOEXEC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Recheck the flags after the parsing: prevent conflicting setups.
|
||||
* This check should be always false.
|
||||
*/
|
||||
if (pax_check_conflicting_modes(flags) != 0) {
|
||||
/*
|
||||
* indicate flags inconsistencies in dmesg and in user terminal
|
||||
*/
|
||||
pax_log_internal_imgp(imgp, PAX_LOG_DEFAULT,
|
||||
"inconsistent paxflags after the setup: %x", flags);
|
||||
pax_ulog_internal("inconsistent paxflags after the setup: %x\n", flags);
|
||||
|
||||
return (ENOEXEC);
|
||||
}
|
||||
|
||||
pax_set_flags(imgp->proc, td, flags);
|
||||
|
||||
/*
|
||||
* if we enable/disable features with secadm, print out a warning
|
||||
*/
|
||||
if (mode != 0) {
|
||||
pax_log_internal_imgp(imgp, PAX_LOG_DEFAULT,
|
||||
"the process has non-default settings");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief Print out PaX settings on boot time, and validate some of them.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void
|
||||
pax_sysinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
SYSINIT(pax, SI_SUB_PAX, SI_ORDER_FIRST, pax_sysinit, NULL);
|
||||
|
||||
/*
|
||||
* @brief Initialize prison's state.
|
||||
*
|
||||
* The prison0 state initialized with global state.
|
||||
* The child prisons state initialized with it's parent's state.
|
||||
*
|
||||
* @param pr Initializable prison's pointer.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void
|
||||
pax_init_prison(struct prison *pr)
|
||||
{
|
||||
|
||||
CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
|
||||
__func__, pr->pr_name);
|
||||
|
||||
pax_aslr_init_prison(pr);
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
pax_aslr_init_prison32(pr);
|
||||
#endif
|
||||
}
|
||||
|
||||
107
sys/hardenedbsd/hbsd_pax_internal.h
Normal file
107
sys/hardenedbsd/hbsd_pax_internal.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*-
|
||||
* Copyright (c) 2016, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __HBSD_PAX_INTERNAL_H
|
||||
#define __HBSD_PAX_INTERNAL_H
|
||||
|
||||
#define SYSCTL_HBSD_2STATE(g_status, pr_status, parent, name, access, desc) \
|
||||
static int sysctl ## parent ## _ ## name (SYSCTL_HANDLER_ARGS); \
|
||||
SYSCTL_PROC(parent, OID_AUTO, name, access, \
|
||||
NULL, 0, sysctl ## parent ## _ ## name, "I", \
|
||||
desc " status: " \
|
||||
"0 - disabled, " \
|
||||
"1 - enabled"); \
|
||||
\
|
||||
static int \
|
||||
sysctl ## parent ## _ ## name (SYSCTL_HANDLER_ARGS) \
|
||||
{ \
|
||||
struct prison *pr; \
|
||||
int err, val; \
|
||||
\
|
||||
pr = pax_get_prison_td(req->td); \
|
||||
\
|
||||
val = pr->pr_status; \
|
||||
err = sysctl_handle_int(oidp, &val, sizeof(int), req); \
|
||||
if (err || (req->newptr == NULL)) \
|
||||
return (err); \
|
||||
\
|
||||
switch (val) { \
|
||||
case PAX_FEATURE_SIMPLE_DISABLED: \
|
||||
case PAX_FEATURE_SIMPLE_ENABLED: \
|
||||
if (pr == &prison0) \
|
||||
g_status = val; \
|
||||
pr->pr_status = val; \
|
||||
break; \
|
||||
default: \
|
||||
return (EINVAL); \
|
||||
} \
|
||||
\
|
||||
return (0); \
|
||||
}
|
||||
|
||||
#define SYSCTL_HBSD_4STATE(g_status, pr_status, parent, name, access) \
|
||||
static int sysctl ## parent ## _ ## name (SYSCTL_HANDLER_ARGS); \
|
||||
SYSCTL_PROC(parent, OID_AUTO, name, access, \
|
||||
NULL, 0, sysctl ## parent ## _ ## name, "I", \
|
||||
"Restrictions status: " \
|
||||
"0 - disabled, " \
|
||||
"1 - opt-in, " \
|
||||
"2 - opt-out, " \
|
||||
"3 - force enabled"); \
|
||||
\
|
||||
static int \
|
||||
sysctl ## parent ## _ ## name (SYSCTL_HANDLER_ARGS) \
|
||||
{ \
|
||||
struct prison *pr; \
|
||||
int err, val; \
|
||||
\
|
||||
pr = pax_get_prison_td(req->td); \
|
||||
\
|
||||
val = pr->pr_status; \
|
||||
err = sysctl_handle_int(oidp, &val, sizeof(int), req); \
|
||||
if (err || (req->newptr == NULL)) \
|
||||
return (err); \
|
||||
\
|
||||
switch (val) { \
|
||||
case PAX_FEATURE_DISABLED: \
|
||||
case PAX_FEATURE_OPTIN: \
|
||||
case PAX_FEATURE_OPTOUT: \
|
||||
case PAX_FEATURE_FORCE_ENABLED: \
|
||||
if (pr == &prison0) \
|
||||
g_status = val; \
|
||||
pr->pr_status = val; \
|
||||
break; \
|
||||
default: \
|
||||
return (EINVAL); \
|
||||
} \
|
||||
\
|
||||
return (0); \
|
||||
}
|
||||
|
||||
#endif /* __HBSD_PAX_INTERNAL_H */
|
||||
380
sys/hardenedbsd/hbsd_pax_log.c
Normal file
380
sys/hardenedbsd/hbsd_pax_log.c
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
/*-
|
||||
* Copyright (c) 2014, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_pax.h"
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/jail.h>
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#ifdef DDB
|
||||
#include <ddb/ddb.h>
|
||||
#endif
|
||||
|
||||
#include "hbsd_pax_internal.h"
|
||||
|
||||
static void pax_log_log(struct proc *p, struct thread *td, pax_log_settings_t flags,
|
||||
const char *prefix, const char *fmt, va_list ap);
|
||||
static void pax_log_ulog(const char *prefix, const char *fmt, va_list ap);
|
||||
|
||||
#define PAX_LOG_FEATURES_STRING \
|
||||
"\020" \
|
||||
"\001PAGEEXEC" \
|
||||
"\002NOPAGEEXEC" \
|
||||
"\003MPROTECT" \
|
||||
"\004NOMPROTECT" \
|
||||
"\005SEGVGUARD" \
|
||||
"\006NOSEGVGUARD" \
|
||||
"\007ASLR" \
|
||||
"\010NOASLR" \
|
||||
"\011SHLIBRANDOM" \
|
||||
"\012NOSHLIBRANDOM" \
|
||||
"\013DISALLOWMAP32BIT" \
|
||||
"\014NODISALLOWMAP32BIT" \
|
||||
"\015<f12>" \
|
||||
"\016<f13>" \
|
||||
"\017<f14>" \
|
||||
"\020<f15>" \
|
||||
"\021<f16>" \
|
||||
"\022<f17>" \
|
||||
"\023<f18>" \
|
||||
"\024<f19>" \
|
||||
"\025<f20>" \
|
||||
"\026<f21>" \
|
||||
"\027<f22>" \
|
||||
"\030<f23>" \
|
||||
"\031<f24>" \
|
||||
"\032<f25>" \
|
||||
"\033<f26>" \
|
||||
"\034<f27>" \
|
||||
"\035<f28>" \
|
||||
"\036<f29>" \
|
||||
"\037<f30>" \
|
||||
"\040<f31>"
|
||||
|
||||
#define __HARDENING_LOG_TEMPLATE(MAIN, SUBJECT, prefix, name) \
|
||||
void \
|
||||
prefix##_log_##name(struct proc *p, pax_log_settings_t flags, \
|
||||
const char* fmt, ...) \
|
||||
{ \
|
||||
const char *prefix = "["#MAIN" "#SUBJECT"]"; \
|
||||
va_list args; \
|
||||
\
|
||||
if (hardening_log_log == 0) \
|
||||
return; \
|
||||
\
|
||||
va_start(args, fmt); \
|
||||
pax_log_log(p, NULL, flags, prefix, fmt, args); \
|
||||
va_end(args); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
prefix##_ulog_##name(const char* fmt, ...) \
|
||||
{ \
|
||||
const char *prefix = "["#MAIN" "#SUBJECT"]"; \
|
||||
va_list args; \
|
||||
\
|
||||
if (hardening_log_ulog == 0) \
|
||||
return; \
|
||||
\
|
||||
va_start(args, fmt); \
|
||||
pax_log_ulog(prefix, fmt, args); \
|
||||
va_end(args); \
|
||||
}
|
||||
|
||||
static int hardening_log_log = PAX_FEATURE_SIMPLE_ENABLED;
|
||||
static int hardening_log_ulog = PAX_FEATURE_SIMPLE_DISABLED;
|
||||
|
||||
TUNABLE_INT("hardening.log.log", &hardening_log_log);
|
||||
TUNABLE_INT("hardening.log.ulog", &hardening_log_ulog);
|
||||
|
||||
#ifdef PAX_SYSCTLS
|
||||
SYSCTL_NODE(_hardening, OID_AUTO, log, CTLFLAG_RD, 0,
|
||||
"Hardening related logging facility.");
|
||||
|
||||
SYSCTL_HBSD_2STATE(hardening_log_log, pr_hbsd.log.log, _hardening_log, log,
|
||||
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
|
||||
"log to syslog ");
|
||||
|
||||
SYSCTL_HBSD_2STATE(hardening_log_ulog, pr_hbsd.log.ulog, _hardening_log, ulog,
|
||||
CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE,
|
||||
"log to syslog ");
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
hardening_log_sysinit(void)
|
||||
{
|
||||
switch (hardening_log_log) {
|
||||
case PAX_FEATURE_SIMPLE_DISABLED:
|
||||
case PAX_FEATURE_SIMPLE_ENABLED:
|
||||
break;
|
||||
default:
|
||||
printf("[HBSD LOG] WARNING, invalid settings in loader.conf!"
|
||||
" (hardening.log.log = %d)\n", hardening_log_log);
|
||||
hardening_log_log = PAX_FEATURE_SIMPLE_ENABLED;
|
||||
}
|
||||
printf("[HBSD LOG] logging to system: %s\n",
|
||||
pax_status_simple_str[hardening_log_log]);
|
||||
|
||||
switch (hardening_log_ulog) {
|
||||
case PAX_FEATURE_SIMPLE_DISABLED:
|
||||
case PAX_FEATURE_SIMPLE_ENABLED:
|
||||
break;
|
||||
default:
|
||||
printf("[HBSD LOG] WARNING, invalid settings in loader.conf!"
|
||||
" (hardening.log.ulog = %d)\n", hardening_log_ulog);
|
||||
hardening_log_ulog = PAX_FEATURE_SIMPLE_ENABLED;
|
||||
}
|
||||
printf("[HBSD LOG] logging to user: %s\n",
|
||||
pax_status_simple_str[hardening_log_ulog]);
|
||||
}
|
||||
SYSINIT(hardening_log, SI_SUB_PAX, SI_ORDER_SECOND, hardening_log_sysinit, NULL);
|
||||
|
||||
void
|
||||
pax_log_init_prison(struct prison *pr)
|
||||
{
|
||||
struct prison *pr_p;
|
||||
|
||||
CTR2(KTR_PAX, "%s: Setting prison %s PaX variables\n",
|
||||
__func__, pr->pr_name);
|
||||
|
||||
if (pr == &prison0) {
|
||||
/* prison0 has no parent, use globals */
|
||||
pr->pr_hbsd.log.log = hardening_log_log;
|
||||
pr->pr_hbsd.log.ulog = hardening_log_ulog;
|
||||
} else {
|
||||
KASSERT(pr->pr_parent != NULL,
|
||||
("%s: pr->pr_parent == NULL", __func__));
|
||||
pr_p = pr->pr_parent;
|
||||
|
||||
pr->pr_hbsd.log.log = pr_p->pr_hbsd.log.log;
|
||||
pr->pr_hbsd.log.ulog = pr_p->pr_hbsd.log.ulog;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_pax_log_prefix(struct sbuf *sb, pax_log_settings_t flags, const char *prefix)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "%s ", prefix);
|
||||
}
|
||||
|
||||
static void
|
||||
_pax_log_indent(struct sbuf *sb, pax_log_settings_t flags)
|
||||
{
|
||||
|
||||
if ((flags & PAX_LOG_NO_INDENT) != PAX_LOG_NO_INDENT)
|
||||
sbuf_printf(sb, "\n -> ");
|
||||
}
|
||||
|
||||
static void
|
||||
_pax_log_proc_details(struct sbuf *sb, pax_log_settings_t flags, struct proc *p)
|
||||
{
|
||||
|
||||
if (p != NULL) {
|
||||
if ((flags & PAX_LOG_P_COMM) == PAX_LOG_P_COMM)
|
||||
sbuf_printf(sb, "p_comm: %s ", p->p_comm);
|
||||
|
||||
sbuf_printf(sb, "pid: %d ", p->p_pid);
|
||||
sbuf_printf(sb, "ppid: %d ", p->p_pptr->p_pid);
|
||||
|
||||
if ((flags & PAX_LOG_NO_P_PAX) != PAX_LOG_NO_P_PAX)
|
||||
sbuf_printf(sb, "p_pax: 0x%b ", p->p_pax, PAX_LOG_FEATURES_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_pax_log_thread_details(struct sbuf *sb, pax_log_settings_t flags, struct thread *td)
|
||||
{
|
||||
|
||||
if (td != NULL) {
|
||||
sbuf_printf(sb, "tid: %d ", td->td_tid);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_pax_log_details_end(struct sbuf *sb)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
_pax_log_imgp_details(struct sbuf *sb, pax_log_settings_t flags, struct image_params *imgp)
|
||||
{
|
||||
|
||||
if (imgp != NULL && imgp->args != NULL)
|
||||
if (imgp->args->fname != NULL)
|
||||
sbuf_printf(sb, "fname: %s ",
|
||||
imgp->args->fname);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pax_log_log(struct proc *p, struct thread *td, pax_log_settings_t flags,
|
||||
const char *prefix, const char *fmt, va_list ap)
|
||||
{
|
||||
struct sbuf *sb;
|
||||
|
||||
sb = sbuf_new_auto();
|
||||
if (sb == NULL)
|
||||
panic("%s: Could not allocate memory", __func__);
|
||||
|
||||
_pax_log_prefix(sb, flags, prefix);
|
||||
|
||||
sbuf_vprintf(sb, fmt, ap);
|
||||
if ((flags & PAX_LOG_SKIP_DETAILS) != PAX_LOG_SKIP_DETAILS) {
|
||||
_pax_log_indent(sb, flags);
|
||||
_pax_log_proc_details(sb, flags, p);
|
||||
_pax_log_thread_details(sb, flags, td);
|
||||
_pax_log_details_end(sb);
|
||||
}
|
||||
|
||||
if (sbuf_finish(sb) != 0)
|
||||
panic("%s: Could not generate message", __func__);
|
||||
|
||||
printf("%s", sbuf_data(sb));
|
||||
sbuf_delete(sb);
|
||||
}
|
||||
|
||||
static void
|
||||
pax_log_ulog(const char *prefix, const char *fmt, va_list ap)
|
||||
{
|
||||
struct sbuf *sb;
|
||||
|
||||
sb = sbuf_new_auto();
|
||||
if (sb == NULL)
|
||||
panic("%s: Could not allocate memory", __func__);
|
||||
|
||||
if (prefix != NULL)
|
||||
sbuf_printf(sb, "%s ", prefix);
|
||||
sbuf_vprintf(sb, fmt, ap);
|
||||
if (sbuf_finish(sb) != 0)
|
||||
panic("%s: Could not generate message", __func__);
|
||||
|
||||
hbsd_uprintf("%s", sbuf_data(sb)); \
|
||||
sbuf_delete(sb);
|
||||
}
|
||||
|
||||
void
|
||||
pax_printf_flags(struct proc *p, pax_log_settings_t flags)
|
||||
{
|
||||
|
||||
if (p != NULL) {
|
||||
printf("pax flags: 0x%b%c", p->p_pax, PAX_LOG_FEATURES_STRING,
|
||||
((flags & PAX_LOG_NO_NEWLINE) == PAX_LOG_NO_NEWLINE) ?
|
||||
' ' : '\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pax_printf_flags_td(struct thread *td, pax_log_settings_t flags)
|
||||
{
|
||||
|
||||
if (td != NULL) {
|
||||
printf("pax flags: 0x%b%c", td->td_pax, PAX_LOG_FEATURES_STRING,
|
||||
((flags & PAX_LOG_NO_NEWLINE) == PAX_LOG_NO_NEWLINE) ?
|
||||
' ' : '\n');
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DDB
|
||||
void
|
||||
pax_db_printf_flags(struct proc *p, pax_log_settings_t flags)
|
||||
{
|
||||
|
||||
if (p != NULL) {
|
||||
db_printf(" pax flags: 0x%b%c", p->p_pax, PAX_LOG_FEATURES_STRING,
|
||||
((flags & PAX_LOG_NO_NEWLINE) == PAX_LOG_NO_NEWLINE) ?
|
||||
' ' : '\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pax_db_printf_flags_td(struct thread *td, pax_log_settings_t flags)
|
||||
{
|
||||
|
||||
if (td != NULL) {
|
||||
db_printf(" pax flags: 0x%b%c", td->td_pax, PAX_LOG_FEATURES_STRING,
|
||||
((flags & PAX_LOG_NO_NEWLINE) == PAX_LOG_NO_NEWLINE) ?
|
||||
' ' : '\n');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__HARDENING_LOG_TEMPLATE(HBSD, INTERNAL, pax, internal);
|
||||
__HARDENING_LOG_TEMPLATE(HBSD, ASLR, pax, aslr);
|
||||
|
||||
void
|
||||
pax_log_internal_imgp(struct image_params *imgp, pax_log_settings_t flags, const char* fmt, ...)
|
||||
{
|
||||
const char *prefix = "[HBSD INTERNAL]";
|
||||
struct sbuf *sb;
|
||||
va_list args;
|
||||
|
||||
KASSERT(imgp != NULL, ("%s: imgp == NULL", __func__));
|
||||
|
||||
if (hardening_log_log == 0)
|
||||
return;
|
||||
|
||||
sb = sbuf_new_auto();
|
||||
if (sb == NULL)
|
||||
panic("%s: Could not allocate memory", __func__);
|
||||
|
||||
_pax_log_prefix(sb, flags, prefix);
|
||||
|
||||
va_start(args, fmt);
|
||||
sbuf_vprintf(sb, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if ((flags & PAX_LOG_SKIP_DETAILS) != PAX_LOG_SKIP_DETAILS) {
|
||||
_pax_log_indent(sb, flags);
|
||||
_pax_log_imgp_details(sb, flags, imgp);
|
||||
_pax_log_indent(sb, flags);
|
||||
_pax_log_proc_details(sb, flags, imgp->proc);
|
||||
_pax_log_details_end(sb);
|
||||
}
|
||||
|
||||
if (sbuf_finish(sb) != 0)
|
||||
panic("%s: Could not generate message", __func__);
|
||||
|
||||
printf("%s", sbuf_data(sb));
|
||||
sbuf_delete(sb);
|
||||
}
|
||||
|
|
@ -373,3 +373,6 @@ device xenpci # Xen HVM Hypervisor services driver
|
|||
|
||||
# VMware support
|
||||
device vmx # VMware VMXNET3 Ethernet
|
||||
|
||||
options PAX
|
||||
options PAX_ASLR
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_cpu.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
|
@ -34,6 +35,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
|
|
@ -88,6 +90,7 @@ struct sysentvec elf32_freebsd_sysvec = {
|
|||
.sv_shared_page_base = SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -486,11 +486,11 @@ osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
|
||||
regs->tf_esp = (int)fp;
|
||||
if (p->p_sysent->sv_sigcode_base != 0) {
|
||||
regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode -
|
||||
regs->tf_eip = p->p_sigcode_base + szsigcode -
|
||||
szosigcode;
|
||||
} else {
|
||||
/* a.out sysentvec does not use shared page */
|
||||
regs->tf_eip = p->p_sysent->sv_psstrings - szosigcode;
|
||||
regs->tf_eip = p->p_psstrings - szosigcode;
|
||||
}
|
||||
regs->tf_eflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucodesel;
|
||||
|
|
@ -618,7 +618,7 @@ freebsd4_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
}
|
||||
|
||||
regs->tf_esp = (int)sfp;
|
||||
regs->tf_eip = p->p_sysent->sv_sigcode_base + szsigcode -
|
||||
regs->tf_eip = p->p_sigcode_base + szsigcode -
|
||||
szfreebsd4_sigcode;
|
||||
regs->tf_eflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucodesel;
|
||||
|
|
@ -792,9 +792,9 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
}
|
||||
|
||||
regs->tf_esp = (int)sfp;
|
||||
regs->tf_eip = p->p_sysent->sv_sigcode_base;
|
||||
regs->tf_eip = p->p_sigcode_base;
|
||||
if (regs->tf_eip == 0)
|
||||
regs->tf_eip = p->p_sysent->sv_psstrings - szsigcode;
|
||||
regs->tf_eip = p->p_psstrings - szsigcode;
|
||||
regs->tf_eflags &= ~(PSL_T | PSL_D);
|
||||
regs->tf_cs = _ucodesel;
|
||||
regs->tf_ds = _udatasel;
|
||||
|
|
|
|||
|
|
@ -541,7 +541,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
|
|||
* mmap's return value.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
|
||||
p->p_vmspace->vm_maxsaddr = (char *)p->p_usrstack -
|
||||
lim_cur(p, RLIMIT_STACK);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/exec.h>
|
||||
|
|
@ -41,6 +43,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
|
|
@ -250,8 +253,8 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
|||
("unsafe elf_linux_fixup(), should be curproc"));
|
||||
|
||||
p = imgp->proc;
|
||||
arginfo = (struct ps_strings *)p->p_psstrings;
|
||||
issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0;
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szplatform);
|
||||
args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
|
|
@ -311,7 +314,7 @@ linux_copyout_strings(struct image_params *imgp)
|
|||
* Also deal with signal trampoline code for this exec type.
|
||||
*/
|
||||
p = imgp->proc;
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
arginfo = (struct ps_strings *)p->p_psstrings;
|
||||
destp = (caddr_t)arginfo - SPARE_USRSPACE - linux_szplatform -
|
||||
roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
|
||||
|
||||
|
|
@ -975,6 +978,7 @@ struct sysentvec linux_sysvec = {
|
|||
.sv_shared_page_base = LINUX_SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = linux_schedtail,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#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 +48,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/mount.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/pioctl.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procfs.h>
|
||||
|
|
@ -791,16 +792,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
|
|||
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;
|
||||
|
|
@ -821,6 +813,20 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
|
|||
error = exec_new_vmspace(imgp, sv);
|
||||
imgp->proc->p_sysent = sv;
|
||||
|
||||
et_dyn_addr = 0;
|
||||
if (hdr->e_type == ET_DYN) {
|
||||
/*
|
||||
* Honour the base load address from the dso if it is
|
||||
* non-zero for some reason.
|
||||
*/
|
||||
if (baddr == 0) {
|
||||
et_dyn_addr = ET_DYN_LOAD_ADDR;
|
||||
#ifdef PAX_ASLR
|
||||
pax_aslr_execbase(imgp->proc, &et_dyn_addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
if (error)
|
||||
return (error);
|
||||
|
|
@ -918,6 +924,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
|
|||
*/
|
||||
addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(imgp->proc,
|
||||
RLIMIT_DATA));
|
||||
#ifdef PAX_ASLR
|
||||
pax_aslr_rtld(imgp->proc, &addr);
|
||||
#endif
|
||||
PROC_UNLOCK(imgp->proc);
|
||||
|
||||
imgp->entry_addr = entry;
|
||||
|
|
@ -1011,7 +1020,7 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
|
|||
}
|
||||
if (imgp->sysent->sv_timekeep_base != 0) {
|
||||
AUXARGS_ENTRY(pos, AT_TIMEKEEP,
|
||||
imgp->sysent->sv_timekeep_base);
|
||||
imgp->proc->p_timekeep_base);
|
||||
}
|
||||
AUXARGS_ENTRY(pos, AT_STACKPROT, imgp->sysent->sv_shared_page_obj
|
||||
!= NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
|
||||
|
|
@ -1979,9 +1988,9 @@ __elfN(note_procstat_psstrings)(void *arg, struct sbuf *sb, size_t *sizep)
|
|||
KASSERT(*sizep == size, ("invalid size"));
|
||||
structsize = sizeof(ps_strings);
|
||||
#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
|
||||
ps_strings = PTROUT(p->p_sysent->sv_psstrings);
|
||||
ps_strings = PTROUT(p->p_psstrings);
|
||||
#else
|
||||
ps_strings = p->p_sysent->sv_psstrings;
|
||||
ps_strings = p->p_psstrings;
|
||||
#endif
|
||||
sbuf_bcat(sb, &structsize, sizeof(structsize));
|
||||
sbuf_bcat(sb, &ps_strings, sizeof(ps_strings));
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_init_path.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
|
@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/mutex.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/racct.h>
|
||||
#include <sys/resourcevar.h>
|
||||
|
|
@ -410,6 +412,7 @@ struct sysentvec null_sysvec = {
|
|||
.sv_fetch_syscall_args = null_fetch_syscall_args,
|
||||
.sv_syscallnames = NULL,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -476,6 +479,11 @@ proc0_init(void *dummy __unused)
|
|||
p->p_flag = P_SYSTEM | P_INMEM;
|
||||
p->p_flag2 = 0;
|
||||
p->p_state = PRS_NORMAL;
|
||||
#ifdef PAX
|
||||
p->p_pax = PAX_NOTE_ALL_DISABLED;
|
||||
#endif
|
||||
p->p_usrstack = USRSTACK;
|
||||
p->p_psstrings = PS_STRINGS;
|
||||
knlist_init_mtx(&p->p_klist, &p->p_mtx);
|
||||
STAILQ_INIT(&p->p_ktr);
|
||||
p->p_nice = NZERO;
|
||||
|
|
@ -493,6 +501,9 @@ proc0_init(void *dummy __unused)
|
|||
td->td_flags = TDF_INMEM;
|
||||
td->td_pflags = TDP_KTHREAD;
|
||||
td->td_cpuset = cpuset_thread0();
|
||||
#ifdef PAX
|
||||
td->td_pax = PAX_NOTE_ALL_DISABLED;
|
||||
#endif
|
||||
prison0_init();
|
||||
p->p_peers = 0;
|
||||
p->p_leader = p;
|
||||
|
|
@ -713,7 +724,7 @@ start_init(void *dummy)
|
|||
/*
|
||||
* Need just enough stack to hold the faked-up "execve()" arguments.
|
||||
*/
|
||||
addr = p->p_sysent->sv_usrstack - PAGE_SIZE;
|
||||
addr = p->p_usrstack - PAGE_SIZE;
|
||||
if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 0,
|
||||
VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0)
|
||||
panic("init: couldn't allocate argument space");
|
||||
|
|
@ -740,7 +751,7 @@ start_init(void *dummy)
|
|||
* Move out the boot flag argument.
|
||||
*/
|
||||
options = 0;
|
||||
ucp = (char *)p->p_sysent->sv_usrstack;
|
||||
ucp = (char *)p->p_usrstack;
|
||||
(void)subyte(--ucp, 0); /* trailing zero */
|
||||
if (boothowto & RB_SINGLE) {
|
||||
(void)subyte(--ucp, 's');
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include "opt_hwpmc_hooks.h"
|
||||
#include "opt_kdtrace.h"
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_pax.h"
|
||||
#include "opt_vm.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/imgact_elf.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/pioctl.h>
|
||||
|
|
@ -128,11 +130,6 @@ SYSCTL_INT(_kern, OID_AUTO, disallow_high_osrel, CTLFLAG_RW,
|
|||
&disallow_high_osrel, 0,
|
||||
"Disallow execution of binaries built for higher version of the world");
|
||||
|
||||
static int map_at_zero = 0;
|
||||
TUNABLE_INT("security.bsd.map_at_zero", &map_at_zero);
|
||||
SYSCTL_INT(_security_bsd, OID_AUTO, map_at_zero, CTLFLAG_RW, &map_at_zero, 0,
|
||||
"Permit processes to map an object at virtual address 0.");
|
||||
|
||||
static int
|
||||
sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
|
|
@ -143,12 +140,12 @@ sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS)
|
|||
#ifdef SCTL_MASK32
|
||||
if (req->flags & SCTL_MASK32) {
|
||||
unsigned int val;
|
||||
val = (unsigned int)p->p_sysent->sv_psstrings;
|
||||
val = (unsigned int)p->p_psstrings;
|
||||
error = SYSCTL_OUT(req, &val, sizeof(val));
|
||||
} else
|
||||
#endif
|
||||
error = SYSCTL_OUT(req, &p->p_sysent->sv_psstrings,
|
||||
sizeof(p->p_sysent->sv_psstrings));
|
||||
error = SYSCTL_OUT(req, &p->p_psstrings,
|
||||
sizeof(p->p_psstrings));
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -162,12 +159,12 @@ sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS)
|
|||
#ifdef SCTL_MASK32
|
||||
if (req->flags & SCTL_MASK32) {
|
||||
unsigned int val;
|
||||
val = (unsigned int)p->p_sysent->sv_usrstack;
|
||||
val = (unsigned int)p->p_usrstack;
|
||||
error = SYSCTL_OUT(req, &val, sizeof(val));
|
||||
} else
|
||||
#endif
|
||||
error = SYSCTL_OUT(req, &p->p_sysent->sv_usrstack,
|
||||
sizeof(p->p_sysent->sv_usrstack));
|
||||
error = SYSCTL_OUT(req, &p->p_usrstack,
|
||||
sizeof(p->p_usrstack));
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -452,6 +449,12 @@ interpret:
|
|||
imgp->vp = binvp;
|
||||
}
|
||||
|
||||
#ifdef PAX
|
||||
error = pax_elf(imgp, td, 0);
|
||||
if (error)
|
||||
goto exec_fail_dealloc;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check file permissions (also 'opens' file)
|
||||
*/
|
||||
|
|
@ -565,6 +568,11 @@ interpret:
|
|||
goto exec_fail_dealloc;
|
||||
}
|
||||
|
||||
p->p_psstrings = p->p_sysent->sv_psstrings;
|
||||
#ifdef PAX_ASLR
|
||||
pax_aslr_stack_with_gap(p, &(p->p_psstrings));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copy out strings (args and env) and initialize stack base
|
||||
*/
|
||||
|
|
@ -1045,10 +1053,7 @@ exec_new_vmspace(imgp, sv)
|
|||
* not disrupted
|
||||
*/
|
||||
map = &vmspace->vm_map;
|
||||
if (map_at_zero)
|
||||
sv_minuser = sv->sv_minuser;
|
||||
else
|
||||
sv_minuser = MAX(sv->sv_minuser, PAGE_SIZE);
|
||||
sv_minuser = MAX(sv->sv_minuser, PAGE_SIZE);
|
||||
if (vmspace->vm_refcnt == 1 && vm_map_min(map) == sv_minuser &&
|
||||
vm_map_max(map) == sv->sv_maxuser) {
|
||||
shmexit(vmspace);
|
||||
|
|
@ -1062,19 +1067,44 @@ exec_new_vmspace(imgp, sv)
|
|||
map = &vmspace->vm_map;
|
||||
}
|
||||
|
||||
#ifdef PAX_ASLR
|
||||
PROC_LOCK(imgp->proc);
|
||||
pax_aslr_init(imgp);
|
||||
PROC_UNLOCK(imgp->proc);
|
||||
#endif
|
||||
|
||||
/* Map a shared page */
|
||||
obj = sv->sv_shared_page_obj;
|
||||
if (obj != NULL) {
|
||||
p->p_shared_page_base = sv->sv_shared_page_base;
|
||||
#ifdef PAX_ASLR
|
||||
PROC_LOCK(imgp->proc);
|
||||
pax_aslr_vdso(p, &(p->p_shared_page_base));
|
||||
PROC_UNLOCK(imgp->proc);
|
||||
#endif
|
||||
vm_object_reference(obj);
|
||||
error = vm_map_fixed(map, obj, 0,
|
||||
sv->sv_shared_page_base, sv->sv_shared_page_len,
|
||||
p->p_shared_page_base, sv->sv_shared_page_len,
|
||||
VM_PROT_READ | VM_PROT_EXECUTE,
|
||||
VM_PROT_READ | VM_PROT_EXECUTE,
|
||||
MAP_INHERIT_SHARE | MAP_ACC_NO_CHARGE);
|
||||
if (error) {
|
||||
#ifdef PAX_ASLR
|
||||
pax_log_aslr(p, PAX_LOG_DEFAULT,
|
||||
"failed to map the shared-page @%p",
|
||||
(void *)p->p_shared_page_base);
|
||||
#endif
|
||||
vm_object_deallocate(obj);
|
||||
return (error);
|
||||
}
|
||||
|
||||
p->p_timekeep_base = sv->sv_timekeep_base;
|
||||
#ifdef PAX_ASLR
|
||||
PROC_LOCK(imgp->proc);
|
||||
if (p->p_timekeep_base != 0)
|
||||
pax_aslr_vdso(p, &(p->p_timekeep_base));
|
||||
PROC_UNLOCK(imgp->proc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Allocate a new stack */
|
||||
|
|
@ -1094,13 +1124,27 @@ exec_new_vmspace(imgp, sv)
|
|||
} else {
|
||||
ssiz = maxssiz;
|
||||
}
|
||||
stack_addr = sv->sv_usrstack - ssiz;
|
||||
stack_addr = sv->sv_usrstack;
|
||||
#ifdef PAX_ASLR
|
||||
/* Randomize the stack top. */
|
||||
pax_aslr_stack(p, &stack_addr);
|
||||
#endif
|
||||
/* Save the process specific randomized stack top */
|
||||
p->p_usrstack = stack_addr;
|
||||
/* Calculate the stack's mapping address */
|
||||
stack_addr -= ssiz;
|
||||
error = vm_map_stack(map, stack_addr, (vm_size_t)ssiz,
|
||||
obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
|
||||
sv->sv_stackprot,
|
||||
VM_PROT_ALL, MAP_STACK_GROWS_DOWN);
|
||||
if (error)
|
||||
if (error) {
|
||||
#ifdef PAX_ASLR
|
||||
pax_log_aslr(p, PAX_LOG_DEFAULT,
|
||||
"failed to map the main stack @%p",
|
||||
(void *)p->p_usrstack);
|
||||
#endif
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef __ia64__
|
||||
/* Allocate a new register stack */
|
||||
|
|
@ -1278,10 +1322,15 @@ exec_copyout_strings(imgp)
|
|||
execpath_len = 0;
|
||||
p = imgp->proc;
|
||||
szsigcode = 0;
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
if (p->p_sysent->sv_sigcode_base == 0) {
|
||||
p->p_sigcode_base = p->p_sysent->sv_sigcode_base;
|
||||
arginfo = (struct ps_strings *)p->p_psstrings;
|
||||
if (p->p_sigcode_base == 0) {
|
||||
if (p->p_sysent->sv_szsigcode != NULL)
|
||||
szsigcode = *(p->p_sysent->sv_szsigcode);
|
||||
#ifdef PAX_ASLR
|
||||
} else {
|
||||
pax_aslr_vdso(p, &(p->p_sigcode_base));
|
||||
#endif
|
||||
}
|
||||
destp = (uintptr_t)arginfo;
|
||||
|
||||
|
|
|
|||
|
|
@ -481,6 +481,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
|
|||
__rangeof(struct thread, td_startcopy, td_endcopy));
|
||||
|
||||
bcopy(&p2->p_comm, &td2->td_name, sizeof(td2->td_name));
|
||||
td2->td_pax = p2->p_pax;
|
||||
td2->td_sigstk = td->td_sigstk;
|
||||
td2->td_flags = TDF_INMEM;
|
||||
td2->td_lend_user_pri = PRI_MAX;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include "opt_ddb.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -249,6 +250,10 @@ prison0_init(void)
|
|||
prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset);
|
||||
prison0.pr_osreldate = osreldate;
|
||||
strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease));
|
||||
|
||||
#ifdef PAX
|
||||
pax_init_prison(&prison0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef INET
|
||||
|
|
@ -1367,6 +1372,10 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
|||
goto done_releroot;
|
||||
}
|
||||
|
||||
#ifdef PAX
|
||||
pax_init_prison(pr);
|
||||
#endif
|
||||
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
/*
|
||||
* New prisons do not yet have a reference, because we do not
|
||||
|
|
@ -4731,6 +4740,27 @@ db_show_prison(struct prison *pr)
|
|||
ii == 0 ? "ip6.addr =" : " ",
|
||||
ip6_sprintf(ip6buf, &pr->pr_ip6[ii]));
|
||||
#endif
|
||||
#ifdef PAX
|
||||
db_printf(" pr_hbsd = {\n");
|
||||
|
||||
db_printf(" .aslr = {\n");
|
||||
db_printf(" .status = %d\n",
|
||||
pr->pr_hbsd.aslr.status);
|
||||
db_printf(" .compat_status = %d\n",
|
||||
pr->pr_hbsd.aslr.compat_status);
|
||||
db_printf(" .disallow_map32bit_status = %d\n",
|
||||
pr->pr_hbsd.aslr.disallow_map32bit_status);
|
||||
db_printf(" }\n");
|
||||
|
||||
db_printf(" .log = {\n");
|
||||
db_printf(" .log = %d\n",
|
||||
pr->pr_hbsd.log.log);
|
||||
db_printf(" .ulog = %d\n",
|
||||
pr->pr_hbsd.log.ulog);
|
||||
db_printf(" }\n");
|
||||
|
||||
db_printf(" }\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
DB_SHOW_COMMAND(prison, db_show_prison_command)
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ SYSCTL_ROOT_NODE(OID_AUTO, compat, CTLFLAG_RW, 0,
|
|||
"Compatibility code");
|
||||
SYSCTL_ROOT_NODE(OID_AUTO, security, CTLFLAG_RW, 0,
|
||||
"Security");
|
||||
SYSCTL_ROOT_NODE(OID_AUTO, hardening, CTLFLAG_RW, 0,
|
||||
"Kernel hardening features");
|
||||
#ifdef REGRESSION
|
||||
SYSCTL_ROOT_NODE(OID_AUTO, regression, CTLFLAG_RW, 0,
|
||||
"Regression test MIB");
|
||||
|
|
|
|||
|
|
@ -1541,7 +1541,7 @@ get_proc_vector32(struct thread *td, struct proc *p, char ***proc_vectorp,
|
|||
size_t vsize, size;
|
||||
int i, error;
|
||||
|
||||
error = proc_read_mem(td, p, (vm_offset_t)(p->p_sysent->sv_psstrings),
|
||||
error = proc_read_mem(td, p, (vm_offset_t)(p->p_psstrings),
|
||||
&pss, sizeof(pss));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
|
@ -1617,7 +1617,7 @@ get_proc_vector(struct thread *td, struct proc *p, char ***proc_vectorp,
|
|||
if (SV_PROC_FLAG(p, SV_ILP32) != 0)
|
||||
return (get_proc_vector32(td, p, proc_vectorp, vsizep, type));
|
||||
#endif
|
||||
error = proc_read_mem(td, p, (vm_offset_t)(p->p_sysent->sv_psstrings),
|
||||
error = proc_read_mem(td, p, (vm_offset_t)(p->p_psstrings),
|
||||
&pss, sizeof(pss));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
|
@ -2609,13 +2609,13 @@ sysctl_kern_proc_ps_strings(SYSCTL_HANDLER_ARGS)
|
|||
* process.
|
||||
*/
|
||||
ps_strings32 = SV_PROC_FLAG(p, SV_ILP32) != 0 ?
|
||||
PTROUT(p->p_sysent->sv_psstrings) : 0;
|
||||
PTROUT(p->p_psstrings) : 0;
|
||||
PROC_UNLOCK(p);
|
||||
error = SYSCTL_OUT(req, &ps_strings32, sizeof(ps_strings32));
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
ps_strings = p->p_sysent->sv_psstrings;
|
||||
ps_strings = p->p_psstrings;
|
||||
PROC_UNLOCK(p);
|
||||
error = SYSCTL_OUT(req, &ps_strings, sizeof(ps_strings));
|
||||
return (error);
|
||||
|
|
@ -2719,13 +2719,13 @@ sysctl_kern_proc_sigtramp(SYSCTL_HANDLER_ARGS)
|
|||
bzero(&kst32, sizeof(kst32));
|
||||
if (SV_PROC_FLAG(p, SV_ILP32)) {
|
||||
if (sv->sv_sigcode_base != 0) {
|
||||
kst32.ksigtramp_start = sv->sv_sigcode_base;
|
||||
kst32.ksigtramp_end = sv->sv_sigcode_base +
|
||||
kst32.ksigtramp_start = p->p_sigcode_base;
|
||||
kst32.ksigtramp_end = p->p_sigcode_base +
|
||||
*sv->sv_szsigcode;
|
||||
} else {
|
||||
kst32.ksigtramp_start = sv->sv_psstrings -
|
||||
kst32.ksigtramp_start = p->p_psstrings -
|
||||
*sv->sv_szsigcode;
|
||||
kst32.ksigtramp_end = sv->sv_psstrings;
|
||||
kst32.ksigtramp_end = p->p_psstrings;
|
||||
}
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
|
|
@ -2735,13 +2735,13 @@ sysctl_kern_proc_sigtramp(SYSCTL_HANDLER_ARGS)
|
|||
#endif
|
||||
bzero(&kst, sizeof(kst));
|
||||
if (sv->sv_sigcode_base != 0) {
|
||||
kst.ksigtramp_start = (char *)sv->sv_sigcode_base;
|
||||
kst.ksigtramp_end = (char *)sv->sv_sigcode_base +
|
||||
kst.ksigtramp_start = (char *)p->p_sigcode_base;
|
||||
kst.ksigtramp_end = (char *)p->p_sigcode_base +
|
||||
*sv->sv_szsigcode;
|
||||
} else {
|
||||
kst.ksigtramp_start = (char *)sv->sv_psstrings -
|
||||
kst.ksigtramp_start = (char *)p->p_psstrings -
|
||||
*sv->sv_szsigcode;
|
||||
kst.ksigtramp_end = (char *)sv->sv_psstrings;
|
||||
kst.ksigtramp_end = (char *)p->p_psstrings;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
error = SYSCTL_OUT(req, &kst, sizeof(kst));
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/refcount.h>
|
||||
|
|
@ -776,12 +778,12 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which,
|
|||
if (limp->rlim_cur > oldssiz.rlim_cur) {
|
||||
prot = p->p_sysent->sv_stackprot;
|
||||
size = limp->rlim_cur - oldssiz.rlim_cur;
|
||||
addr = p->p_sysent->sv_usrstack -
|
||||
addr = p->p_usrstack -
|
||||
limp->rlim_cur;
|
||||
} else {
|
||||
prot = VM_PROT_NONE;
|
||||
size = oldssiz.rlim_cur - limp->rlim_cur;
|
||||
addr = p->p_sysent->sv_usrstack -
|
||||
addr = p->p_usrstack -
|
||||
oldssiz.rlim_cur;
|
||||
}
|
||||
addr = trunc_page(addr);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ create_thread(struct thread *td, mcontext_t *ctx,
|
|||
td->td_proc->p_flag |= P_HADTHREADS;
|
||||
thread_link(newtd, p);
|
||||
bcopy(p->p_comm, newtd->td_name, sizeof(newtd->td_name));
|
||||
newtd->td_pax = p->p_pax;
|
||||
thread_lock(td);
|
||||
/* let the scheduler know about these things. */
|
||||
sched_fork_thread(td, newtd);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#ifdef _KERNEL
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_pax.h"
|
||||
#include "opt_printf.h"
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/kernel.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/stddef.h>
|
||||
|
|
@ -180,6 +182,49 @@ uprintf(const char *fmt, ...)
|
|||
return (retval);
|
||||
}
|
||||
|
||||
int
|
||||
hbsd_uprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct putchar_arg pca;
|
||||
struct proc *p;
|
||||
struct thread *td;
|
||||
int p_locked, retval;
|
||||
|
||||
td = curthread;
|
||||
if (TD_IS_IDLETHREAD(td))
|
||||
return (0);
|
||||
|
||||
sx_slock(&proctree_lock);
|
||||
p = td->td_proc;
|
||||
if ((p_locked = PROC_LOCKED(p)))
|
||||
PROC_LOCK(p);
|
||||
if ((p->p_flag & P_CONTROLT) == 0) {
|
||||
if (p_locked)
|
||||
PROC_UNLOCK(p);
|
||||
sx_sunlock(&proctree_lock);
|
||||
return (0);
|
||||
}
|
||||
SESS_LOCK(p->p_session);
|
||||
pca.tty = p->p_session->s_ttyp;
|
||||
SESS_UNLOCK(p->p_session);
|
||||
if (p_locked)
|
||||
PROC_UNLOCK(p);
|
||||
if (pca.tty == NULL) {
|
||||
sx_sunlock(&proctree_lock);
|
||||
return (0);
|
||||
}
|
||||
pca.flags = TOTTY;
|
||||
pca.p_bufr = NULL;
|
||||
va_start(ap, fmt);
|
||||
tty_lock(pca.tty);
|
||||
sx_sunlock(&proctree_lock);
|
||||
retval = kvprintf(fmt, putchar, &pca, 10, ap);
|
||||
tty_unlock(pca.tty);
|
||||
va_end(ap);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* tprintf and vtprintf print on the controlling terminal associated with the
|
||||
* given session, possibly to the log as well.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/sx.h>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -36,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/linker.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/signalvar.h>
|
||||
|
|
@ -83,6 +86,7 @@ struct sysentvec elf64_freebsd_sysvec = {
|
|||
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
|
||||
.sv_syscallnames = syscallnames,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
|
||||
static Elf64_Brandinfo freebsd_brand_info = {
|
||||
|
|
@ -139,6 +143,7 @@ struct sysentvec elf32_freebsd_sysvec = {
|
|||
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
|
||||
.sv_syscallnames = syscallnames,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
|
||||
static Elf32_Brandinfo freebsd_brand_info = {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#define __ELF_WORD_SIZE 32
|
||||
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
|
@ -106,6 +108,7 @@ struct sysentvec elf32_freebsd_sysvec = {
|
|||
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
|
||||
.sv_syscallnames = freebsd32_syscallnames,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace32,
|
||||
};
|
||||
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
|
||||
|
||||
|
|
@ -464,7 +467,7 @@ freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
/*
|
||||
* Signal trampoline code is at base of user stack.
|
||||
*/
|
||||
td->td_frame->ra = (register_t)(intptr_t)FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode);
|
||||
td->td_frame->ra = (register_t)(intptr_t)p->p_psstrings - *(p->p_sysent->sv_szsigcode);
|
||||
PROC_LOCK(p);
|
||||
mtx_lock(&psp->ps_mtx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
/*
|
||||
* Signal trampoline code is at base of user stack.
|
||||
*/
|
||||
regs->ra = (register_t)(intptr_t)PS_STRINGS - *(p->p_sysent->sv_szsigcode);
|
||||
regs->ra = (register_t)(intptr_t)p->p_psstrings - *(p->p_sysent->sv_szsigcode);
|
||||
PROC_LOCK(p);
|
||||
mtx_lock(&psp->ps_mtx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -34,6 +36,7 @@
|
|||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
|
@ -107,6 +110,7 @@ struct sysentvec elf32_freebsd_sysvec = {
|
|||
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace32,
|
||||
};
|
||||
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,15 @@
|
|||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
|
@ -83,6 +86,7 @@ struct sysentvec elf64_freebsd_sysvec = {
|
|||
.sv_shared_page_base = SHAREDPAGE,
|
||||
.sv_shared_page_len = PAGE_SIZE,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
|
||||
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
|||
mtx_unlock(&psp->ps_mtx);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base;
|
||||
tf->srr0 = (register_t)p->p_sigcode_base;
|
||||
|
||||
/*
|
||||
* copy the frame out to userland.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
* from: NetBSD: mdreloc.c,v 1.42 2008/04/28 20:23:04 martin Exp
|
||||
*/
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
|
@ -40,6 +42,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/exec.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/imgact_elf.h>
|
||||
|
|
@ -87,6 +90,7 @@ static struct sysentvec elf64_freebsd_sysvec = {
|
|||
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
|
||||
.sv_syscallnames = syscallnames,
|
||||
.sv_schedtail = NULL,
|
||||
.sv_pax_aslr_init = pax_aslr_init_vmspace,
|
||||
};
|
||||
|
||||
static Elf64_Brandinfo freebsd_brand_info = {
|
||||
|
|
|
|||
|
|
@ -1003,7 +1003,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
|
|||
bzero(pcb, sizeof(*pcb));
|
||||
bzero(tf, sizeof(*tf));
|
||||
tf->tf_out[0] = stack;
|
||||
tf->tf_out[3] = p->p_sysent->sv_psstrings;
|
||||
tf->tf_out[3] = p->p_psstrings;
|
||||
tf->tf_out[6] = sp - SPOFF - sizeof(struct frame);
|
||||
tf->tf_tnpc = imgp->entry_addr + 4;
|
||||
tf->tf_tpc = imgp->entry_addr;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
#ifndef _SYS_JAIL_H_
|
||||
#define _SYS_JAIL_H_
|
||||
|
||||
#if defined(_KERNEL) || defined(_WANT_PRISON)
|
||||
#include <sys/pax.h>
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct jail_v0 {
|
||||
u_int32_t version;
|
||||
|
|
@ -187,6 +191,7 @@ struct prison {
|
|||
char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */
|
||||
char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */
|
||||
char pr_osrelease[OSRELEASELEN]; /* (c) kern.osrelease value */
|
||||
struct hbsd_features pr_hbsd; /* (p) PaX-inspired hardening features */
|
||||
};
|
||||
|
||||
struct prison_racct {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ enum sysinit_sub_id {
|
|||
SI_SUB_WITNESS = 0x1A80000, /* witness initialization */
|
||||
SI_SUB_MTX_POOL_DYNAMIC = 0x1AC0000, /* dynamic mutex pool */
|
||||
SI_SUB_LOCK = 0x1B00000, /* various locks */
|
||||
SI_SUB_PAX = 0x1B80000, /* pax setup */
|
||||
SI_SUB_EVENTHANDLER = 0x1C00000, /* eventhandler init */
|
||||
SI_SUB_VNET_PRELINK = 0x1E00000, /* vnet init before modules */
|
||||
SI_SUB_KLD = 0x2000000, /* KLD and module setup */
|
||||
|
|
|
|||
179
sys/sys/pax.h
Normal file
179
sys/sys/pax.h
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*-
|
||||
* Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
|
||||
* Copyright (c) 2013-2016, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
|
||||
* Copyright (c) 2014-2015 by Shawn Webb <shawn.webb@hardenedbsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PAX_H
|
||||
#define _SYS_PAX_H
|
||||
|
||||
#if defined(_KERNEL) || defined(_WANT_PRISON)
|
||||
struct hbsd_features {
|
||||
struct hbsd_aslr {
|
||||
int status; /* (p) PaX ASLR enabled */
|
||||
int compat_status; /* (p) PaX ASLR enabled (compat32) */
|
||||
int disallow_map32bit_status; /* (p) MAP_32BIT protection (__LP64__ only) */
|
||||
} aslr;
|
||||
struct hbsd_log {
|
||||
int log; /* (p) Per-jail logging status */
|
||||
int ulog; /* (p) Per-jail user visible logging status */
|
||||
} log;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
struct image_params;
|
||||
struct prison;
|
||||
struct thread;
|
||||
struct proc;
|
||||
struct vnode;
|
||||
struct vm_offset_t;
|
||||
|
||||
typedef uint32_t pax_flag_t;
|
||||
|
||||
/*
|
||||
* used in sysctl handler
|
||||
*/
|
||||
#define PAX_FEATURE_DISABLED 0
|
||||
#define PAX_FEATURE_OPTIN 1
|
||||
#define PAX_FEATURE_OPTOUT 2
|
||||
#define PAX_FEATURE_FORCE_ENABLED 3
|
||||
|
||||
extern const char *pax_status_str[];
|
||||
|
||||
#define PAX_FEATURE_SIMPLE_DISABLED 0
|
||||
#define PAX_FEATURE_SIMPLE_ENABLED 1
|
||||
|
||||
extern const char *pax_status_simple_str[];
|
||||
|
||||
/*
|
||||
* generic pax functions
|
||||
*/
|
||||
int pax_elf(struct image_params *imgp, struct thread *td, pax_flag_t mode);
|
||||
void pax_get_flags(struct proc *p, pax_flag_t *flags);
|
||||
void pax_get_flags_td(struct thread *td, pax_flag_t *flags);
|
||||
struct prison *pax_get_prison(struct proc *p);
|
||||
struct prison *pax_get_prison_td(struct thread *td);
|
||||
void pax_init_prison(struct prison *pr);
|
||||
|
||||
/*
|
||||
* ASLR related functions
|
||||
*/
|
||||
bool pax_aslr_active(struct proc *p);
|
||||
#ifdef PAX_ASLR
|
||||
void pax_aslr_init_prison(struct prison *pr);
|
||||
void pax_aslr_init_prison32(struct prison *pr);
|
||||
void pax_aslr_init_vmspace(struct proc *p);
|
||||
void pax_aslr_init_vmspace32(struct proc *p);
|
||||
#else
|
||||
#define pax_aslr_init_prison(pr) do {} while (0)
|
||||
#define pax_aslr_init_prison32(pr) do {} while (0)
|
||||
#define pax_aslr_init_vmspace NULL
|
||||
#define pax_aslr_init_vmspace32 NULL
|
||||
#endif
|
||||
void pax_aslr_init(struct image_params *imgp);
|
||||
void pax_aslr_execbase(struct proc *p, u_long *et_dyn_addrp);
|
||||
void pax_aslr_mmap(struct proc *p, vm_offset_t *addr, vm_offset_t orig_addr, int mmap_flags);
|
||||
void pax_aslr_mmap_map_32bit(struct proc *p, vm_offset_t *addr, vm_offset_t orig_addr, int mmap_flags);
|
||||
void pax_aslr_rtld(struct proc *p, u_long *addr);
|
||||
pax_flag_t pax_aslr_setup_flags(struct image_params *imgp, struct thread *td, pax_flag_t mode);
|
||||
void pax_aslr_stack(struct proc *p, vm_offset_t *addr);
|
||||
void pax_aslr_stack_with_gap(struct proc *p, vm_offset_t *addr);
|
||||
void pax_aslr_vdso(struct proc *p, vm_offset_t *addr);
|
||||
pax_flag_t pax_disallow_map32bit_setup_flags(struct image_params *imgp, struct thread *td, pax_flag_t mode);
|
||||
bool pax_disallow_map32bit_active(struct thread *td, int mmap_flags);
|
||||
|
||||
/*
|
||||
* Log related functions
|
||||
*/
|
||||
|
||||
typedef uint64_t pax_log_settings_t;
|
||||
|
||||
#define PAX_LOG_DEFAULT 0x00000000
|
||||
#define PAX_LOG_SKIP_DETAILS 0x00000001
|
||||
#define PAX_LOG_NO_NEWLINE 0x00000002
|
||||
#define PAX_LOG_P_COMM 0x00000004
|
||||
#define PAX_LOG_NO_P_PAX 0x00000008
|
||||
#define PAX_LOG_NO_INDENT 0x00000010
|
||||
|
||||
void pax_log_init_prison(struct prison *pr);
|
||||
void pax_printf_flags(struct proc *p, pax_log_settings_t flags);
|
||||
void pax_printf_flags_td(struct thread *td, pax_log_settings_t flags);
|
||||
void pax_db_printf_flags(struct proc *p, pax_log_settings_t flags);
|
||||
void pax_db_printf_flags_td(struct thread *td, pax_log_settings_t flags);
|
||||
int hbsd_uprintf(const char *fmt, ...) __printflike(1, 2);
|
||||
void pax_log_internal(struct proc *, pax_log_settings_t flags, const char *fmt, ...) __printflike(3, 4);
|
||||
void pax_log_internal_imgp(struct image_params *imgp, pax_log_settings_t flags, const char* fmt, ...) __printflike(3, 4);
|
||||
void pax_ulog_internal(const char *fmt, ...) __printflike(1, 2);
|
||||
void pax_log_aslr(struct proc *, pax_log_settings_t flags, const char *fmt, ...) __printflike(3, 4);
|
||||
void pax_ulog_aslr(const char *fmt, ...) __printflike(1, 2);
|
||||
|
||||
/*
|
||||
* Hardening related functions
|
||||
*/
|
||||
#ifdef PAX_HARDENING
|
||||
void pax_hardening_init_prison(struct prison *pr);
|
||||
#else
|
||||
#define pax_hardening_init_prison(pr) do {} while (0)
|
||||
#endif
|
||||
int pax_procfs_harden(struct thread *td);
|
||||
|
||||
#define PAX_NOTE_PAGEEXEC 0x00000001
|
||||
#define PAX_NOTE_NOPAGEEXEC 0x00000002
|
||||
#define PAX_NOTE_MPROTECT 0x00000004
|
||||
#define PAX_NOTE_NOMPROTECT 0x00000008
|
||||
#define PAX_NOTE_SEGVGUARD 0x00000010
|
||||
#define PAX_NOTE_NOSEGVGUARD 0x00000020
|
||||
#define PAX_NOTE_ASLR 0x00000040
|
||||
#define PAX_NOTE_NOASLR 0x00000080
|
||||
#define PAX_NOTE_SHLIBRANDOM 0x00000100
|
||||
#define PAX_NOTE_NOSHLIBRANDOM 0x00000200
|
||||
#define PAX_NOTE_DISALLOWMAP32BIT 0x00000400
|
||||
#define PAX_NOTE_NODISALLOWMAP32BIT 0x00000800
|
||||
|
||||
#define PAX_NOTE_RESERVED0 0x40000000
|
||||
#define PAX_NOTE_FINALIZED 0x80000000
|
||||
|
||||
#define PAX_NOTE_ALL_ENABLED \
|
||||
(PAX_NOTE_PAGEEXEC | PAX_NOTE_MPROTECT | PAX_NOTE_SEGVGUARD | \
|
||||
PAX_NOTE_ASLR | PAX_NOTE_SHLIBRANDOM | PAX_NOTE_DISALLOWMAP32BIT)
|
||||
#define PAX_NOTE_ALL_DISABLED \
|
||||
(PAX_NOTE_NOPAGEEXEC | PAX_NOTE_NOMPROTECT | \
|
||||
PAX_NOTE_NOSEGVGUARD | PAX_NOTE_NOASLR | PAX_NOTE_NOSHLIBRANDOM | \
|
||||
PAX_NOTE_NODISALLOWMAP32BIT)
|
||||
#define PAX_NOTE_ALL (PAX_NOTE_ALL_ENABLED | PAX_NOTE_ALL_DISABLED | PAX_NOTE_FINALIZED)
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define PAX_HARDENING_SHLIBRANDOM 0x00000100
|
||||
#define PAX_HARDENING_NOSHLIBRANDOM 0x00000200
|
||||
|
||||
#endif /* !_SYS_PAX_H */
|
||||
|
|
@ -286,6 +286,7 @@ struct thread {
|
|||
u_char td_pri_class; /* (t) Scheduling class. */
|
||||
u_char td_user_pri; /* (t) User pri from estcpu and nice. */
|
||||
u_char td_base_user_pri; /* (t) Base user pri */
|
||||
uint32_t td_pax; /* (b) Cached PaX settings from process. */
|
||||
#define td_endcopy td_pcb
|
||||
|
||||
/*
|
||||
|
|
@ -561,6 +562,12 @@ struct proc {
|
|||
rlim_t p_cpulimit; /* (c) Current CPU limit in seconds. */
|
||||
signed char p_nice; /* (c) Process "nice" value. */
|
||||
int p_fibnum; /* in this routing domain XXX MRT */
|
||||
uint32_t p_pax; /* (b) PaX is enabled to this process */
|
||||
vm_offset_t p_usrstack; /* (b) Process stack top. */
|
||||
vm_offset_t p_psstrings; /* (b) Process psstrings address. */
|
||||
vm_offset_t p_timekeep_base; /* (c) Address of timekeep structure. */
|
||||
vm_offset_t p_shared_page_base; /* (c) Address of shared page. */
|
||||
vm_offset_t p_sigcode_base; /* Address of sigcode. */
|
||||
/* End area that is copied on creation. */
|
||||
#define p_endcopy p_xstat
|
||||
|
||||
|
|
|
|||
|
|
@ -753,6 +753,7 @@ SYSCTL_DECL(_compat);
|
|||
SYSCTL_DECL(_regression);
|
||||
SYSCTL_DECL(_security);
|
||||
SYSCTL_DECL(_security_bsd);
|
||||
SYSCTL_DECL(_hardening);
|
||||
|
||||
extern char machine[];
|
||||
extern char osrelease[];
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ struct rlimit;
|
|||
struct sysent;
|
||||
struct thread;
|
||||
struct ksiginfo;
|
||||
struct proc;
|
||||
|
||||
typedef int sy_call_t(struct thread *, void *);
|
||||
|
||||
|
|
@ -130,6 +131,7 @@ struct sysentvec {
|
|||
uint32_t sv_timekeep_gen;
|
||||
void *sv_shared_page_obj;
|
||||
void (*sv_schedtail)(struct thread *);
|
||||
void (* const sv_pax_aslr_init)(struct proc *p);
|
||||
};
|
||||
|
||||
#define SV_ILP32 0x000100
|
||||
|
|
|
|||
|
|
@ -65,12 +65,15 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <sys/mman.h>
|
||||
|
|
@ -295,6 +298,15 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, pmap_pinit_t pinit)
|
|||
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;
|
||||
vm->vm_aslr_delta_vdso = 0;
|
||||
#ifdef __LP64__
|
||||
vm->vm_aslr_delta_map32bit = 0;
|
||||
#endif
|
||||
#endif
|
||||
return (vm);
|
||||
}
|
||||
|
||||
|
|
@ -3275,6 +3287,15 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge)
|
|||
vm2->vm_taddr = vm1->vm_taddr;
|
||||
vm2->vm_daddr = vm1->vm_daddr;
|
||||
vm2->vm_maxsaddr = vm1->vm_maxsaddr;
|
||||
#ifdef PAX_ASLR
|
||||
vm2->vm_aslr_delta_exec = vm1->vm_aslr_delta_exec;
|
||||
vm2->vm_aslr_delta_mmap = vm1->vm_aslr_delta_mmap;
|
||||
vm2->vm_aslr_delta_stack = vm1->vm_aslr_delta_stack;
|
||||
vm2->vm_aslr_delta_vdso = vm1->vm_aslr_delta_vdso;
|
||||
#ifdef __LP64__
|
||||
vm2->vm_aslr_delta_map32bit = vm1->vm_aslr_delta_map32bit;
|
||||
#endif
|
||||
#endif
|
||||
vm_map_lock(old_map);
|
||||
if (old_map->busy)
|
||||
vm_map_wait_busy(old_map);
|
||||
|
|
@ -3657,7 +3678,8 @@ Retry:
|
|||
return (KERN_NO_SPACE);
|
||||
}
|
||||
|
||||
is_procstack = (addr >= (vm_offset_t)vm->vm_maxsaddr) ? 1 : 0;
|
||||
is_procstack = (addr >= (vm_offset_t)vm->vm_maxsaddr &&
|
||||
addr < (vm_offset_t)p->p_usrstack) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* If this is the main process stack, see if we're over the stack
|
||||
|
|
|
|||
|
|
@ -241,6 +241,13 @@ struct vmspace {
|
|||
caddr_t vm_taddr; /* (c) user virtual address of text */
|
||||
caddr_t vm_daddr; /* (c) user virtual address of data */
|
||||
caddr_t vm_maxsaddr; /* user VA at max stack growth */
|
||||
vm_offset_t vm_aslr_delta_mmap; /* mmap() random delta for ASLR */
|
||||
vm_offset_t vm_aslr_delta_stack; /* stack random delta for ASLR */
|
||||
vm_offset_t vm_aslr_delta_exec; /* exec base random delta for ASLR */
|
||||
vm_offset_t vm_aslr_delta_vdso; /* VDSO base random delta for ASLR */
|
||||
#ifdef __LP64__
|
||||
vm_offset_t vm_aslr_delta_map32bit; /* random for MAP_32BIT mappings */
|
||||
#endif
|
||||
volatile int vm_refcnt; /* number of references */
|
||||
/*
|
||||
* Keep the PMAP last, so that CPU-specific variations of that
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_hwpmc_hooks.h"
|
||||
#include "opt_pax.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
|
@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/mutex.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/pax.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procctl.h>
|
||||
|
|
@ -211,6 +213,9 @@ sys_mmap(td, uap)
|
|||
off_t pos;
|
||||
struct vmspace *vms = td->td_proc->p_vmspace;
|
||||
cap_rights_t rights;
|
||||
#ifdef PAX_ASLR
|
||||
int pax_aslr_done;
|
||||
#endif
|
||||
|
||||
addr = (vm_offset_t) uap->addr;
|
||||
size = uap->len;
|
||||
|
|
@ -220,6 +225,10 @@ sys_mmap(td, uap)
|
|||
|
||||
fp = NULL;
|
||||
|
||||
#ifdef PAX_ASLR
|
||||
pax_aslr_done = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enforce the constraints.
|
||||
* Mapping of length 0 is only allowed for old binaries.
|
||||
|
|
@ -297,7 +306,13 @@ sys_mmap(td, uap)
|
|||
*/
|
||||
if (addr + size > MAP_32BIT_MAX_ADDR)
|
||||
addr = 0;
|
||||
#endif
|
||||
#ifdef PAX_ASLR
|
||||
PROC_LOCK(td->td_proc);
|
||||
pax_aslr_mmap_map_32bit(td->td_proc, &addr, (vm_offset_t)uap->addr, flags);
|
||||
pax_aslr_done = 1;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
#endif /* PAX_ASLR */
|
||||
#endif /* MAP_32BIT */
|
||||
} else {
|
||||
/*
|
||||
* XXX for non-fixed mappings where no hint is provided or
|
||||
|
|
@ -315,6 +330,12 @@ sys_mmap(td, uap)
|
|||
addr = round_page((vm_offset_t)vms->vm_daddr +
|
||||
lim_max(td->td_proc, RLIMIT_DATA));
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
#ifdef PAX_ASLR
|
||||
PROC_LOCK(td->td_proc);
|
||||
pax_aslr_mmap(td->td_proc, &addr, (vm_offset_t)uap->addr, flags);
|
||||
pax_aslr_done = 1;
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
#endif
|
||||
}
|
||||
if (flags & MAP_ANON) {
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue