Print this page
sync further changes from uts/aslr
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (aslr)
7031 noexec_user_stack should be a secflag
7032 want a means to forbid mappings around NULL.

*** 60,73 **** #include <vm/seg_vn.h> int use_brk_lpg = 1; int use_stk_lpg = 1; static int brk_lpg(caddr_t nva); static int grow_lpg(caddr_t sp); ! int brk(caddr_t nva) { int error; proc_t *p = curproc; --- 60,79 ---- #include <vm/seg_vn.h> int use_brk_lpg = 1; int use_stk_lpg = 1; + /* + * If set, we will not randomize mappings where the 'addr' argument is + * non-NULL and not an alignment. + */ + int aslr_respect_mmap_hint = 0; + static int brk_lpg(caddr_t nva); static int grow_lpg(caddr_t sp); ! intptr_t brk(caddr_t nva) { int error; proc_t *p = curproc;
*** 75,84 **** --- 81,100 ---- * Serialize brk operations on an address space. * This also serves as the lock protecting p_brksize * and p_brkpageszc. */ as_rangelock(p->p_as); + + /* + * As a special case to aid the implementation of sbrk(3C), if given a + * new brk of 0, return the current brk. We'll hide this in brk(3C). + */ + if (nva == 0) { + as_rangeunlock(p->p_as); + return ((intptr_t)(p->p_brkbase + p->p_brksize)); + } + if (use_brk_lpg && (p->p_flag & SAUTOLPG) != 0) { error = brk_lpg(nva); } else { error = brk_internal(nva, p->p_brkpageszc); }
*** 488,501 **** p->p_stksize = newsize; return (0); } /* ! * Find address for user to map. ! * If MAP_FIXED is not specified, we can pick any address we want, but we will ! * first try the value in *addrp if it is non-NULL. Thus this is implementing ! * a way to try and get a preferred address. */ int choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off, int vacalign, uint_t flags) { --- 504,517 ---- p->p_stksize = newsize; return (0); } /* ! * Find address for user to map. If MAP_FIXED is not specified, we can pick ! * any address we want, but we will first try the value in *addrp if it is ! * non-NULL and _MAP_RANDOMIZE is not set. Thus this is implementing a way to ! * try and get a preferred address. */ int choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off, int vacalign, uint_t flags) {
*** 504,514 **** ASSERT(AS_ISCLAIMGAP(as)); /* searches should be serialized */ if (flags & MAP_FIXED) { (void) as_unmap(as, *addrp, len); return (0); ! } else if (basep != NULL && ((flags & MAP_ALIGN) == 0) && !as_gap(as, len, &basep, &lenp, 0, *addrp)) { /* User supplied address was available */ *addrp = basep; } else { /* --- 520,531 ---- ASSERT(AS_ISCLAIMGAP(as)); /* searches should be serialized */ if (flags & MAP_FIXED) { (void) as_unmap(as, *addrp, len); return (0); ! } else if (basep != NULL && ! ((flags & (MAP_ALIGN | _MAP_RANDOMIZE)) == 0) && !as_gap(as, len, &basep, &lenp, 0, *addrp)) { /* User supplied address was available */ *addrp = basep; } else { /*
*** 585,594 **** --- 602,614 ---- vn_a.lgrp_mem_policy_flags = 0; return (as_map(as, *addrp, len, segvn_create, &vn_a)); } + #define RANDOMIZABLE_MAPPING(addr, flags) (((flags & MAP_FIXED) == 0) && \ + !(((flags & MAP_ALIGN) == 0) && (addr != 0) && aslr_respect_mmap_hint)) + static int smmap_common(caddr_t *addrp, size_t len, int prot, int flags, struct file *fp, offset_t pos) { struct vnode *vp;
*** 610,619 **** --- 630,652 ---- if ((flags & (MAP_TEXT | MAP_INITDATA)) == (MAP_TEXT | MAP_INITDATA)) { return (EINVAL); } + if ((flags & (MAP_FIXED | _MAP_RANDOMIZE)) == + (MAP_FIXED | _MAP_RANDOMIZE)) { + return (EINVAL); + } + + /* + * If it's not a fixed allocation and mmap ASLR is enabled, randomize + * it. + */ + if (RANDOMIZABLE_MAPPING(*addrp, flags) && + secflag_enabled(curproc, PROC_SEC_ASLR)) + flags |= _MAP_RANDOMIZE; + #if defined(__sparc) /* * See if this is an "old mmap call". If so, remember this * fact and convert the flags value given to mmap to indicate * the specified address in the system call must be used.
*** 628,638 **** if (type != MAP_PRIVATE && type != MAP_SHARED) return (EINVAL); if (flags & MAP_ALIGN) { - if (flags & MAP_FIXED) return (EINVAL); /* alignment needs to be a power of 2 >= page size */ if (((uintptr_t)*addrp < PAGESIZE && (uintptr_t)*addrp != 0) || --- 661,670 ----