Print this page
uts: Allow for address space randomisation.
Randomise the base addresses of shared objects, non-fixed mappings, the
stack and the heap. Introduce a service, svc:/system/process-security,
and a tool psecflags(1) to control and observe it
libc: adjust brk(0) to return the existing break, and use it to initialize sbrk()
*** 63,79 ****
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;
/*
* Serialize brk operations on an address space.
* This also serves as the lock protecting p_brksize
* and p_brkpageszc.
*/
as_rangelock(p->p_as);
--- 63,86 ----
int use_stk_lpg = 1;
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;
/*
+ * 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)
+ return ((intptr_t)(p->p_brkbase + p->p_brksize));
+
+ /*
* Serialize brk operations on an address space.
* This also serves as the lock protecting p_brksize
* and p_brkpageszc.
*/
as_rangelock(p->p_as);
*** 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)
{
--- 495,508 ----
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 {
/*
--- 511,522 ----
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 {
/*
*** 610,619 ****
--- 618,636 ----
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 (((flags & MAP_FIXED) == 0) &&
+ 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) ||
--- 645,654 ----