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()

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/grow.c
          +++ new/usr/src/uts/common/os/grow.c
↓ open down ↓ 57 lines elided ↑ open up ↑
  58   58  #include <vm/seg.h>
  59   59  #include <vm/seg_dev.h>
  60   60  #include <vm/seg_vn.h>
  61   61  
  62   62  int use_brk_lpg = 1;
  63   63  int use_stk_lpg = 1;
  64   64  
  65   65  static int brk_lpg(caddr_t nva);
  66   66  static int grow_lpg(caddr_t sp);
  67   67  
  68      -int
       68 +intptr_t
  69   69  brk(caddr_t nva)
  70   70  {
  71   71          int error;
  72   72          proc_t *p = curproc;
  73   73  
  74   74          /*
       75 +         * As a special case to aid the implementation of sbrk(3C), if given a
       76 +         * new brk of 0, return the current brk.  We'll hide this in brk(3C).
       77 +         */
       78 +        if (nva == 0)
       79 +                return ((intptr_t)(p->p_brkbase + p->p_brksize));
       80 +
       81 +        /*
  75   82           * Serialize brk operations on an address space.
  76   83           * This also serves as the lock protecting p_brksize
  77   84           * and p_brkpageszc.
  78   85           */
  79   86          as_rangelock(p->p_as);
  80   87          if (use_brk_lpg && (p->p_flag & SAUTOLPG) != 0) {
  81   88                  error = brk_lpg(nva);
  82   89          } else {
  83   90                  error = brk_internal(nva, p->p_brkpageszc);
  84   91          }
↓ open down ↓ 398 lines elided ↑ open up ↑
 483  490                          cmn_err(CE_WARN, "Sorry, no swap space to grow stack "
 484  491                              "for pid %d (%s)", p->p_pid, PTOU(p)->u_comm);
 485  492                  }
 486  493                  return (error);
 487  494          }
 488  495          p->p_stksize = newsize;
 489  496          return (0);
 490  497  }
 491  498  
 492  499  /*
 493      - * Find address for user to map.
 494      - * If MAP_FIXED is not specified, we can pick any address we want, but we will
 495      - * first try the value in *addrp if it is non-NULL.  Thus this is implementing
 496      - * a way to try and get a preferred address.
      500 + * Find address for user to map.  If MAP_FIXED is not specified, we can pick
      501 + * any address we want, but we will first try the value in *addrp if it is
      502 + * non-NULL and _MAP_RANDOMIZE is not set.  Thus this is implementing a way to
      503 + * try and get a preferred address.
 497  504   */
 498  505  int
 499  506  choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
 500  507      int vacalign, uint_t flags)
 501  508  {
 502  509          caddr_t basep = (caddr_t)(uintptr_t)((uintptr_t)*addrp & PAGEMASK);
 503  510          size_t lenp = len;
 504  511  
 505  512          ASSERT(AS_ISCLAIMGAP(as));      /* searches should be serialized */
 506  513          if (flags & MAP_FIXED) {
 507  514                  (void) as_unmap(as, *addrp, len);
 508  515                  return (0);
 509      -        } else if (basep != NULL && ((flags & MAP_ALIGN) == 0) &&
      516 +        } else if (basep != NULL &&
      517 +            ((flags & (MAP_ALIGN | _MAP_RANDOMIZE)) == 0) &&
 510  518              !as_gap(as, len, &basep, &lenp, 0, *addrp)) {
 511  519                  /* User supplied address was available */
 512  520                  *addrp = basep;
 513  521          } else {
 514  522                  /*
 515  523                   * No user supplied address or the address supplied was not
 516  524                   * available.
 517  525                   */
 518  526                  map_addr(addrp, len, off, vacalign, flags);
 519  527          }
↓ open down ↓ 85 lines elided ↑ open up ↑
 605  613          }
 606  614  
 607  615          if ((flags & MAP_TEXT) && !(prot & PROT_EXEC)) {
 608  616                  return (EINVAL);
 609  617          }
 610  618  
 611  619          if ((flags & (MAP_TEXT | MAP_INITDATA)) == (MAP_TEXT | MAP_INITDATA)) {
 612  620                  return (EINVAL);
 613  621          }
 614  622  
      623 +        if ((flags & (MAP_FIXED | _MAP_RANDOMIZE)) == (MAP_FIXED | _MAP_RANDOMIZE)) {
      624 +                return (EINVAL);
      625 +        }
      626 +
      627 +        /* If it's not a fixed allocation and mmap ASLR is enabled, randomize it. */
      628 +        if (((flags & MAP_FIXED) == 0) &&
      629 +            secflag_enabled(curproc, PROC_SEC_ASLR))
      630 +                flags |= _MAP_RANDOMIZE;
      631 +
 615  632  #if defined(__sparc)
 616  633          /*
 617  634           * See if this is an "old mmap call".  If so, remember this
 618  635           * fact and convert the flags value given to mmap to indicate
 619  636           * the specified address in the system call must be used.
 620  637           * _MAP_NEW is turned set by all new uses of mmap.
 621  638           */
 622  639          if ((flags & _MAP_NEW) == 0)
 623  640                  flags |= MAP_FIXED;
 624  641  #endif
 625  642          flags &= ~_MAP_NEW;
 626  643  
 627  644          type = flags & MAP_TYPE;
 628  645          if (type != MAP_PRIVATE && type != MAP_SHARED)
 629  646                  return (EINVAL);
 630  647  
 631  648  
 632  649          if (flags & MAP_ALIGN) {
 633      -
 634  650                  if (flags & MAP_FIXED)
 635  651                          return (EINVAL);
 636  652  
 637  653                  /* alignment needs to be a power of 2 >= page size */
 638  654                  if (((uintptr_t)*addrp < PAGESIZE && (uintptr_t)*addrp != 0) ||
 639  655                      !ISP2((uintptr_t)*addrp))
 640  656                          return (EINVAL);
 641  657          }
 642  658          /*
 643  659           * Check for bad lengths and file position.
↓ open down ↓ 380 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX