Date: Sun, 22 Jun 2014 09:37:40 -0400 From: Shawn Webb <lattera@gmail.com> To: freebsd-current@freebsd.org Subject: [CFT] New Round of ASLR Patches Message-ID: <20140622133740.GD1824@pwnie.vrt.sourcefire.com>
next in thread | raw e-mail | index | archive | help
--S5HS5MvDw4DmbRmb Content-Type: multipart/mixed; boundary="yRA+Bmk8aPhU85Qt" Content-Disposition: inline --yRA+Bmk8aPhU85Qt Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hey All, Attached is a new patch with the latest work regarding our ASLR implementation. Here's what has changed since the last patch distributed on 24 May 2014: Shawn Webb: Sat Jun 21 20:03:07 2014 -0400: PAX SEGVGUARD: Remove segvguard prior to putting in a separate feature branch Thu Jun 19 21:08:37 2014 -0400: PAX ASLR: More style(9) fixes Thu Jun 19 20:59:44 2014 -0400: PAX ASLR: Add PAX_SYSCTLS to sys/conf/NOTES Thu Jun 19 20:48:42 2014 -0400: PAX ASLR: Remove extra NO_PIE/MK_PIE entries that aren't now needed Wed Jun 11 22:07:51 2014 -0400: PAX ASLR: Rollback code cleanup that removed orig_addr from pax_aslr_mmap(). Wed Jun 11 17:54:12 2014 -0400: PAX ASLR: style(9) changes. Grammar fixes. Code cleanup. Fri May 30 18:36:49 2014 -0400: PAX ASLR: Pull in Oliver Pinter's change to add stack randomization Fri May 30 18:36:01 2014 -0400: Update copyright Oliver Pinter: Wed Jun 4 09:39:48 2014 +0200: PAX ASLR: added FEATURE(aslr, ...) to the kernel, and modify ugidfw to use them Wed May 28 00:27:06 2014 +0200: PAX: fix prison0 initialization after my jail modifications Sun May 25 21:20:23 2014 +0200: PAX: show pax settings in dmesg, and validate some value Sun May 25 19:48:44 2014 +0200: PAX ASLR: make security.pax.aslr sysctls optional Sun May 25 19:15:16 2014 +0200: PAX: check proc->p_ucred Sun May 25 19:11:50 2014 +0200: PAX: added PAX_SYSCTLS kernel option Sun May 25 19:10:16 2014 +0200: PAX ASLR: simplify jail handling Sun May 25 19:00:12 2014 +0200: PAX: hook in pax_init_prison at kern_jail_set Thanks, Shawn --yRA+Bmk8aPhU85Qt Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="2014-06-21_aslr.patch" Content-Transfer-Encoding: quoted-printable diff --git a/lib/libugidfw/ugidfw.c b/lib/libugidfw/ugidfw.c index 0dc423d..a4a38bc 100644 --- a/lib/libugidfw/ugidfw.c +++ b/lib/libugidfw/ugidfw.c @@ -36,6 +36,9 @@ #include <sys/sysctl.h> #include <sys/ucred.h> #include <sys/mount.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/sysctl.h> =20 #include <security/mac_bsdextended/mac_bsdextended.h> =20 @@ -44,6 +47,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <fcntl.h> +#include <unistd.h> =20 #include "ugidfw.h" =20 @@ -329,14 +334,19 @@ bsde_rule_to_string(struct mac_bsdextended_rule *rule= , char *buf, size_t buflen) cur +=3D len; } if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) { - numfs =3D getmntinfo(&mntbuf, MNT_NOWAIT); - for (i =3D 0; i < numfs; i++) - if (memcmp(&(rule->mbr_object.mbo_fsid), - &(mntbuf[i].f_fsid), - sizeof(mntbuf[i].f_fsid)) =3D=3D 0) - break; - len =3D snprintf(cur, left, "filesys %s ", - i =3D=3D numfs ? "???" : mntbuf[i].f_mntonname); + if (rule->mbr_object.mbo_inode =3D=3D 0) { + numfs =3D getmntinfo(&mntbuf, MNT_NOWAIT); + for (i =3D 0; i < numfs; i++) + if (memcmp(&(rule->mbr_object.mbo_fsid), + &(mntbuf[i].f_fsid), + sizeof(mntbuf[i].f_fsid)) =3D=3D 0) + break; + len =3D snprintf(cur, left, "filesys %s ", + i =3D=3D numfs ? "???" : mntbuf[i].f_mntonname); + } else { + len =3D snprintf(cur, left, "filesys %s ", + rule->mbr_object.mbo_paxpath); + } if (len < 0 || len > left) goto truncated; left -=3D len; @@ -500,6 +510,33 @@ bsde_rule_to_string(struct mac_bsdextended_rule *rule,= char *buf, size_t buflen) cur +=3D len; } =20 + if (rule->mbr_pax) { + len =3D snprintf(cur, left, " paxflags "); + if (len < 0 || len > left) + goto truncated; + left -=3D len; + cur +=3D len; + + if (rule->mbr_pax & MBI_FORCE_ASLR_ENABLED) { + len =3D snprintf(cur, left, "A"); + if (len < 0 || len > left) + goto truncated; + + left -=3D len; + cur +=3D len; + } + + if (rule->mbr_pax & MBI_FORCE_ASLR_DISABLED) { + len =3D snprintf(cur, left, "a"); + if (len < 0 || len > left) + goto truncated; + + left -=3D len; + cur +=3D len; + } + + } + return (0); =20 truncated: @@ -507,8 +544,8 @@ truncated: } =20 int -bsde_parse_uidrange(char *spec, uid_t *min, uid_t *max, - size_t buflen, char *errstr){ +bsde_parse_uidrange(char *spec, uid_t *min, uid_t *max, size_t buflen, cha= r *errstr) +{ struct passwd *pwd; uid_t uid1, uid2; char *spec1, *spec2, *endp; @@ -556,8 +593,8 @@ bsde_parse_uidrange(char *spec, uid_t *min, uid_t *max, } =20 int -bsde_parse_gidrange(char *spec, gid_t *min, gid_t *max, - size_t buflen, char *errstr){ +bsde_parse_gidrange(char *spec, gid_t *min, gid_t *max, size_t buflen, cha= r *errstr) +{ struct group *grp; gid_t gid1, gid2; char *spec1, *spec2, *endp; @@ -766,10 +803,15 @@ bsde_parse_type(char *spec, int *type, size_t buflen,= char *errstr) } =20 int -bsde_parse_fsid(char *spec, struct fsid *fsid, size_t buflen, char *errstr) +bsde_parse_fsid(char *spec, struct fsid *fsid, ino_t *inode, size_t buflen= , char *errstr) { size_t len; struct statfs buf; + struct stat sb; + int fd, paxstatus; + size_t bufsz; + + *inode =3D 0; =20 if (statfs(spec, &buf) < 0) { len =3D snprintf(errstr, buflen, "Unable to get id for %s: %s", @@ -779,6 +821,21 @@ bsde_parse_fsid(char *spec, struct fsid *fsid, size_t = buflen, char *errstr) =20 *fsid =3D buf.f_fsid; =20 + if (strcmp(buf.f_fstypename, "devfs") !=3D 0) { + bufsz =3D sizeof(int); + if (!sysctlbyname("kern.features.aslr", &paxstatus, &bufsz, + NULL, 0)) { + fd =3D open(spec, O_RDONLY); + if (fd !=3D -1) { + if (fstat(fd, &sb) =3D=3D 0) + if(S_ISDIR(sb.st_mode) =3D=3D 0) + *inode =3D sb.st_ino; + + close(fd); + } + } + } + return (0); } =20 @@ -852,13 +909,18 @@ bsde_parse_object(int argc, char *argv[], return (-1); } if (bsde_parse_fsid(argv[current+1], &fsid, - buflen, errstr) < 0) + &object->mbo_inode, buflen, errstr) < 0) return (-1); flags |=3D MBO_FSID_DEFINED; if (nextnot) { neg ^=3D MBO_FSID_DEFINED; nextnot =3D 0; } + if (object->mbo_inode) + snprintf(object->mbo_paxpath, MAXPATHLEN, "%s", + argv[current+1]); + else + memset(object->mbo_paxpath, 0x00, MAXPATHLEN); current +=3D 2; } else if (strcmp(argv[current], "suid") =3D=3D 0) { flags |=3D MBO_SUID; @@ -991,12 +1053,48 @@ bsde_parse_mode(int argc, char *argv[], mode_t *mode= , size_t buflen, } =20 int +bsde_parse_paxflags(int argc, char *argv[], uint32_t *pax, size_t buflen, = char *errstr) +{ + size_t len; + int i; + + if (argc =3D=3D 0) { + len =3D snprintf(errstr, buflen, "paxflags expects mode value"); + return (-1); + } + + if (argc !=3D 1) { + len =3D snprintf(errstr, buflen, "'%s' unexpected", argv[1]); + return (-1); + } + + *pax =3D 0; + for (i =3D 0; i < strlen(argv[0]); i++) { + switch (argv[0][i]) { + case 'A': + *pax |=3D MBI_FORCE_ASLR_ENABLED; + break; + case 'a': + *pax |=3D MBI_FORCE_ASLR_DISABLED; + break; + default: + len =3D snprintf(errstr, buflen, "Unknown mode letter: %c", + argv[0][i]); + return (-1); + }=20 + } + + return (0); +} + +int bsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule, size_t buflen, char *errstr) { int subject, subject_elements, subject_elements_length; int object, object_elements, object_elements_length; int mode, mode_elements, mode_elements_length; + int paxflags, paxflags_elements, paxflags_elements_length=3D0; int error, i; size_t len; =20 @@ -1037,11 +1135,23 @@ bsde_parse_rule(int argc, char *argv[], struct mac_= bsdextended_rule *rule, return (-1); } =20 + /* Search forward for paxflags */ + paxflags =3D -1; + for (i =3D 1; i < argc; i++) + if (strcmp(argv[i], "paxflags") =3D=3D 0) + paxflags =3D i; + + if (paxflags >=3D 0) { + paxflags_elements =3D paxflags + 1; + paxflags_elements_length =3D argc - paxflags_elements; + } + subject_elements_length =3D object - subject - 1; object_elements =3D object + 1; object_elements_length =3D mode - object_elements; mode_elements =3D mode + 1; - mode_elements_length =3D argc - mode_elements; + mode_elements_length =3D argc - mode_elements - + (paxflags_elements_length ? paxflags_elements_length+1 : 0); =20 error =3D bsde_parse_subject(subject_elements_length, argv + subject_elements, &rule->mbr_subject, buflen, errstr); @@ -1058,6 +1168,13 @@ bsde_parse_rule(int argc, char *argv[], struct mac_b= sdextended_rule *rule, if (error) return (-1); =20 + if (paxflags >=3D 0) { + error =3D bsde_parse_paxflags(paxflags_elements_length, argv + paxflags_= elements, + &rule->mbr_pax, buflen, errstr); + if (error) + return (-1); + } + return (0); } =20 diff --git a/lib/libugidfw/ugidfw.h b/lib/libugidfw/ugidfw.h index 5b7fcf2..cef469c 100644 --- a/lib/libugidfw/ugidfw.h +++ b/lib/libugidfw/ugidfw.h @@ -39,6 +39,8 @@ int bsde_rule_to_string(struct mac_bsdextended_rule *rule= , char *buf, size_t buflen); int bsde_parse_mode(int argc, char *argv[], mode_t *mode, size_t buflen, char *errstr); +int bsde_parse_paxflags(int argc, char *argv[], uint32_t *pax, size_t bufl= en, + char *errstr); int bsde_parse_rule(int argc, char *argv[], struct mac_bsdextended_rule *rule, size_t buflen, char *errstr); int bsde_parse_rule_string(const char *string, diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c index fdc4d56..ffb5e31 100644 --- a/sys/amd64/amd64/elf_machdep.c +++ b/sys/amd64/amd64/elf_machdep.c @@ -26,12 +26,17 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/exec.h> #include <sys/imgact.h> #include <sys/linker.h> +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif #include <sys/proc.h> #include <sys/sysent.h> #include <sys/imgact_elf.h> @@ -81,6 +86,11 @@ struct sysentvec elf64_freebsd_sysvec =3D { .sv_shared_page_base =3D SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); =20 diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h index bda9722..5e83a8f 100644 --- a/sys/amd64/include/vmparam.h +++ b/sys/amd64/include/vmparam.h @@ -170,7 +170,7 @@ #define VM_MAXUSER_ADDRESS UVADDR(NUPML4E, 0, 0, 0) =20 #define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE) -#define USRSTACK SHAREDPAGE +#define USRSTACK (SHAREDPAGE - 4*PAGE_SIZE) =20 #define VM_MAX_ADDRESS UPT_MAX_ADDRESS #define VM_MIN_ADDRESS (0) diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32= _sysvec.c index c06ce11..f4f99f58 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -33,6 +33,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #include "opt_compat.h" +#include "opt_pax.h" =20 #ifndef COMPAT_FREEBSD32 #error "Unable to compile Linux-emulator due to missing COMPAT_FREEBSD32 o= ption!" @@ -84,6 +85,10 @@ __FBSDID("$FreeBSD$"); #include <compat/linux/linux_signal.h> #include <compat/linux/linux_util.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + MODULE_VERSION(linux, 1); =20 MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); @@ -1037,6 +1042,11 @@ struct sysentvec elf_linux_sysvec =3D { .sv_shared_page_base =3D LINUX32_SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D linux_schedtail, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init32, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf_sysvec, &elf_linux_sysvec); =20 diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index 8ef9bd4..26e37e6 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -26,6 +26,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -46,6 +48,10 @@ __FBSDID("$FreeBSD$"); #include <machine/elf.h> #include <machine/md_var.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + struct sysentvec elf32_freebsd_sysvec =3D { .sv_size =3D SYS_MAXSYSCALL, .sv_table =3D sysent, @@ -79,6 +85,11 @@ struct sysentvec elf32_freebsd_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; =20 static Elf32_Brandinfo freebsd_brand_info =3D { diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/f= reebsd32_misc.c index 68e761b..96a81d9 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_pax.h" =20 #define __ELF_WORD_SIZE 32 =20 @@ -113,6 +114,10 @@ __FBSDID("$FreeBSD$"); =20 FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD"); =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + #ifndef __mips__ CTASSERT(sizeof(struct timeval32) =3D=3D 8); CTASSERT(sizeof(struct timespec32) =3D=3D 8); @@ -2886,6 +2891,10 @@ freebsd32_copyout_strings(struct image_params *imgp) szsigcode =3D 0; destp =3D (uintptr_t)arginfo; =20 +#ifdef PAX_ASLR + pax_aslr_stack(curthread, &destp); +#endif + /* * install sigcode */ diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c index a8e52e8..ade8da5 100644 --- a/sys/compat/ia32/ia32_sysvec.c +++ b/sys/compat/ia32/ia32_sysvec.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); =20 #include "opt_compat.h" +#include "opt_pax.h" =20 #define __ELF_WORD_SIZE 32 =20 @@ -74,6 +75,10 @@ __FBSDID("$FreeBSD$"); #include <machine/pcb.h> #include <machine/cpufunc.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + CTASSERT(sizeof(struct ia32_mcontext) =3D=3D 640); CTASSERT(sizeof(struct ia32_ucontext) =3D=3D 704); CTASSERT(sizeof(struct ia32_sigframe) =3D=3D 800); @@ -139,6 +144,11 @@ struct sysentvec ia32_freebsd_sysvec =3D { .sv_shared_page_base =3D FREEBSD32_SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init32, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec); =20 diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 4d27713..671ef83 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2972,3 +2972,7 @@ options RANDOM_RWFILE # Read and write entropy cache =20 # Module to enable execution of application via emulators like QEMU options IMAGACT_BINMISC + +# Address Space Layout Randomization (ASLR) +options PAX_ASLR +options PAX_SYSCTLS diff --git a/sys/conf/files b/sys/conf/files index cc907c50..1e73c88 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2907,6 +2907,9 @@ kern/kern_mtxpool.c standard kern/kern_mutex.c standard kern/kern_ntptime.c standard kern/kern_osd.c standard +kern/kern_pax.c optional pax_aslr +kern/kern_pax_aslr.c optional pax_aslr +kern/kern_pax_log.c optional pax_aslr kern/kern_physio.c standard kern/kern_pmc.c standard kern/kern_poll.c optional device_polling diff --git a/sys/conf/options b/sys/conf/options index 32fb4d4..6e81e4e 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -916,6 +916,12 @@ RACCT opt_global.h # Resource Limits RCTL opt_global.h =20 +# PaX - hardening options +PAX_ASLR opt_pax.h +PAX_ASLR_MAX_SEC opt_pax.h +PAX_MPROTECT opt_pax.h +PAX_SYSCTLS opt_pax.h + # Random number generator(s) RANDOM_YARROW opt_random.h RANDOM_FORTUNA opt_random.h diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c index 034b4c4..9571252 100644 --- a/sys/i386/i386/elf_machdep.c +++ b/sys/i386/i386/elf_machdep.c @@ -26,6 +26,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -46,6 +48,10 @@ __FBSDID("$FreeBSD$"); #include <machine/elf.h> #include <machine/md_var.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + struct sysentvec elf32_freebsd_sysvec =3D { .sv_size =3D SYS_MAXSYSCALL, .sv_table =3D sysent, @@ -81,6 +87,11 @@ struct sysentvec elf32_freebsd_sysvec =3D { .sv_shared_page_base =3D SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); =20 diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c index 5d007c7..1bb9d89 100644 --- a/sys/i386/ibcs2/ibcs2_sysvec.c +++ b/sys/i386/ibcs2/ibcs2_sysvec.c @@ -31,6 +31,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -50,6 +52,10 @@ __FBSDID("$FreeBSD$"); #include <i386/ibcs2/ibcs2_syscall.h> #include <i386/ibcs2/ibcs2_signal.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + MODULE_VERSION(ibcs2, 1); =20 extern int bsd_to_ibcs2_errno[]; @@ -89,6 +95,11 @@ struct sysentvec ibcs2_svr3_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D NULL, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, /* XXXOP */ +#else + .sv_pax_aslr_init =3D NULL, +#endif }; =20 static int diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 0ad6791..403070c 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -29,6 +29,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/exec.h> @@ -72,6 +74,10 @@ __FBSDID("$FreeBSD$"); #include <compat/linux/linux_signal.h> #include <compat/linux/linux_util.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + MODULE_VERSION(linux, 1); =20 MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); @@ -974,6 +980,11 @@ struct sysentvec linux_sysvec =3D { .sv_shared_page_base =3D LINUX_SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D linux_schedtail, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, /* XXXOP */ +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(aout_sysvec, &linux_sysvec); =20 @@ -1012,6 +1023,11 @@ struct sysentvec elf_linux_sysvec =3D { .sv_shared_page_base =3D LINUX_SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D linux_schedtail, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf_sysvec, &elf_linux_sysvec); =20 diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c index 05cb641..e3d19c1 100644 --- a/sys/ia64/ia64/elf_machdep.c +++ b/sys/ia64/ia64/elf_machdep.c @@ -25,6 +25,8 @@ * $FreeBSD$ */ =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -49,6 +51,10 @@ #include <machine/md_var.h> #include <machine/unwind.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + Elf_Addr link_elf_get_gp(linker_file_t); =20 extern Elf_Addr fptr_storage[]; @@ -86,6 +92,12 @@ struct sysentvec elf64_freebsd_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif + }; =20 static Elf64_Brandinfo freebsd_brand_info =3D { diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 3ae78de..aac03f1 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -27,6 +27,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/exec.h> #include <sys/imgact.h> @@ -62,6 +64,10 @@ __FBSDID("$FreeBSD$"); #include <compat/ia32/ia32_signal.h> #endif =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + static int exec_aout_imgact(struct image_params *imgp); static int aout_fixup(register_t **stack_base, struct image_params *imgp); =20 @@ -99,6 +105,11 @@ struct sysentvec aout_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, /* XXXOP */ +#else + .sv_pax_aslr_init =3D NULL, +#endif }; =20 #elif defined(__amd64__) @@ -143,6 +154,11 @@ struct sysentvec aout_sysvec =3D { .sv_set_syscall_retval =3D ia32_set_syscall_retval, .sv_fetch_syscall_args =3D ia32_fetch_syscall_args, .sv_syscallnames =3D freebsd32_syscallnames, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init32, /* XXXOP */ +#else + .sv_pax_aslr_init =3D NULL, +#endif }; #else #error "Port me" diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 591094e..d0e01d3 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include "opt_capsicum.h" #include "opt_compat.h" #include "opt_core.h" +#include "opt_pax.h" =20 #include <sys/param.h> #include <sys/capsicum.h> @@ -48,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mman.h> #include <sys/namei.h> #include <sys/pioctl.h> +#include <sys/jail.h> #include <sys/proc.h> #include <sys/procfs.h> #include <sys/racct.h> @@ -81,6 +83,10 @@ __FBSDID("$FreeBSD$"); #include <machine/elf.h> #include <machine/md_var.h> =20 +#if defined(PAX_ASLR) +#include <sys/pax.h> +#endif + #define ELF_NOTE_ROUNDSIZE 4 #define OLD_EI_BRAND 8 =20 @@ -655,16 +661,16 @@ __elfN(load_file)(struct proc *p, const char *file, u= _long *addr, hdr =3D (const Elf_Ehdr *)imgp->image_header; if ((error =3D __elfN(check_header)(hdr)) !=3D 0) goto fail; - if (hdr->e_type =3D=3D ET_DYN) + if (hdr->e_type =3D=3D ET_DYN) { rbase =3D *addr; - else if (hdr->e_type =3D=3D ET_EXEC) + } else if (hdr->e_type =3D=3D ET_EXEC) { rbase =3D 0; - else { + } else { error =3D ENOEXEC; goto fail; } =20 - /* Only support headers that fit within first page for now */ + /* Only support headers that fit within first page for now */ if ((hdr->e_phoff > PAGE_SIZE) || (u_int)hdr->e_phentsize * hdr->e_phnum > PAGE_SIZE - hdr->e_phoff) { error =3D ENOEXEC; @@ -789,16 +795,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i= mgp) if (hdr->e_type =3D=3D ET_DYN) { if ((brand_info->flags & BI_CAN_EXEC_DYN) =3D=3D 0) return (ENOEXEC); - /* - * Honour the base load address from the dso if it is - * non-zero for some reason. - */ - if (baddr =3D=3D 0) - et_dyn_addr =3D ET_DYN_LOAD_ADDR; - else - et_dyn_addr =3D 0; - } else - et_dyn_addr =3D 0; + } sv =3D brand_info->sysvec; if (interp !=3D NULL && brand_info->interp_newpath !=3D NULL) newinterp =3D brand_info->interp_newpath; @@ -819,6 +816,25 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i= mgp) error =3D exec_new_vmspace(imgp, sv); imgp->proc->p_sysent =3D sv; =20 +#if defined(PAX_MPROTECT) || defined(PAX_ASLR) + pax_elf(imgp, 0); +#endif + + et_dyn_addr =3D 0; + if (hdr->e_type =3D=3D ET_DYN) { + /* + * Honour the base load address from the dso if it is + * non-zero for some reason. + */ + if (baddr =3D=3D 0) { + et_dyn_addr =3D ET_DYN_LOAD_ADDR; +#ifdef PAX_ASLR + if (pax_aslr_active(NULL, imgp->proc)) + et_dyn_addr +=3D imgp->proc->p_vmspace->vm_aslr_delta_exec; +#endif + } + } + vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY); if (error) return (error); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 141d438..9301b57 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -410,6 +410,7 @@ struct sysentvec null_sysvec =3D { .sv_fetch_syscall_args =3D null_fetch_syscall_args, .sv_syscallnames =3D NULL, .sv_schedtail =3D NULL, + .sv_pax_aslr_init =3D NULL, }; =20 /* diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 667715e..24caccc 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include "opt_capsicum.h" #include "opt_hwpmc_hooks.h" #include "opt_ktrace.h" +#include "opt_pax.h" #include "opt_vm.h" =20 #include <sys/param.h> @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$"); dtrace_execexit_func_t dtrace_fasttrap_exec; #endif =20 +#if defined(PAX_ASLR) +#include <sys/pax.h> +#endif + SDT_PROVIDER_DECLARE(proc); SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *"); SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int"); @@ -404,6 +409,7 @@ do_execve(td, args, mac_p) imgp->pagesizes =3D 0; imgp->pagesizeslen =3D 0; imgp->stack_prot =3D 0; + imgp->pax_flags =3D 0; =20 #ifdef MAC error =3D mac_execve_enter(imgp, mac_p); @@ -1064,6 +1070,10 @@ exec_new_vmspace(imgp, sv) map =3D &vmspace->vm_map; } =20 +#ifdef PAX_ASLR + pax_aslr_init(curthread, imgp); +#endif + /* Map a shared page */ obj =3D sv->sv_shared_page_obj; if (obj !=3D NULL) { @@ -1107,6 +1117,9 @@ exec_new_vmspace(imgp, sv) */ vmspace->vm_ssize =3D sgrowsiz >> PAGE_SHIFT; vmspace->vm_maxsaddr =3D (char *)sv->sv_usrstack - ssiz; +#ifdef PAX_ASLR + vmspace->vm_maxsaddr -=3D vmspace->vm_aslr_delta_stack; +#endif =20 return (0); } @@ -1266,6 +1279,9 @@ exec_copyout_strings(imgp) szsigcode =3D *(p->p_sysent->sv_szsigcode); } destp =3D (uintptr_t)arginfo; +#ifdef PAX_ASLR + pax_aslr_stack(curthread, &destp); +#endif =20 /* * install sigcode diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index b3d9c24..3cd85d8 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -513,6 +513,11 @@ do_fork(struct thread *td, int flags, struct proc *p2,= struct thread *td2, } =20 /* + * XXXOP: this is the right place? + */ + p2->p_pax =3D p1->p_pax; + + /* * p_limit is copy-on-write. Bump its refcount. */ lim_fork(p1, p2); diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 47cd568..d9036bd 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_pax.h" =20 #include <sys/param.h> #include <sys/types.h> @@ -74,6 +75,10 @@ __FBSDID("$FreeBSD$"); #endif /* INET6 */ #endif /* DDB */ =20 +#if defined(PAX_ASLR) +#include <sys/pax.h> +#endif + #include <security/mac/mac_framework.h> =20 #define DEFAULT_HOSTUUID "00000000-0000-0000-0000-000000000000" @@ -117,6 +122,10 @@ struct prison prison0 =3D { }; MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF); =20 +#if defined(PAX_ASLR) +SYSINIT(pax, SI_SUB_PAX, SI_ORDER_MIDDLE, pax_init_prison, (void *) &priso= n0); +#endif + /* allprison, allprison_racct and lastprid are protected by allprison_lock= =2E */ struct sx allprison_lock; SX_SYSINIT(allprison_lock, &allprison_lock, "allprison"); @@ -1307,6 +1316,10 @@ kern_jail_set(struct thread *td, struct uio *optuio,= int flags) goto done_releroot; } =20 +#if defined(PAX_ASLR) + pax_init_prison(pr); +#endif + mtx_lock(&pr->pr_mtx); /* * New prisons do not yet have a reference, because we do not diff --git a/sys/kern/kern_pax.c b/sys/kern/kern_pax.c new file mode 100644 index 0000000..1bd5ad0 --- /dev/null +++ b/sys/kern/kern_pax.c @@ -0,0 +1,214 @@ +/*- + * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> + * Copyright (c) 2013-2014, by Oliver Pinter <oliver.pntr at gmail.com> + * Copyright (c) 2014, by Shawn Webb <lattera at gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI= ES + * 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 US= E, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_compat.h" +#include "opt_pax.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/imgact.h> +#include <sys/imgact_elf.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/sysent.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/elf_common.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <sys/vnode.h> +#include <sys/queue.h> +#include <sys/libkern.h> +#include <sys/jail.h> + +#include <sys/mman.h> +#include <sys/libkern.h> +#include <sys/exec.h> +#include <sys/kthread.h> + +#include <sys/syslimits.h> +#include <sys/param.h> + +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +#include <machine/elf.h> + +#include <sys/pax.h> + +#include <security/mac_bsdextended/mac_bsdextended.h> + +SYSCTL_NODE(_security, OID_AUTO, pax, CTLFLAG_RD, 0, + "PaX (exploit mitigation) features."); + +struct prison * +pax_get_prison(struct thread *td, struct proc *proc) +{ + + if (td !=3D NULL) { + if ((td->td_proc !=3D NULL) && (td->td_proc->p_ucred !=3D NULL)) + return (td->td_proc->p_ucred->cr_prison); + + return (NULL); + } + if ((proc =3D=3D NULL) || (proc->p_ucred =3D=3D NULL)) + return (NULL); + + return (proc->p_ucred->cr_prison); +} + +void +pax_elf(struct image_params *imgp, uint32_t mode) +{ + u_int flags =3D 0; + + if ((mode & MBI_ALLPAX) =3D=3D MBI_ALLPAX) + goto end; + + if (mode & MBI_FORCE_ASLR_ENABLED) + flags |=3D PAX_NOTE_ASLR; + else if (mode & MBI_FORCE_ASLR_DISABLED) + flags |=3D PAX_NOTE_NOASLR; + +end: + if (imgp !=3D NULL) { + imgp->pax_flags =3D flags; + if (imgp->proc !=3D NULL) { + PROC_LOCK(imgp->proc); + imgp->proc->p_pax =3D flags; + PROC_UNLOCK(imgp->proc); + } + } +} + + +/* + * print out PaX settings on boot time, and validate some of them + */ +void +pax_init(void) +{ +#if defined(PAX_ASLR) + const char *status_str[] =3D { + [0] =3D "disabled", + [1] =3D "opt-in", + [2] =3D "opt-out", + [3] =3D "force enabled", + [4] =3D "UNKNOWN -> changed to \"force enabled\"" + }; +#endif + +#ifdef PAX_ASLR + switch (pax_aslr_status) { + case 0: + case 1: + case 2: + case 3: + break; + default: + printf("[PAX ASLR] WARNING, invalid PAX settings in loader.conf!" + " (pax_aslr_status =3D %d)\n", pax_aslr_status); + pax_aslr_status =3D 3; + break; + } + printf("[PAX ASLR] status: %s\n", status_str[pax_aslr_status]); + printf("[PAX ASLR] mmap: %d bit\n", pax_aslr_mmap_len); + printf("[PAX ASLR] exec base: %d bit\n", pax_aslr_exec_len); + printf("[PAX ASLR] stack: %d bit\n", pax_aslr_stack_len); + +#ifdef COMPAT_FREEBSD32 + switch (pax_aslr_compat_status) { + case 0: + case 1: + case 2: + case 3: + break; + default: + printf("[PAX ASLR (compat)] WARNING, invalid PAX settings in loader.conf= ! " + "(pax_aslr_compat_status =3D %d)\n", pax_aslr_compat_status); + pax_aslr_compat_status =3D 3; + break; + } + printf("[PAX ASLR (compat)] status: %s\n", status_str[pax_aslr_compat_sta= tus]); + printf("[PAX ASLR (compat)] mmap: %d bit\n", pax_aslr_compat_mmap_len); + printf("[PAX ASLR (compat)] exec base: %d bit\n", pax_aslr_compat_exec_le= n); + printf("[PAX ASLR (compat)] stack: %d bit\n", pax_aslr_compat_stack_len); +#endif /* COMPAT_FREEBSD32 */ +#endif /* PAX_ASLR */ + + printf("[PAX LOG] logging to system: %d\n", pax_log_log); + printf("[PAX LOG] logging to user: %d\n", pax_log_ulog); +} +SYSINIT(pax, SI_SUB_PAX, SI_ORDER_FIRST, pax_init, NULL); + +void +pax_init_prison(struct prison *pr) +{ + + if (pr =3D=3D NULL) + return; + + if (pr->pr_pax_set) + return; + + mtx_lock(&(pr->pr_mtx)); + + if (pax_aslr_debug) + uprintf("[PaX ASLR] %s: Setting prison %s ASLR variables\n", + __func__, pr->pr_name); + +#ifdef PAX_ASLR + pr->pr_pax_aslr_status =3D pax_aslr_status; + pr->pr_pax_aslr_debug =3D pax_aslr_debug; + pr->pr_pax_aslr_mmap_len =3D pax_aslr_mmap_len; + pr->pr_pax_aslr_stack_len =3D pax_aslr_stack_len; + pr->pr_pax_aslr_exec_len =3D pax_aslr_exec_len; + +#ifdef COMPAT_FREEBSD32 + pr->pr_pax_aslr_compat_status =3D pax_aslr_compat_status; + pr->pr_pax_aslr_compat_mmap_len =3D pax_aslr_compat_mmap_len; + pr->pr_pax_aslr_compat_stack_len =3D pax_aslr_compat_stack_len; + pr->pr_pax_aslr_compat_exec_len =3D pax_aslr_compat_exec_len; +#endif /* COMPAT_FREEBSD32 */ +#endif /* PAX_ASLR */ + + pr->pr_pax_log_log =3D pax_log_log; + pr->pr_pax_log_ulog =3D pax_log_ulog; + + pr->pr_pax_set =3D 1; + + mtx_unlock(&(pr->pr_mtx)); +} diff --git a/sys/kern/kern_pax_aslr.c b/sys/kern/kern_pax_aslr.c new file mode 100644 index 0000000..4b5e8dd --- /dev/null +++ b/sys/kern/kern_pax_aslr.c @@ -0,0 +1,685 @@ +/*- + * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> + * Copyright (c) 2013-2014, by Oliver Pinter <oliver.pntr at gmail.com> + * Copyright (c) 2014, by Shawn Webb <lattera at gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI= ES + * 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 US= E, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_compat.h" +#include "opt_pax.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/imgact.h> +#include <sys/imgact_elf.h> +#include <sys/sysent.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/elf_common.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <sys/vnode.h> +#include <sys/queue.h> +#include <sys/libkern.h> +#include <sys/jail.h> + +#include <sys/mman.h> +#include <sys/libkern.h> +#include <sys/exec.h> +#include <sys/kthread.h> + +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +#include <machine/elf.h> + +#include <sys/pax.h> + +FEATURE(aslr, "Address Space Layout Randomization."); + +int pax_aslr_status =3D PAX_ASLR_OPTOUT; +int pax_aslr_debug =3D 0; + +#ifdef PAX_ASLR_MAX_SEC +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_MAX_LEN; +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_MAX_LEN; +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_MAX_LEN; +#else +int pax_aslr_mmap_len =3D PAX_ASLR_DELTA_MMAP_DEF_LEN; +int pax_aslr_stack_len =3D PAX_ASLR_DELTA_STACK_DEF_LEN; +int pax_aslr_exec_len =3D PAX_ASLR_DELTA_EXEC_DEF_LEN; +#endif /* PAX_ASLR_MAX_SEC */ + +#ifdef COMPAT_FREEBSD32 +int pax_aslr_compat_status =3D PAX_ASLR_OPTOUT; +#ifdef PAX_ASLR_MAX_SEC +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN; +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN; +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN; +#else +int pax_aslr_compat_mmap_len =3D PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN; +int pax_aslr_compat_stack_len =3D PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN; +int pax_aslr_compat_exec_len =3D PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN; +#endif /* PAX_ASLR_MAX_SEC */ +#endif /* COMPAT_FREEBSD32 */ + +TUNABLE_INT("security.pax.aslr.status", &pax_aslr_status); +TUNABLE_INT("security.pax.aslr.mmap_len", &pax_aslr_mmap_len); +TUNABLE_INT("security.pax.aslr.debug", &pax_aslr_debug); +TUNABLE_INT("security.pax.aslr.stack_len", &pax_aslr_stack_len); +TUNABLE_INT("security.pax.aslr.exec_len", &pax_aslr_exec_len); +#ifdef COMPAT_FREEBSD32 +TUNABLE_INT("security.pax.aslr.compat.status", &pax_aslr_compat_status); +TUNABLE_INT("security.pax.aslr.compat.mmap", &pax_aslr_compat_mmap_len); +TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_stack_len); +TUNABLE_INT("security.pax.aslr.compat.stack", &pax_aslr_compat_exec_len); +#endif + + +#ifdef PAX_SYSCTLS +/* + * sysctls and tunables + */ +static int sysctl_pax_aslr_debug(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS); + +SYSCTL_DECL(_security_pax); + +SYSCTL_NODE(_security_pax, OID_AUTO, aslr, CTLFLAG_RD, 0, + "Address Space Layout Randomization."); + +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, status, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_aslr_status, "I", + "Restrictions status. " + "0 - disabled, " + "1 - opt-in, " + "2 - opt-out, " + "3 - force enabled"); + +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, debug, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_aslr_debug, "I", + "ASLR debug mode"); + +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, mmap_len, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_aslr_mmap, "I", + "Number of bits randomized for mmap(2) calls. " + "32 bit: [8,16] 64 bit: [16,32]"); + +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, stack_len, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_aslr_stack, "I", + "Number of bits randomized for the stack. " + "32 bit: [6,12] 64 bit: [12,21]"); + +SYSCTL_PROC(_security_pax_aslr, OID_AUTO, exec_len, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_aslr_exec, "I", + "Number of bits randomized for the PIE exec base. " + "32 bit: [6,12] 64 bit: [12,21]"); + +static int +sysctl_pax_aslr_status(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_status : pax_aslr_status; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || (req->newptr =3D=3D NULL)) + return (err); + + switch (val) { + case PAX_ASLR_DISABLED: + case PAX_ASLR_OPTIN: + case PAX_ASLR_OPTOUT: + case PAX_ASLR_FORCE_ENABLED: + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_status =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_status =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + break; + default: + return (EINVAL); + } + + return (0); +} + +static int +sysctl_pax_aslr_debug(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr=3DNULL; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + if ((pr !=3D NULL) && !(pr->pr_pax_set)) + pax_init_prison(pr); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_debug : pax_aslr_debug; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + switch (val) { + case 0: + case 1: + break; + default: + return (EINVAL); + + } + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_debug =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_debug =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +static int +sysctl_pax_aslr_mmap(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr=3DNULL; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + if ((pr !=3D NULL) && !(pr->pr_pax_set)) + pax_init_prison(pr); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_mmap_len : pax_aslr_mmap_len; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + if (val < PAX_ASLR_DELTA_MMAP_MIN_LEN || + val > PAX_ASLR_DELTA_MMAP_MAX_LEN) + return (EINVAL); + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_mmap_len =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_mmap_len =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +static int +sysctl_pax_aslr_stack(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr=3DNULL; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + if ((pr !=3D NULL) && !(pr->pr_pax_set)) + pax_init_prison(pr); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_stack_len : pax_aslr_stack_len; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + if (val < PAX_ASLR_DELTA_STACK_MIN_LEN || + val > PAX_ASLR_DELTA_STACK_MAX_LEN) + return (EINVAL); + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_stack_len =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_stack_len =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +static int +sysctl_pax_aslr_exec(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr=3DNULL; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + if ((pr !=3D NULL) && !(pr->pr_pax_set)) + pax_init_prison(pr); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_exec_len : pax_aslr_exec_len; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || (req->newptr =3D=3D NULL)) + return (err); + + if (val < PAX_ASLR_DELTA_EXEC_MIN_LEN || + val > PAX_ASLR_DELTA_EXEC_MAX_LEN) + return (EINVAL); + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_exec_len =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_exec_len =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +/* + * COMPAT_FREEBSD32 and linuxulator.. + */ +#ifdef COMPAT_FREEBSD32 +static int sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS); + +SYSCTL_NODE(_security_pax_aslr, OID_AUTO, compat, CTLFLAG_RD, 0, + "Setting for COMPAT_FREEBSD32 and linuxulator."); + +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, status, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON, + NULL, 0, sysctl_pax_aslr_compat_status, "I", + "Restrictions status. " + "0 - disabled, " + "1 - enabled, " + "2 - global enabled, " + "3 - force global enabled"); + +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, mmap_len, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON, + NULL, 0, sysctl_pax_aslr_compat_mmap, "I", + "Number of bits randomized for mmap(2) calls. " + "32 bit: [8,16]"); + +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, stack_len, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON, + NULL, 0, sysctl_pax_aslr_compat_stack, "I", + "Number of bits randomized for the stack. " + "32 bit: [6,12]"); + +SYSCTL_PROC(_security_pax_aslr_compat, OID_AUTO, exec_len, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON, + NULL, 0, sysctl_pax_aslr_compat_exec, "I", + "Number of bits randomized for the PIE exec base. " + "32 bit: [6,12]"); + +static int +sysctl_pax_aslr_compat_status(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + val =3D (pr !=3D NULL) ?pr->pr_pax_aslr_compat_status : pax_aslr_compat_s= tatus; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || (req->newptr =3D=3D NULL)) + return (err); + + switch (val) { + case PAX_ASLR_DISABLED: + case PAX_ASLR_OPTIN: + case PAX_ASLR_OPTOUT: + case PAX_ASLR_FORCE_ENABLED: + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_compat_status =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_compat_status =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + break; + default: + return (EINVAL); + } + + return (0); +} + +static int +sysctl_pax_aslr_compat_mmap(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_compat_mmap_len : pax_aslr_compa= t_mmap_len; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + if (val < PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN || + val > PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN) + return (EINVAL); + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_compat_mmap_len =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_compat_mmap_len =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +static int +sysctl_pax_aslr_compat_stack(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + val =3D (pr !=3D NULL) ? pr->pr_pax_aslr_compat_stack_len : pax_aslr_comp= at_stack_len; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + if (val < PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN || + val > PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN) + return (EINVAL); + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_compat_stack_len =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_compat_stack_len =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +static int +sysctl_pax_aslr_compat_exec(SYSCTL_HANDLER_ARGS) +{ + struct prison *pr; + int err, val; + + pr =3D pax_get_prison(req->td, NULL); + + if (pr !=3D NULL) + val =3D pr->pr_pax_aslr_compat_exec_len; + else + val =3D pax_aslr_compat_exec_len; + + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + if (val < PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN || + val > PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN) + return (EINVAL); + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_aslr_compat_exec_len =3D val; + + if (pr !=3D NULL) { + mtx_lock(&(pr->pr_mtx)); + pr->pr_pax_aslr_compat_exec_len =3D val; + mtx_unlock(&(pr->pr_mtx)); + } + + return (0); +} + +#endif /* COMPAT_FREEBSD32 */ +#endif /* PAX_SYSCTLS */ + + +/* + * ASLR functions + */ +bool +pax_aslr_active(struct thread *td, struct proc *proc) +{ + int status; + struct prison *pr; + uint32_t flags; + + if ((td =3D=3D NULL) && (proc =3D=3D NULL)) + return (true); + + pr =3D pax_get_prison(td, proc); + + flags =3D (td !=3D NULL) ? td->td_proc->p_pax : proc->p_pax; + if (((flags & 0xaaaaaaaa) & ((flags & 0x55555555) << 1)) !=3D 0) { + pax_log_aslr(pr, __func__, "inconsistent paxflags: %x\n", flags); + pax_ulog_aslr(pr, NULL, "inconsistent paxflags: %x\n", flags); + return (true); + } + + if (pr !=3D NULL) + status =3D pr->pr_pax_aslr_status; + else + status =3D pax_aslr_status; + + switch (status) { + case PAX_ASLR_DISABLED: + return (false); + case PAX_ASLR_FORCE_ENABLED: + return (true); + case PAX_ASLR_OPTIN: + if ((flags & PAX_NOTE_ASLR) =3D=3D 0) { + pax_log_aslr(pr, __func__, + "ASLR is opt-in, and executable does not have ASLR enabled\n"); + pax_ulog_aslr(pr, NULL, + "ASLR is opt-in, and executable does not have ASLR enabled\n"); + return (false); + } + break; + case PAX_ASLR_OPTOUT: + if ((flags & PAX_NOTE_NOASLR) !=3D 0) { + pax_log_aslr(pr, __func__, + "ASLR is opt-out, and executable explicitly disabled ASLR\n"); + pax_ulog_aslr(pr, NULL, + "ASLR is opt-out, and executable explicitly disabled ASLR\n"); + return (false); + } + break; + default: + return (true); + } + + return (true); +} + +void +_pax_aslr_init(struct vmspace *vm, struct prison *pr) +{ + if (vm =3D=3D NULL) + panic("[PaX ASLR] %s: vm =3D=3D NULL", __func__); + + vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(), + PAX_ASLR_DELTA_MMAP_LSB, (pr !=3D NULL) ? + pr->pr_pax_aslr_mmap_len : + pax_aslr_mmap_len); + vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(), + PAX_ASLR_DELTA_STACK_LSB, (pr !=3D NULL) ? + pr->pr_pax_aslr_stack_len : + pax_aslr_stack_len); + vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack); + vm->vm_aslr_delta_exec =3D PAX_ASLR_DELTA(arc4random(), + PAX_ASLR_DELTA_EXEC_LSB, (pr !=3D NULL) ? + pr->pr_pax_aslr_exec_len : + pax_aslr_exec_len); + + if ((pr !=3D NULL) && pr->pr_pax_aslr_debug) { + pax_log_aslr(pr, __func__, "vm_aslr_delta_mmap=3D%p\n", + (void *) vm->vm_aslr_delta_mmap); + pax_log_aslr(pr, __func__, "vm_aslr_delta_stack=3D%p\n", + (void *) vm->vm_aslr_delta_stack); + pax_log_aslr(pr, __func__, "vm_aslr_delta_exec=3D%p\n", + (void *) vm->vm_aslr_delta_exec); + pax_ulog_aslr(pr, NULL, "vm_aslr_delta_mmap=3D%p\n", + (void *) vm->vm_aslr_delta_mmap); + pax_ulog_aslr(pr, NULL, "vm_aslr_delta_stack=3D%p\n", + (void *) vm->vm_aslr_delta_stack); + pax_ulog_aslr(pr, NULL, "vm_aslr_delta_exec=3D%p\n", + (void *) vm->vm_aslr_delta_exec); + } +} + +#ifdef COMPAT_FREEBSD32 +void +_pax_aslr_init32(struct vmspace *vm, struct prison *pr) +{ + if (vm =3D=3D NULL) + panic("[PaX ASLR] %s: vm =3D=3D NULL", __func__); + + vm->vm_aslr_delta_mmap =3D PAX_ASLR_DELTA(arc4random(), + PAX_ASLR_COMPAT_DELTA_MMAP_LSB, (pr !=3D NULL) ? + pr->pr_pax_aslr_compat_mmap_len : + pax_aslr_compat_mmap_len); + vm->vm_aslr_delta_stack =3D PAX_ASLR_DELTA(arc4random(), + PAX_ASLR_COMPAT_DELTA_STACK_LSB, (pr !=3D NULL) ? + pr->pr_pax_aslr_compat_stack_len : + pax_aslr_compat_stack_len); + vm->vm_aslr_delta_stack =3D ALIGN(vm->vm_aslr_delta_stack); + vm->vm_aslr_delta_exec =3D PAX_ASLR_DELTA(arc4random(), + PAX_ASLR_DELTA_EXEC_LSB, (pr !=3D NULL) ? + pr->pr_pax_aslr_compat_exec_len : + pax_aslr_compat_exec_len); + + if ((pr !=3D NULL) && pr->pr_pax_aslr_debug) { + pax_log_aslr(pr, __func__, "vm_aslr_delta_mmap=3D%p\n", + (void *) vm->vm_aslr_delta_mmap); + pax_log_aslr(pr, __func__, "vm_aslr_delta_stack=3D%p\n", + (void *) vm->vm_aslr_delta_stack); + pax_log_aslr(pr, __func__, "vm_aslr_delta_exec=3D%p\n", + (void *) vm->vm_aslr_delta_exec); + pax_ulog_aslr(pr, NULL, "vm_aslr_delta_mmap=3D%p\n", + (void *) vm->vm_aslr_delta_mmap); + pax_ulog_aslr(pr, NULL, "vm_aslr_delta_stack=3D%p\n", + (void *) vm->vm_aslr_delta_stack); + pax_ulog_aslr(pr, NULL, "vm_aslr_delta_exec=3D%p\n", + (void *) vm->vm_aslr_delta_exec); + } +} +#endif + +void +pax_aslr_init(struct thread *td, struct image_params *imgp) +{ + struct prison *pr; + struct vmspace *vm; + + pr =3D pax_get_prison(td, NULL); + + if (imgp =3D=3D NULL) + panic("[PaX ASLR] %s: imgp =3D=3D NULL", __func__); + + if (!pax_aslr_active(td, NULL)) + return; + + vm =3D imgp->proc->p_vmspace; + + if (imgp->sysent->sv_pax_aslr_init !=3D NULL) + imgp->sysent->sv_pax_aslr_init(vm, pr); +} + +void +pax_aslr_mmap(struct thread *td, vm_offset_t *addr, vm_offset_t orig_addr,= int flags) +{ + struct prison *pr; + + if (!pax_aslr_active(td, NULL)) + return; + + orig_addr =3D *addr; + + pr =3D pax_get_prison(td, NULL); + + if (!(flags & MAP_FIXED) && ((orig_addr =3D=3D 0) || !(flags & MAP_ANON))= ) { + pax_log_aslr(pr, __func__, "applying to %p orig_addr=3D%p flags=3D%x\n", + (void *)*addr, (void *)orig_addr, flags); + + if (!(td->td_proc->p_vmspace->vm_map.flags & MAP_ENTRY_GROWS_DOWN)) + *addr +=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap; + else + *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_mmap; + pax_log_aslr(pr, __func__, "result %p\n", (void *)*addr); + } else { + pax_log_aslr(pr, __func__, "not applying to %p orig_addr=3D%p flags=3D%x= \n", + (void *)*addr, (void *)orig_addr, flags); + } +} + +void +pax_aslr_stack(struct thread *td, uintptr_t *addr) +{ + struct prison *pr; + uintptr_t orig_addr; + + if (!pax_aslr_active(td, NULL)) + return; + + pr =3D pax_get_prison(td, NULL); + + orig_addr =3D *addr; + *addr -=3D td->td_proc->p_vmspace->vm_aslr_delta_stack; + pax_log_aslr(pr, __func__, "orig_addr=3D%p, new_addr=3D%p\n", + (void *)orig_addr, (void *)*addr); + pax_ulog_aslr(pr, NULL, "orig_addr=3D%p, new_addr=3D%p\n", + (void *)orig_addr, (void *)*addr); +} diff --git a/sys/kern/kern_pax_log.c b/sys/kern/kern_pax_log.c new file mode 100644 index 0000000..943ac81 --- /dev/null +++ b/sys/kern/kern_pax_log.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2014, by Oliver Pinter <oliver.pntr at gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP= OSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT= IAL + * 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, STR= ICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W= AY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/kernel.h> +#include <sys/pax.h> +#include <sys/sbuf.h> +#include <sys/jail.h> +#include <machine/stdarg.h> + +#define __PAX_LOG_TEMPLATE(SUBJECT, name) \ +void \ +pax_log_##name(struct prison *pr, const char *caller_name, const char* fmt= , ...)\ +{ \ + struct sbuf *sb; \ + va_list args; \ + \ + if ((pr !=3D NULL) && (pr->pr_pax_log_log =3D=3D 0)) \ + return; \ + \ + sb =3D sbuf_new_auto(); \ + if (sb =3D=3D NULL) \ + panic("%s: Could not allocate memory", __func__); \ + sbuf_printf(sb, "[PAX "#SUBJECT"] "); \ + if (caller_name !=3D NULL) \ + sbuf_printf(sb, "%s: ", caller_name); \ + va_start(args, fmt); \ + sbuf_vprintf(sb, fmt, args); \ + va_end(args); \ + if (sbuf_finish(sb) !=3D 0) \ + panic("%s: Could not generate message", __func__); \ + \ + printf("%s", sbuf_data(sb)); \ + sbuf_delete(sb); \ +} \ + \ +void \ +pax_ulog_##name(struct prison *pr, const char *caller_name, const char* fm= t, ...)\ +{ \ + struct sbuf *sb; \ + va_list args; \ + \ + if ((pr !=3D NULL) && (pr->pr_pax_log_ulog =3D=3D 0)) \ + return; \ + \ + sb =3D sbuf_new_auto(); \ + if (sb =3D=3D NULL) \ + panic("%s: Could not allocate memory", __func__); \ + sbuf_printf(sb, "[PAX "#SUBJECT"] "); \ + if (caller_name !=3D NULL) \ + sbuf_printf(sb, "%s: ", caller_name); \ + va_start(args, fmt); \ + sbuf_vprintf(sb, fmt, args); \ + va_end(args); \ + if (sbuf_finish(sb) !=3D 0) \ + panic("%s: Could not generate message", __func__); \ + \ + uprintf("%s", sbuf_data(sb)); \ + sbuf_delete(sb); \ +} + + +static int sysctl_pax_log_log(SYSCTL_HANDLER_ARGS); +static int sysctl_pax_log_ulog(SYSCTL_HANDLER_ARGS); + +int pax_log_log =3D PAX_LOG_LOG; +int pax_log_ulog =3D PAX_LOG_ULOG; + +SYSCTL_DECL(_security_pax); + +SYSCTL_NODE(_security_pax, OID_AUTO, log, CTLFLAG_RD, 0, + "PAX related logging facility."); + +SYSCTL_PROC(_security_pax_log, OID_AUTO, log, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_log_log, "I", + "log to syslog " + "0 - disabled, " + "1 - enabled "); +TUNABLE_INT("security.pax.log.log", &pax_log_log); + +SYSCTL_PROC(_security_pax_log, OID_AUTO, ulog, + CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_PRISON|CTLFLAG_SECURE, + NULL, 0, sysctl_pax_log_ulog, "I", + "log to user terminal" + "0 - disabled, " + "1 - enabled "); +TUNABLE_INT("security.pax.log.ulog", &pax_log_ulog); + +static int +sysctl_pax_log_log(SYSCTL_HANDLER_ARGS) +{ + int err; + int val; + struct prison *pr=3DNULL; + + pr =3D pax_get_prison(req->td, NULL); + + if ((pr !=3D NULL) && !(pr->pr_pax_set)) + pax_init_prison(pr); + + val =3D (pr !=3D NULL) ? pr->pr_pax_log_log : pax_log_log; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + switch (val) { + case 0: + case 1: + break; + default: + return (EINVAL); + + } + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_log_log =3D val; + if (pr !=3D NULL) + pr->pr_pax_log_log =3D val; + + return (0); +} + +static int +sysctl_pax_log_ulog(SYSCTL_HANDLER_ARGS) +{ + int err; + int val; + struct prison *pr=3DNULL; + + pr =3D pax_get_prison(req->td, NULL); + + if ((pr !=3D NULL) && !(pr->pr_pax_set)) + pax_init_prison(pr); + + val =3D (pr !=3D NULL) ? pr->pr_pax_log_ulog : pax_log_ulog; + err =3D sysctl_handle_int(oidp, &val, sizeof(int), req); + if (err || !req->newptr) + return (err); + + switch (val) { + case 0: + case 1: + break; + default: + return (EINVAL); + + } + + if ((pr =3D=3D NULL) || (pr =3D=3D &prison0)) + pax_log_ulog =3D val; + if (pr !=3D NULL) + pr->pr_pax_log_ulog =3D val; + + return (0); +} + + +__PAX_LOG_TEMPLATE(ASLR, aslr) diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c index d374713..f95ba35 100644 --- a/sys/mips/mips/elf_machdep.c +++ b/sys/mips/mips/elf_machdep.c @@ -28,6 +28,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -49,6 +51,10 @@ __FBSDID("$FreeBSD$"); #include <machine/md_var.h> #include <machine/cache.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + #ifdef __mips_n64 struct sysentvec elf64_freebsd_sysvec =3D { .sv_size =3D SYS_MAXSYSCALL, @@ -83,6 +89,11 @@ struct sysentvec elf64_freebsd_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; =20 static Elf64_Brandinfo freebsd_brand_info =3D { @@ -139,6 +150,11 @@ struct sysentvec elf32_freebsd_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init32, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; =20 static Elf32_Brandinfo freebsd_brand_info =3D { diff --git a/sys/mips/mips/freebsd32_machdep.c b/sys/mips/mips/freebsd32_ma= chdep.c index dfdf70f..103ad84 100644 --- a/sys/mips/mips/freebsd32_machdep.c +++ b/sys/mips/mips/freebsd32_machdep.c @@ -31,6 +31,7 @@ */ =20 #include "opt_compat.h" +#include "opt_pax.h" =20 #define __ELF_WORD_SIZE 32 =20 @@ -66,6 +67,10 @@ #include <compat/freebsd32/freebsd32_util.h> #include <compat/freebsd32/freebsd32_proto.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + static void freebsd32_exec_setregs(struct thread *, struct image_params *,= u_long); static int get_mcontext32(struct thread *, mcontext32_t *, int); static int set_mcontext32(struct thread *, const mcontext32_t *); @@ -106,6 +111,11 @@ struct sysentvec elf32_freebsd_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D freebsd32_syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init32, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); =20 diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf3= 2_machdep.c index dbe58df..229fe97 100644 --- a/sys/powerpc/powerpc/elf32_machdep.c +++ b/sys/powerpc/powerpc/elf32_machdep.c @@ -25,6 +25,8 @@ * $FreeBSD$ */ =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -52,6 +54,10 @@ #include <machine/reg.h> #include <machine/md_var.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + #ifdef __powerpc64__ #include <compat/freebsd32/freebsd32_proto.h> #include <compat/freebsd32/freebsd32_util.h> @@ -107,6 +113,11 @@ struct sysentvec elf32_freebsd_sysvec =3D { .sv_shared_page_base =3D FREEBSD32_SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init32, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); =20 diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf6= 4_machdep.c index 0c41a8d..095f37b0 100644 --- a/sys/powerpc/powerpc/elf64_machdep.c +++ b/sys/powerpc/powerpc/elf64_machdep.c @@ -25,6 +25,8 @@ * $FreeBSD$ */ =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -48,6 +50,10 @@ #include <machine/elf.h> #include <machine/md_var.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + struct sysentvec elf64_freebsd_sysvec =3D { .sv_size =3D SYS_MAXSYSCALL, .sv_table =3D sysent, @@ -83,6 +89,11 @@ struct sysentvec elf64_freebsd_sysvec =3D { .sv_shared_page_base =3D SHAREDPAGE, .sv_shared_page_len =3D PAGE_SIZE, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); =20 diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/= mac_bsdextended/mac_bsdextended.c index ccbc525..520168d 100644 --- a/sys/security/mac_bsdextended/mac_bsdextended.c +++ b/sys/security/mac_bsdextended/mac_bsdextended.c @@ -47,6 +47,8 @@ * firewall-like rules regarding users and file system objects. */ =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/acl.h> #include <sys/kernel.h> @@ -56,14 +58,20 @@ #include <sys/module.h> #include <sys/mount.h> #include <sys/mutex.h> +#include <sys/param.h> #include <sys/priv.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/vnode.h> #include <sys/sysctl.h> #include <sys/syslog.h> +#include <sys/syslimits.h> #include <sys/stat.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + #include <security/mac/mac_policy.h> #include <security/mac_bsdextended/mac_bsdextended.h> #include <security/mac_bsdextended/ugidfw_internal.h> @@ -117,7 +125,6 @@ SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstma= tch_enabled, static int ugidfw_rule_valid(struct mac_bsdextended_rule *rule) { - if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) !=3D MBS_ALL_FLAGS) return (EINVAL); if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) !=3D MBS_ALL_FLAGS) @@ -129,8 +136,13 @@ ugidfw_rule_valid(struct mac_bsdextended_rule *rule) if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) && (rule->mbr_object.mbo_type | MBO_ALL_TYPE) !=3D MBO_ALL_TYPE) return (EINVAL); +#ifdef PAX_ASLR + if ((rule->mbr_pax | MBI_ALLPAX) !=3D MBI_ALLPAX) + return (EINVAL); +#endif if ((rule->mbr_mode | MBI_ALLPERM) !=3D MBI_ALLPERM) return (EINVAL); + return (0); } =20 @@ -227,7 +239,7 @@ ugidfw_destroy(struct mac_policy_conf *mpc) =20 static int ugidfw_rulecheck(struct mac_bsdextended_rule *rule, - struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode) + struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode,= struct image_params *imgp) { int mac_granted, match, priv_granted; int i; @@ -305,6 +317,10 @@ ugidfw_rulecheck(struct mac_bsdextended_rule *rule, match =3D (bcmp(&(vp->v_mount->mnt_stat.f_fsid), &(rule->mbr_object.mbo_fsid), sizeof(rule->mbr_object.mbo_fsid)) =3D=3D 0); +#if defined(PAX_ASLR) + if (match && rule->mbr_object.mbo_inode) + match =3D (vap->va_fileid =3D=3D rule->mbr_object.mbo_inode); +#endif if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED) match =3D !match; if (!match) @@ -413,6 +429,11 @@ ugidfw_rulecheck(struct mac_bsdextended_rule *rule, return (EACCES); } =20 +#ifdef PAX_ASLR + if (imgp !=3D NULL) + pax_elf(imgp, rule->mbr_pax); +#endif + /* * If the rule matched, permits access, and first match is enabled, * return success. @@ -425,7 +446,7 @@ ugidfw_rulecheck(struct mac_bsdextended_rule *rule, =20 int ugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, - int acc_mode) + int acc_mode, struct image_params *imgp) { int error, i; =20 @@ -441,7 +462,7 @@ ugidfw_check(struct ucred *cred, struct vnode *vp, stru= ct vattr *vap, if (rules[i] =3D=3D NULL) continue; error =3D ugidfw_rulecheck(rules[i], cred, - vp, vap, acc_mode); + vp, vap, acc_mode, imgp); if (error =3D=3D EJUSTRETURN) break; if (error) { @@ -454,7 +475,7 @@ ugidfw_check(struct ucred *cred, struct vnode *vp, stru= ct vattr *vap, } =20 int -ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode) +ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode, struct= image_params *imgp) { int error; struct vattr vap; @@ -464,7 +485,7 @@ ugidfw_check_vp(struct ucred *cred, struct vnode *vp, i= nt acc_mode) error =3D VOP_GETATTR(vp, &vap, cred); if (error) return (error); - return (ugidfw_check(cred, vp, &vap, acc_mode)); + return (ugidfw_check(cred, vp, &vap, acc_mode, imgp)); } =20 int diff --git a/sys/security/mac_bsdextended/mac_bsdextended.h b/sys/security/= mac_bsdextended/mac_bsdextended.h index c09abc0..c3cbf28 100644 --- a/sys/security/mac_bsdextended/mac_bsdextended.h +++ b/sys/security/mac_bsdextended/mac_bsdextended.h @@ -51,6 +51,9 @@ #define MBI_ADMIN 010000 #define MBI_STAT 020000 #define MBI_APPEND 040000 +#define MBI_FORCE_ASLR_ENABLED 0x01 +#define MBI_FORCE_ASLR_DISABLED 0x02 +#define MBI_ALLPAX (MBI_FORCE_ASLR_ENABLED | MBI_FORCE_ASLR_DISABLED) #define MBI_ALLPERM (MBI_EXEC | MBI_WRITE | MBI_READ | MBI_ADMIN | \ MBI_STAT | MBI_APPEND) =20 @@ -78,6 +81,7 @@ struct mac_bsdextended_subject { #define MBO_UID_SUBJECT 0x00000020 /* uid must match subject */ #define MBO_GID_SUBJECT 0x00000040 /* gid must match subject */ #define MBO_TYPE_DEFINED 0x00000080 /* object type should be matched */ +#define MBO_PAXPATH_DEFINED 0x00000100 /* TODO: paxpath should be matched = */ =20 #define MBO_ALL_FLAGS (MBO_UID_DEFINED | MBO_GID_DEFINED | MBO_FSID_DEFINE= D | \ MBO_SUID | MBO_SGID | MBO_UID_SUBJECT | MBO_GID_SUBJECT | \ @@ -103,12 +107,15 @@ struct mac_bsdextended_object { gid_t mbo_gid_max; struct fsid mbo_fsid; int mbo_type; + ino_t mbo_inode; + char mbo_paxpath[MAXPATHLEN]; }; =20 struct mac_bsdextended_rule { struct mac_bsdextended_subject mbr_subject; struct mac_bsdextended_object mbr_object; mode_t mbr_mode; /* maximum access */ + uint32_t mbr_pax; }; =20 #endif /* _SYS_SECURITY_MAC_BSDEXTENDED_H */ diff --git a/sys/security/mac_bsdextended/ugidfw_internal.h b/sys/security/= mac_bsdextended/ugidfw_internal.h index 5597fd1..18c74dc 100644 --- a/sys/security/mac_bsdextended/ugidfw_internal.h +++ b/sys/security/mac_bsdextended/ugidfw_internal.h @@ -36,8 +36,9 @@ */ int ugidfw_accmode2mbi(accmode_t accmode); int ugidfw_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, - int acc_mode); -int ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode); + int acc_mode, struct image_params *imgp); +int ugidfw_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode, + struct image_params *imgp); =20 /* * System access control checks. diff --git a/sys/security/mac_bsdextended/ugidfw_system.c b/sys/security/ma= c_bsdextended/ugidfw_system.c index 49e4f1d..2829a00 100644 --- a/sys/security/mac_bsdextended/ugidfw_system.c +++ b/sys/security/mac_bsdextended/ugidfw_system.c @@ -66,7 +66,7 @@ ugidfw_system_check_acct(struct ucred *cred, struct vnode= *vp, { =20 if (vp !=3D NULL) - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); else return (0); } @@ -77,7 +77,7 @@ ugidfw_system_check_auditctl(struct ucred *cred, struct v= node *vp, { =20 if (vp !=3D NULL) - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); else return (0); } @@ -87,5 +87,5 @@ ugidfw_system_check_swapon(struct ucred *cred, struct vno= de *vp, struct label *vplabel) { =20 - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); } diff --git a/sys/security/mac_bsdextended/ugidfw_vnode.c b/sys/security/mac= _bsdextended/ugidfw_vnode.c index 8ec2d48..2065e6e 100644 --- a/sys/security/mac_bsdextended/ugidfw_vnode.c +++ b/sys/security/mac_bsdextended/ugidfw_vnode.c @@ -65,7 +65,7 @@ ugidfw_vnode_check_access(struct ucred *cred, struct vnod= e *vp, struct label *vplabel, accmode_t accmode) { =20 - return (ugidfw_check_vp(cred, vp, ugidfw_accmode2mbi(accmode))); + return (ugidfw_check_vp(cred, vp, ugidfw_accmode2mbi(accmode), NULL)); } =20 int @@ -73,7 +73,7 @@ ugidfw_vnode_check_chdir(struct ucred *cred, struct vnode= *dvp, struct label *dvplabel) { =20 - return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); + return (ugidfw_check_vp(cred, dvp, MBI_EXEC, NULL)); } =20 int @@ -81,7 +81,7 @@ ugidfw_vnode_check_chroot(struct ucred *cred, struct vnod= e *dvp, struct label *dvplabel) { =20 - return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); + return (ugidfw_check_vp(cred, dvp, MBI_EXEC, NULL)); } =20 int @@ -89,7 +89,7 @@ ugidfw_check_create_vnode(struct ucred *cred, struct vnod= e *dvp, struct label *dvplabel, struct componentname *cnp, struct vattr *vap) { =20 - return (ugidfw_check_vp(cred, dvp, MBI_WRITE)); + return (ugidfw_check_vp(cred, dvp, MBI_WRITE, NULL)); } =20 int @@ -97,7 +97,7 @@ ugidfw_vnode_check_deleteacl(struct ucred *cred, struct v= node *vp, struct label *vplabel, acl_type_t type) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -105,7 +105,7 @@ ugidfw_vnode_check_deleteextattr(struct ucred *cred, st= ruct vnode *vp, struct label *vplabel, int attrnamespace, const char *name) { =20 - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); } =20 int @@ -114,7 +114,7 @@ ugidfw_vnode_check_exec(struct ucred *cred, struct vnod= e *vp, struct label *execlabel) { =20 - return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC)); + return (ugidfw_check_vp(cred, vp, MBI_READ|MBI_EXEC, imgp)); } =20 int @@ -122,7 +122,7 @@ ugidfw_vnode_check_getacl(struct ucred *cred, struct vn= ode *vp, struct label *vplabel, acl_type_t type) { =20 - return (ugidfw_check_vp(cred, vp, MBI_STAT)); + return (ugidfw_check_vp(cred, vp, MBI_STAT, NULL)); } =20 int @@ -130,7 +130,7 @@ ugidfw_vnode_check_getextattr(struct ucred *cred, struc= t vnode *vp, struct label *vplabel, int attrnamespace, const char *name) { =20 - return (ugidfw_check_vp(cred, vp, MBI_READ)); + return (ugidfw_check_vp(cred, vp, MBI_READ, NULL)); } =20 int @@ -140,10 +140,10 @@ ugidfw_vnode_check_link(struct ucred *cred, struct vn= ode *dvp, { int error; =20 - error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE); + error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE, NULL); if (error) return (error); - error =3D ugidfw_check_vp(cred, vp, MBI_WRITE); + error =3D ugidfw_check_vp(cred, vp, MBI_WRITE, NULL); if (error) return (error); return (0); @@ -154,7 +154,7 @@ ugidfw_vnode_check_listextattr(struct ucred *cred, stru= ct vnode *vp, struct label *vplabel, int attrnamespace) { =20 - return (ugidfw_check_vp(cred, vp, MBI_READ)); + return (ugidfw_check_vp(cred, vp, MBI_READ, NULL)); } =20 int @@ -162,7 +162,7 @@ ugidfw_vnode_check_lookup(struct ucred *cred, struct vn= ode *dvp, struct label *dvplabel, struct componentname *cnp) { =20 - return (ugidfw_check_vp(cred, dvp, MBI_EXEC)); + return (ugidfw_check_vp(cred, dvp, MBI_EXEC, NULL)); } =20 int @@ -170,7 +170,7 @@ ugidfw_vnode_check_open(struct ucred *cred, struct vnod= e *vp, struct label *vplabel, accmode_t accmode) { =20 - return (ugidfw_check_vp(cred, vp, ugidfw_accmode2mbi(accmode))); + return (ugidfw_check_vp(cred, vp, ugidfw_accmode2mbi(accmode), NULL)); } =20 int @@ -178,7 +178,7 @@ ugidfw_vnode_check_readdir(struct ucred *cred, struct v= node *dvp, struct label *dvplabel) { =20 - return (ugidfw_check_vp(cred, dvp, MBI_READ)); + return (ugidfw_check_vp(cred, dvp, MBI_READ, NULL)); } =20 int @@ -186,7 +186,7 @@ ugidfw_vnode_check_readdlink(struct ucred *cred, struct= vnode *vp, struct label *vplabel) { =20 - return (ugidfw_check_vp(cred, vp, MBI_READ)); + return (ugidfw_check_vp(cred, vp, MBI_READ, NULL)); } =20 int @@ -196,10 +196,10 @@ ugidfw_vnode_check_rename_from(struct ucred *cred, st= ruct vnode *dvp, { int error; =20 - error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE); + error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE, NULL); if (error) return (error); - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); } =20 int @@ -209,11 +209,11 @@ ugidfw_vnode_check_rename_to(struct ucred *cred, stru= ct vnode *dvp, { int error; =20 - error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE); + error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE, NULL); if (error) return (error); if (vp !=3D NULL) - error =3D ugidfw_check_vp(cred, vp, MBI_WRITE); + error =3D ugidfw_check_vp(cred, vp, MBI_WRITE, NULL); return (error); } =20 @@ -222,7 +222,7 @@ ugidfw_vnode_check_revoke(struct ucred *cred, struct vn= ode *vp, struct label *vplabel) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -230,7 +230,7 @@ ugidfw_check_setacl_vnode(struct ucred *cred, struct vn= ode *vp, struct label *vplabel, acl_type_t type, struct acl *acl) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -238,7 +238,7 @@ ugidfw_vnode_check_setextattr(struct ucred *cred, struc= t vnode *vp, struct label *vplabel, int attrnamespace, const char *name) { =20 - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); } =20 int @@ -246,7 +246,7 @@ ugidfw_vnode_check_setflags(struct ucred *cred, struct = vnode *vp, struct label *vplabel, u_long flags) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -254,7 +254,7 @@ ugidfw_vnode_check_setmode(struct ucred *cred, struct v= node *vp, struct label *vplabel, mode_t mode) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -262,7 +262,7 @@ ugidfw_vnode_check_setowner(struct ucred *cred, struct = vnode *vp, struct label *vplabel, uid_t uid, gid_t gid) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -270,7 +270,7 @@ ugidfw_vnode_check_setutimes(struct ucred *cred, struct= vnode *vp, struct label *vplabel, struct timespec atime, struct timespec utime) { =20 - return (ugidfw_check_vp(cred, vp, MBI_ADMIN)); + return (ugidfw_check_vp(cred, vp, MBI_ADMIN, NULL)); } =20 int @@ -278,7 +278,7 @@ ugidfw_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *vplabel) { =20 - return (ugidfw_check_vp(active_cred, vp, MBI_STAT)); + return (ugidfw_check_vp(active_cred, vp, MBI_STAT, NULL)); } =20 int @@ -288,8 +288,8 @@ ugidfw_vnode_check_unlink(struct ucred *cred, struct vn= ode *dvp, { int error; =20 - error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE); + error =3D ugidfw_check_vp(cred, dvp, MBI_WRITE, NULL); if (error) return (error); - return (ugidfw_check_vp(cred, vp, MBI_WRITE)); + return (ugidfw_check_vp(cred, vp, MBI_WRITE, NULL)); } diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_ma= chdep.c index 4d55717..e0eba33 100644 --- a/sys/sparc64/sparc64/elf_machdep.c +++ b/sys/sparc64/sparc64/elf_machdep.c @@ -34,6 +34,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> @@ -52,6 +54,10 @@ __FBSDID("$FreeBSD$"); =20 #include <machine/elf.h> =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + #include "linker_if.h" =20 static struct sysentvec elf64_freebsd_sysvec =3D { @@ -87,6 +93,11 @@ static struct sysentvec elf64_freebsd_sysvec =3D { .sv_fetch_syscall_args =3D cpu_fetch_syscall_args, .sv_syscallnames =3D syscallnames, .sv_schedtail =3D NULL, +#ifdef PAX_ASLR + .sv_pax_aslr_init =3D _pax_aslr_init, +#else + .sv_pax_aslr_init =3D NULL, +#endif }; =20 static Elf64_Brandinfo freebsd_brand_info =3D { diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 17cfcc2..15c2c4f 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -78,6 +78,7 @@ struct image_params { unsigned long pagesizes; int pagesizeslen; vm_prot_t stack_prot; + int pax_flags; }; =20 #ifdef _KERNEL diff --git a/sys/sys/jail.h b/sys/sys/jail.h index 59d791c..699b21c 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -184,6 +184,19 @@ struct prison { char pr_hostname[MAXHOSTNAMELEN]; /* (p) jail hostname */ char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */ char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */ + /* Lock only needed for pax_* if pr_pax_set =3D=3D 0 */ + int pr_pax_set; /* (p) PaX settings initialized */ + int pr_pax_aslr_status; /* (p) PaX ASLR enabled */ + int pr_pax_aslr_debug; /* (p) PaX ASLR debug */ + int pr_pax_aslr_mmap_len; /* (p) Number of bits randomized with mmap */ + int pr_pax_aslr_stack_len; /* (p) Number of bits randomized with stack= */ + int pr_pax_aslr_exec_len; /* (p) Number of bits randomized with the ex= ecbase */ + int pr_pax_aslr_compat_status; /* (p) PaX ASLR enabled (compat32) */ + int pr_pax_aslr_compat_mmap_len; /* (p) Number of bits randomized with = mmap (compat32) */ + int pr_pax_aslr_compat_stack_len; /* (p) Number of bits randomized with= stack (compat32) */ + int pr_pax_aslr_compat_exec_len; /* (p) Number of bits randomized with = the execbase (compat32) */ + int pr_pax_log_log; /* (p) XXX */ + int pr_pax_log_ulog; /* (p) XXX */ }; =20 struct prison_racct { diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 3c5258a..aedb52e 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -102,6 +102,7 @@ enum sysinit_sub_id { SI_SUB_WITNESS =3D 0x1A80000, /* witness initialization */ SI_SUB_MTX_POOL_DYNAMIC =3D 0x1AC0000, /* dynamic mutex pool */ SI_SUB_LOCK =3D 0x1B00000, /* various locks */ + SI_SUB_PAX =3D 0x1B50000, /* pax setup */ SI_SUB_EVENTHANDLER =3D 0x1C00000, /* eventhandler init */ SI_SUB_VNET_PRELINK =3D 0x1E00000, /* vnet init before modules */ SI_SUB_KLD =3D 0x2000000, /* KLD and module setup */ diff --git a/sys/sys/pax.h b/sys/sys/pax.h new file mode 100644 index 0000000..a0f2bf6 --- /dev/null +++ b/sys/sys/pax.h @@ -0,0 +1,226 @@ +/*- + * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> + * Copyright (c) 2013-2014, by Oliver Pinter <oliver.pntr at gmail.com> + * Copyright (c) 2014, by Shawn Webb <lattera at gmail.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI= ES + * 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 US= E, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __SYS_PAX_H +#define __SYS_PAX_H + +struct image_params; +struct prison; +struct thread; +struct vnode; +struct vmspace; +struct vm_offset_t; + +/* + * used in sysctl handler + */ +#define PAX_ASLR_DISABLED 0 +#define PAX_ASLR_OPTIN 1 +#define PAX_ASLR_OPTOUT 2 +#define PAX_ASLR_FORCE_ENABLED 3 + +#ifndef PAX_ASLR_DELTA +#define PAX_ASLR_DELTA(delta, lsb, len) \ + (((delta) & ((1UL << (len)) - 1)) << (lsb)) +#endif /* PAX_ASLR_DELTA */ + +#ifdef PAX_ASLR +/* + * generic ASLR values + * + * MMAP | 32 bit | 64 bit | + * +-------+--------+--------+ + * | MIN | 8 bit | 16 bit | + * +-------+--------+--------+ + * | DEF | 8 bit | 21 bit | + * +-------+--------+--------+ + * | MAX | 16 bit | 32 bit | + * +-------+--------+--------+ + * + * STACK | 32 bit | 64 bit | + * +-------+--------+--------+ + * | MIN | 6 bit | 12 bit | + * +-------+--------+--------+ + * | DEF | 6 bit | 16 bit | + * +-------+--------+--------+ + * | MAX | 10 bit | 21 bit | + * +-------+--------+--------+ + * + * EXEC | 32 bit | 64 bit | + * +-------+--------+--------+ + * | MIN | 6 bit | 12 bit | + * +-------+--------+--------+ + * | DEF | 6 bit | 21 bit | + * +-------+--------+--------+ + * | MAX | 10 bit | 21 bit | + * +-------+--------+--------+ + * + */ +#ifndef PAX_ASLR_DELTA_MMAP_LSB +#define PAX_ASLR_DELTA_MMAP_LSB PAGE_SHIFT +#endif /* PAX_ASLR_DELTA_MMAP_LSB */ + +#ifndef PAX_ASLR_DELTA_MMAP_MIN_LEN +#define PAX_ASLR_DELTA_MMAP_MIN_LEN ((sizeof(void *) * NBBY) / 4) +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */ + +#ifndef PAX_ASLR_DELTA_MMAP_MAX_LEN +#define PAX_ASLR_DELTA_MMAP_MAX_LEN ((sizeof(void *) * NBBY) / 2) +#endif /* PAX_ASLR_DELTA_MMAP_MAX_LEN */ + +#ifndef PAX_ASLR_DELTA_STACK_LSB +#define PAX_ASLR_DELTA_STACK_LSB 3 +#endif /* PAX_ASLR_DELTA_STACK_LSB */ + +#ifndef PAX_ASLR_DELTA_STACK_MIN_LEN +#define PAX_ASLR_DELTA_STACK_MIN_LEN ((sizeof(void *) * NBBY) / 5) +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */ + +#ifndef PAX_ASLR_DELTA_STACK_MAX_LEN +#define PAX_ASLR_DELTA_STACK_MAX_LEN ((sizeof(void *) * NBBY) / 3) +#endif /* PAX_ASLR_DELTA_STACK_MAX_LEN */ + +#ifndef PAX_ASLR_DELTA_EXEC_LSB +#define PAX_ASLR_DELTA_EXEC_LSB PAGE_SHIFT +#endif /* PAX_ASLR_DELTA_EXEC_LSB */ + +#ifndef PAX_ASLR_DELTA_EXEC_MIN_LEN +#define PAX_ASLR_DELTA_EXEC_MIN_LEN ((sizeof(void *) * NBBY) / 5) +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */ + +#ifndef PAX_ASLR_DELTA_EXEC_MAX_LEN +#define PAX_ASLR_DELTA_EXEC_MAX_LEN ((sizeof(void *) * NBBY) / 3) +#endif /* PAX_ASLR_DELTA_EXEC_MAX_LEN */ + +/* + * ASLR default values for native host + */ +#ifdef __amd64__ +#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN +#define PAX_ASLR_DELTA_MMAP_DEF_LEN 21 +#endif /* PAX_ASLR_DELTA_MMAP_DEF_LEN */ +#ifndef PAX_ASLR_DELTA_STACK_DEF_LEN +#define PAX_ASLR_DELTA_STACK_DEF_LEN 16 +#endif /* PAX_ASLR_DELTA_STACK_DEF_LEN */ +#ifndef PAX_ASLR_DELTA_EXEC_DEF_LEN +#define PAX_ASLR_DELTA_EXEC_DEF_LEN 21 +#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */ +#else +#ifndef PAX_ASLR_DELTA_MMAP_DEF_LEN +#define PAX_ASLR_DELTA_MMAP_DEF_LEN PAX_ASLR_DELTA_MMAP_MIN_LEN +#endif /* PAX_ASLR_DELTA_MMAP_DEF_LEN */ +#ifndef PAX_ASLR_DELTA_STACK_DEF_LEN +#define PAX_ASLR_DELTA_STACK_DEF_LEN PAX_ASLR_DELTA_STACK_MIN_LEN +#endif /* PAX_ASLR_DELTA_STACK_DEF_LEN */ +#ifndef PAX_ASLR_DELTA_EXEC_DEF_LEN +#define PAX_ASLR_DELTA_EXEC_DEF_LEN PAX_ASLR_DELTA_EXEC_MIN_LEN +#endif /* PAX_ASLR_DELTA_EXEC_DEF_LEN */ +#endif /* __amd64__ */ + +/* + * ASLR values for COMPAT_FREEBSD32 and COMPAT_LINUX + */ +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_LSB +#define PAX_ASLR_COMPAT_DELTA_MMAP_LSB PAGE_SHIFT +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_LSB */ + +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN +#define PAX_ASLR_COMPAT_DELTA_MMAP_MIN_LEN ((sizeof(int) * NBBY) / 4) +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */ + +#ifndef PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN +#define PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN ((sizeof(int) * NBBY) / 2) +#endif /* PAX_ASLR_COMPAT_DELTA_MMAP_MAX_LEN */ + +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_LSB +#define PAX_ASLR_COMPAT_DELTA_STACK_LSB 3 +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_LSB */ + +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN +#define PAX_ASLR_COMPAT_DELTA_STACK_MIN_LEN ((sizeof(int) * NBBY) / 5) +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */ + +#ifndef PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN +#define PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN ((sizeof(int) * NBBY) / 3) +#endif /* PAX_ASLR_COMPAT_DELTA_STACK_MAX_LEN */ + +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN +#define PAX_ASLR_COMPAT_DELTA_EXEC_MIN_LEN ((sizeof(int) * NBBY) / 5) +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */ + +#ifndef PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN +#define PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN ((sizeof(int) * NBBY) / 3) +#endif /* PAX_ASLR_COMPAT_DELTA_EXEC_MAX_LEN */ + +extern int pax_aslr_status; +extern int pax_aslr_debug; + +extern int pax_aslr_mmap_len; +extern int pax_aslr_stack_len; +extern int pax_aslr_exec_len; +#ifdef COMPAT_FREEBSD32 +extern int pax_aslr_compat_status; +extern int pax_aslr_compat_mmap_len; +extern int pax_aslr_compat_stack_len; +extern int pax_aslr_compat_exec_len; +#endif /* COMPAT_FREEBSD32 */ +#endif /* PAX_ASLR */ + +extern int pax_log_log; +extern int pax_log_ulog; + +#define ELF_NOTE_TYPE_PAX_TAG 3 +#define PAX_NOTE_MPROTECT 0x01 +#define PAX_NOTE_NOMPROTECT 0x02 +#define PAX_NOTE_GUARD 0x04 +#define PAX_NOTE_NOGUARD 0x08 +#define PAX_NOTE_ASLR 0x10 +#define PAX_NOTE_NOASLR 0x20 + +#define PAX_LOG_LOG 0 +#define PAX_LOG_ULOG 0 + +void pax_init(void); +void pax_init_prison(struct prison *pr); +bool pax_aslr_active(struct thread *td, struct proc *proc); +void _pax_aslr_init(struct vmspace *vm, struct prison *pr); +void _pax_aslr_init32(struct vmspace *vm, struct prison *pr); +void pax_aslr_init(struct thread *td, struct image_params *imgp); +void pax_aslr_mmap(struct thread *td, vm_offset_t *addr,=20 + vm_offset_t orig_addr, int flags); +void pax_aslr_stack(struct thread *td, uintptr_t *addr); +struct prison *pax_get_prison(struct thread *td, struct proc *proc); +void pax_elf(struct image_params *, uint32_t); + +void pax_log_aslr(struct prison *pr, const char *func, const char *fmt, ..= =2E); +void pax_ulog_aslr(struct prison *pr, const char *func, const char *fmt, .= =2E.); + +#endif /* __SYS_PAX_H */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index fbd064c..558d7bf 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -539,6 +539,7 @@ struct proc { u_int p_stops; /* (c) Stop event bitmask. */ u_int p_stype; /* (c) Stop event type. */ char p_step; /* (c) Process is stopped. */ + u_int p_pax; /* (b) PaX is enabled to this process */ u_char p_pfsflags; /* (c) Procfs flags. */ struct nlminfo *p_nlminfo; /* (?) Only used by/for lockd. */ struct kaioinfo *p_aioinfo; /* (y) ASYNC I/O info. */ diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index c49db41..cfbcdc0 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -77,9 +77,11 @@ struct sysent { /* system call table */ #define SY_THR_INCR 0x8 =20 struct image_params; +struct prison; struct __sigset; struct syscall_args; struct trapframe; +struct vmspace; struct vnode; =20 struct sysentvec { @@ -130,6 +132,7 @@ struct sysentvec { uint32_t sv_timekeep_gen; void *sv_shared_page_obj; void (*sv_schedtail)(struct thread *); + void (*sv_pax_aslr_init)(struct vmspace *vm, struct prison *pr); }; =20 #define SV_ILP32 0x000100 diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index d8ba33f..4ba8106 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -65,6 +65,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); =20 +#include "opt_pax.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -292,6 +294,12 @@ vmspace_alloc(vm_offset_t min, vm_offset_t max, pmap_p= init_t pinit) vm->vm_taddr =3D 0; vm->vm_daddr =3D 0; vm->vm_maxsaddr =3D 0; +#ifdef PAX_ASLR + vm->vm_aslr_delta_mmap =3D 0; + vm->vm_aslr_delta_stack =3D 0; + vm->vm_aslr_delta_exec =3D 0; +#endif + return (vm); } =20 diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 8cced05..e8e9ffe 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -241,6 +241,9 @@ struct vmspace { caddr_t vm_taddr; /* (c) user virtual address of text */ caddr_t vm_daddr; /* (c) user virtual address of data */ caddr_t vm_maxsaddr; /* user VA at max stack growth */ + vm_size_t vm_aslr_delta_mmap; /* mmap() random delta for ASLR */ + vm_size_t vm_aslr_delta_stack; /* stack random delta for ASLR */ + vm_size_t vm_aslr_delta_exec; /* exec base random delta for ASLR */ volatile int vm_refcnt; /* number of references */ /* * Keep the PMAP last, so that CPU-specific variations of that diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index a524839..fd8876e 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); =20 #include "opt_compat.h" #include "opt_hwpmc_hooks.h" +#include "opt_pax.h" =20 #include <sys/param.h> #include <sys/systm.h> @@ -91,6 +92,10 @@ __FBSDID("$FreeBSD$"); #include <sys/pmckern.h> #endif =20 +#ifdef PAX_ASLR +#include <sys/pax.h> +#endif + int old_mlock =3D 0; SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, &old_mlock,= 0, "Do not apply RLIMIT_MEMLOCK on mlockall"); @@ -203,6 +208,9 @@ sys_mmap(td, uap) struct file *fp; struct vnode *vp; vm_offset_t addr; +#ifdef PAX_ASLR + vm_offset_t orig_addr; +#endif vm_size_t size, pageoff; vm_prot_t cap_maxprot, prot, maxprot; void *handle; @@ -213,6 +221,9 @@ sys_mmap(td, uap) cap_rights_t rights; =20 addr =3D (vm_offset_t) uap->addr; +#ifdef PAX_ASLR + orig_addr =3D addr; +#endif size =3D uap->len; prot =3D uap->prot & VM_PROT_ALL; flags =3D uap->flags; @@ -416,6 +427,9 @@ sys_mmap(td, uap) map: td->td_fpop =3D fp; maxprot &=3D cap_maxprot; +#ifdef PAX_ASLR + pax_aslr_mmap(td, &addr, orig_addr, flags); +#endif error =3D vm_mmap(&vms->vm_map, &addr, size, prot, maxprot, flags, handle_type, handle, pos); td->td_fpop =3D NULL; diff --git a/tools/build/options/WITHOUT_PIE b/tools/build/options/WITHOUT_= PIE new file mode 100644 index 0000000..82019ce --- /dev/null +++ b/tools/build/options/WITHOUT_PIE @@ -0,0 +1 @@ +Enable building of Position-Independent Executables (PIEs). diff --git a/usr.sbin/ugidfw/ugidfw.c b/usr.sbin/ugidfw/ugidfw.c index 977922a..515df16 100644 --- a/usr.sbin/ugidfw/ugidfw.c +++ b/usr.sbin/ugidfw/ugidfw.c @@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <ugidfw.h> =20 +#define UGIDFW_BUFSIZ (BUFSIZ*2) + void add_rule(int argc, char *argv[]); void list_rules(void); void remove_rule(int argc, char *argv[]); @@ -71,22 +73,22 @@ usage(void) void add_rule(int argc, char *argv[]) { - char errstr[BUFSIZ], charstr[BUFSIZ]; + char errstr[UGIDFW_BUFSIZ], charstr[UGIDFW_BUFSIZ]; struct mac_bsdextended_rule rule; int error, rulenum; =20 - error =3D bsde_parse_rule(argc, argv, &rule, BUFSIZ, errstr); + error =3D bsde_parse_rule(argc, argv, &rule, UGIDFW_BUFSIZ, errstr); if (error) { warnx("%s", errstr); return; } =20 - error =3D bsde_add_rule(&rulenum, &rule, BUFSIZ, errstr); + error =3D bsde_add_rule(&rulenum, &rule, UGIDFW_BUFSIZ, errstr); if (error) { warnx("%s", errstr); return; } - if (bsde_rule_to_string(&rule, charstr, BUFSIZ) =3D=3D -1) + if (bsde_rule_to_string(&rule, charstr, UGIDFW_BUFSIZ) =3D=3D -1) warnx("Added rule, but unable to print string."); else printf("%d %s\n", rulenum, charstr); @@ -95,25 +97,25 @@ add_rule(int argc, char *argv[]) void list_rules(void) { - char errstr[BUFSIZ], charstr[BUFSIZ]; + char errstr[UGIDFW_BUFSIZ], charstr[UGIDFW_BUFSIZ]; struct mac_bsdextended_rule rule; int error, i, rule_count, rule_slots; =20 - rule_slots =3D bsde_get_rule_slots(BUFSIZ, errstr); + rule_slots =3D bsde_get_rule_slots(UGIDFW_BUFSIZ, errstr); if (rule_slots =3D=3D -1) { warnx("unable to get rule slots; mac_bsdextended.ko " "may not be loaded"); errx(1, "bsde_get_rule_slots: %s", errstr); } =20 - rule_count =3D bsde_get_rule_count(BUFSIZ, errstr); + rule_count =3D bsde_get_rule_count(UGIDFW_BUFSIZ, errstr); if (rule_count =3D=3D -1) errx(1, "bsde_get_rule_count: %s", errstr); =20 printf("%d slots, %d rules\n", rule_slots, rule_count); =20 for (i =3D 0; i < rule_slots; i++) { - error =3D bsde_get_rule(i, &rule, BUFSIZ, errstr); + error =3D bsde_get_rule(i, &rule, UGIDFW_BUFSIZ, errstr); switch (error) { case -2: continue; @@ -124,7 +126,7 @@ list_rules(void) break; } =20 - if (bsde_rule_to_string(&rule, charstr, BUFSIZ) =3D=3D -1) + if (bsde_rule_to_string(&rule, charstr, UGIDFW_BUFSIZ) =3D=3D -1) warnx("unable to translate rule %d to string", i); else printf("%d %s\n", i, charstr); @@ -134,7 +136,7 @@ list_rules(void) void set_rule(int argc, char *argv[]) { - char errstr[BUFSIZ]; + char errstr[UGIDFW_BUFSIZ]; struct mac_bsdextended_rule rule; long value; int error, rulenum; @@ -152,13 +154,13 @@ set_rule(int argc, char *argv[]) =20 rulenum =3D value; =20 - error =3D bsde_parse_rule(argc - 1, argv + 1, &rule, BUFSIZ, errstr); + error =3D bsde_parse_rule(argc - 1, argv + 1, &rule, UGIDFW_BUFSIZ, errst= r); if (error) { warnx("%s", errstr); return; } =20 - error =3D bsde_set_rule(rulenum, &rule, BUFSIZ, errstr); + error =3D bsde_set_rule(rulenum, &rule, UGIDFW_BUFSIZ, errstr); if (error) { warnx("%s", errstr); return; @@ -168,7 +170,7 @@ set_rule(int argc, char *argv[]) void remove_rule(int argc, char *argv[]) { - char errstr[BUFSIZ]; + char errstr[UGIDFW_BUFSIZ]; long value; int error, rulenum; char *endp; @@ -185,7 +187,7 @@ remove_rule(int argc, char *argv[]) =20 rulenum =3D value; =20 - error =3D bsde_delete_rule(rulenum, BUFSIZ, errstr); + error =3D bsde_delete_rule(rulenum, UGIDFW_BUFSIZ, errstr); if (error) warnx("%s", errstr); } --yRA+Bmk8aPhU85Qt-- --S5HS5MvDw4DmbRmb Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBAgAGBQJTptwkAAoJEGqEZY9SRW7uV/UP/jDGqcEHj+MZomqbnyG+Hs4q sArIbDgKsXMrYkx/H1QbiV/+iIRGboiTcmetqkIg1kdkLjhWoQMrOJRVXu75x486 MTVGhFr2KvCRroaJsYN57F/GwwFYG5DVL9CzdPikax1O/JzyHtulpMP1ZKVz/g3r ARcZpSxVO+IRDkK0O69HeJgduWA7dTdiR9rwGd5XY++Xart9JKMj4V0N+Gzx9UXA 7XhaL5y4o6Z+AlpploqAwuxMMQ/3CP2jIpFjJ06UeIvYdC6IzNL9y9r5GYIwmS7b q03kO0R6fEpViIhsVtKqif+hZJQ7vThASSy9UVd3YB4MRtRFVo/yW/WRByVU5Hsh nyObacX4qTYrXaK8xA8zmhOk+QRGMeS+ixs0fjuVhSCRAhDe3+3Tcr81hQf+VV4K 1q4GFRaN62jDXtuoxgkCzpy3bLSaBFuGdS0kzlubB08/MSC0ZVlIE44dHUt9enXs EBNgHCuOBwF1iKu7qaiiNE2vDmBUNnQ+VBlytZH1nXCO46AlbdTJ2atC0JZO7Wk7 9rsWlvSd6aCKFazahxxmqNyaysO11VAgtYipnFaelGvicY6DLK4bb/ynhMl5oFf8 JDsq55cQI+XC/IPDSZkjDK0/gP1t2loAsbuv7y+R+g5bGJB/4rj3yEDf/T2UJ0VJ DHhPn+4cJ6nhZqy64CAR =KU2A -----END PGP SIGNATURE----- --S5HS5MvDw4DmbRmb--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140622133740.GD1824>