Module Name: src Committed By: christos Date: Sun May 8 01:28:09 UTC 2016
Modified Files: src/sys/kern: exec_elf.c kern_exec.c kern_pax.c src/sys/sys: pax.h Log Message: Move all the randomization inside kern_pax.c so we can control it directly. Add debugging flags to be able to set the random number externally. To generate a diff of this commit: cvs rdiff -u -r1.82 -r1.83 src/sys/kern/exec_elf.c cvs rdiff -u -r1.426 -r1.427 src/sys/kern/kern_exec.c cvs rdiff -u -r1.41 -r1.42 src/sys/kern/kern_pax.c cvs rdiff -u -r1.19 -r1.20 src/sys/sys/pax.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/exec_elf.c diff -u src/sys/kern/exec_elf.c:1.82 src/sys/kern/exec_elf.c:1.83 --- src/sys/kern/exec_elf.c:1.82 Sat Mar 19 14:56:37 2016 +++ src/sys/kern/exec_elf.c Sat May 7 21:28:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: exec_elf.c,v 1.82 2016/03/19 18:56:37 christos Exp $ */ +/* $NetBSD: exec_elf.c,v 1.83 2016/05/08 01:28:09 christos Exp $ */ /*- * Copyright (c) 1994, 2000, 2005, 2015 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.82 2016/03/19 18:56:37 christos Exp $"); +__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.83 2016/05/08 01:28:09 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_pax.h" @@ -76,7 +76,6 @@ __KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v #include <sys/stat.h> #include <sys/kauth.h> #include <sys/bitops.h> -#include <sys/cprng.h> #include <sys/cpu.h> #include <machine/reg.h> @@ -125,32 +124,10 @@ elf_placedynexec(struct exec_package *ep if (ph[i].p_type == PT_LOAD && ph[i].p_align > align) align = ph[i].p_align; -#ifdef PAX_ASLR - if (pax_aslr_epp_active(epp)) { - size_t pax_align, l2, delta; - uint32_t r; - - pax_align = align; - - r = cprng_fast32(); - - if (pax_align == 0) - pax_align = PGSHIFT; - l2 = ilog2(pax_align); - delta = PAX_ASLR_DELTA(r, l2, PAX_ASLR_DELTA_EXEC_LEN); - offset = ELF_TRUNC(delta, pax_align) + PAGE_SIZE; -#ifdef PAX_ASLR_DEBUG - if (pax_aslr_debug) { - uprintf("%s: r=%#x l2=%#zx pax_align=%#zx delta=%#zx\n", - __func__, r, l2, pax_align, delta); - uprintf("%s: pax offset=%#jx entry=%#jx\n", __func__, - (uintmax_t)offset, (uintmax_t)eh->e_entry); - } -#endif /* PAX_ASLR_DEBUG */ - } else -#endif /* PAX_ASLR */ - offset = MAX(align, PAGE_SIZE); - +#ifndef PAX_ASLR +# define pax_aslr_exec_offset(epp, align) MAX(align, PAGE_SIZE) +#endif + offset = (Elf_Addr)pax_aslr_exec_offset(epp, align); offset += epp->ep_vm_minaddr; for (i = 0; i < eh->e_phnum; i++) Index: src/sys/kern/kern_exec.c diff -u src/sys/kern/kern_exec.c:1.426 src/sys/kern/kern_exec.c:1.427 --- src/sys/kern/kern_exec.c:1.426 Mon Apr 4 19:07:06 2016 +++ src/sys/kern/kern_exec.c Sat May 7 21:28:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.426 2016/04/04 23:07:06 christos Exp $ */ +/* $NetBSD: kern_exec.c,v 1.427 2016/05/08 01:28:09 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.426 2016/04/04 23:07:06 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.427 2016/05/08 01:28:09 christos Exp $"); #include "opt_exec.h" #include "opt_execfmt.h" @@ -759,7 +759,7 @@ execve_loadvm(struct lwp *l, const char */ #ifdef PAX_ASLR -#define ASLR_GAP(epp) (pax_aslr_epp_active(epp) ? (cprng_fast32() % PAGE_SIZE) : 0) +#define ASLR_GAP(epp) pax_aslr_stack_gap(epp) #else #define ASLR_GAP(epp) 0 #endif Index: src/sys/kern/kern_pax.c diff -u src/sys/kern/kern_pax.c:1.41 src/sys/kern/kern_pax.c:1.42 --- src/sys/kern/kern_pax.c:1.41 Sun Apr 10 11:41:05 2016 +++ src/sys/kern/kern_pax.c Sat May 7 21:28:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_pax.c,v 1.41 2016/04/10 15:41:05 christos Exp $ */ +/* $NetBSD: kern_pax.c,v 1.42 2016/05/08 01:28:09 christos Exp $ */ /* * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.41 2016/04/10 15:41:05 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.42 2016/05/08 01:28:09 christos Exp $"); #include "opt_pax.h" @@ -73,6 +73,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v #include <sys/syslog.h> #include <sys/vnode.h> #include <sys/queue.h> +#include <sys/bitops.h> #include <sys/kauth.h> #include <sys/cprng.h> @@ -136,8 +137,12 @@ int pax_mprotect_debug; int pax_aslr_debug; /* flag set means disable */ int pax_aslr_flags; -#define PAX_ASLR_STACK 1 -#define PAX_ASLR_MMAP 2 +uint32_t pax_aslr_rand; +#define PAX_ASLR_STACK 0x01 +#define PAX_ASLR_STACK_GAP 0x02 +#define PAX_ASLR_MMAP 0x04 +#define PAX_ASLR_EXEC_OFFSET 0x08 +#define PAX_ASLR_FIXED 0x10 #endif static int pax_segvguard_enabled = 1; @@ -283,6 +288,12 @@ SYSCTL_SETUP(sysctl_security_pax_setup, SYSCTL_DESCR("Disable/Enable select ASLR features."), NULL, 0, &pax_aslr_flags, 0, CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "rand", + SYSCTL_DESCR("Use the given fixed random value"), + NULL, 0, &pax_aslr_rand, 0, + CTL_CREATE, CTL_EOL); #endif sysctl_createv(clog, 0, &rnode, NULL, CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, @@ -459,7 +470,12 @@ pax_aslr_init_vm(struct lwp *l, struct v uint32_t len = (ep->ep_flags & EXEC_32) ? PAX_ASLR_DELTA_MMAP_LEN32 : PAX_ASLR_DELTA_MMAP_LEN; - vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(cprng_fast32(), + uint32_t rand = cprng_fast32(); +#ifdef PAX_ASLR_DEBUG + if (pax_aslr_flags & PAX_ASLR_FIXED) + rand = pax_aslr_rand; +#endif + vm->vm_aslr_delta_mmap = PAX_ASLR_DELTA(rand, PAX_ASLR_DELTA_MMAP_LSB, len); PAX_DPRINTF("delta_mmap=%#jx/%u", vm->vm_aslr_delta_mmap, len); @@ -496,6 +512,40 @@ pax_aslr_mmap(struct lwp *l, vaddr_t *ad } } +#define PAX_TRUNC(a, b) ((a) & ~((b) - 1)) +vaddr_t +pax_aslr_exec_offset(struct exec_package *epp, vaddr_t align) +{ + size_t pax_align, l2, delta; + uint32_t rand; + vaddr_t offset; + + if (!pax_aslr_epp_active(epp)) + goto out; + +#ifdef PAX_ASLR_DEBUG + if (pax_aslr_flags & PAX_ASLR_EXEC_OFFSET) + goto out; +#endif + + pax_align = align == 0 ? PGSHIFT : align; + l2 = ilog2(pax_align); + + rand = cprng_fast32(); +#ifdef PAX_ASLR_DEBUG + if (pax_aslr_flags & PAX_ASLR_FIXED) + rand = pax_aslr_rand; +#endif + delta = PAX_ASLR_DELTA(rand, l2, PAX_ASLR_DELTA_EXEC_LEN); + offset = PAX_TRUNC(delta, pax_align) + PAGE_SIZE; + + PAX_DPRINTF("rand=%#x l2=%#zx pax_align=%#zx delta=%#zx offset=%#jx", + rand, l2, pax_align, delta, (uintmax_t)offset); + return offset; +out: + return MAX(align, PAGE_SIZE); +} + void pax_aslr_stack(struct exec_package *epp, u_long *max_stack_size) { @@ -508,8 +558,12 @@ pax_aslr_stack(struct exec_package *epp, uint32_t len = (epp->ep_flags & EXEC_32) ? PAX_ASLR_DELTA_STACK_LEN32 : PAX_ASLR_DELTA_STACK_LEN; - u_long d = PAX_ASLR_DELTA(cprng_fast32(), PAX_ASLR_DELTA_STACK_LSB, - len); + uint32_t rand = cprng_fast32(); +#ifdef PAX_ASLR_DEBUG + if (pax_aslr_flags & PAX_ASLR_FIXED) + rand = pax_aslr_rand; +#endif + u_long d = PAX_ASLR_DELTA(rand, PAX_ASLR_DELTA_STACK_LSB, len); u_long newminsaddr = (u_long)STACK_ALLOC(epp->ep_minsaddr, d); PAX_DPRINTF("old minsaddr=%#jx delta=%#lx new minsaddr=%#lx", (uintmax_t)epp->ep_minsaddr, d, newminsaddr); @@ -518,6 +572,27 @@ pax_aslr_stack(struct exec_package *epp, if (epp->ep_ssize > *max_stack_size) epp->ep_ssize = *max_stack_size; } + +uint32_t +pax_aslr_stack_gap(struct exec_package *epp) +{ + if (!pax_aslr_epp_active(epp)) + return 0; + +#ifdef PAX_ASLR_DEBUG + if (pax_aslr_flags & PAX_ASLR_STACK_GAP) + return 0; +#endif + + uint32_t rand = cprng_fast32(); +#ifdef PAX_ASLR_DEBUG + if (pax_aslr_flags & PAX_ASLR_FIXED) + rand = pax_aslr_rand; +#endif + rand %= PAGE_SIZE; + PAX_DPRINTF("stack gap=%#x\n", rand); + return rand; +} #endif /* PAX_ASLR */ #ifdef PAX_SEGVGUARD Index: src/sys/sys/pax.h diff -u src/sys/sys/pax.h:1.19 src/sys/sys/pax.h:1.20 --- src/sys/sys/pax.h:1.19 Wed Apr 6 23:31:12 2016 +++ src/sys/sys/pax.h Sat May 7 21:28:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: pax.h,v 1.19 2016/04/07 03:31:12 christos Exp $ */ +/* $NetBSD: pax.h,v 1.20 2016/05/08 01:28:09 christos Exp $ */ /*- * Copyright (c) 2006 Elad Efrat <e...@netbsd.org> @@ -79,6 +79,8 @@ bool pax_aslr_epp_active(struct exec_pac bool pax_aslr_active(struct lwp *); void pax_aslr_init_vm(struct lwp *, struct vmspace *, struct exec_package *); void pax_aslr_stack(struct exec_package *, u_long *); +uint32_t pax_aslr_stack_gap(struct exec_package *); +vaddr_t pax_aslr_exec_offset(struct exec_package *, vaddr_t); void pax_aslr_mmap(struct lwp *, vaddr_t *, vaddr_t, int); #endif /* !_SYS_PAX_H_ */