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.

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/grow.c
          +++ new/usr/src/uts/common/os/grow.c
↓ open down ↓ 54 lines elided ↑ open up ↑
  55   55  
  56   56  #include <vm/hat.h>
  57   57  #include <vm/as.h>
  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 +/*
       66 + * If set, we will not randomize mappings where the 'addr' argument is
       67 + * non-NULL and not an alignment.
       68 + */
       69 +int aslr_respect_mmap_hint = 0;
       70 +
  65   71  static int brk_lpg(caddr_t nva);
  66   72  static int grow_lpg(caddr_t sp);
  67   73  
  68      -int
       74 +intptr_t
  69   75  brk(caddr_t nva)
  70   76  {
  71   77          int error;
  72   78          proc_t *p = curproc;
  73   79  
  74   80          /*
  75   81           * Serialize brk operations on an address space.
  76   82           * This also serves as the lock protecting p_brksize
  77   83           * and p_brkpageszc.
  78   84           */
  79   85          as_rangelock(p->p_as);
       86 +
       87 +        /*
       88 +         * As a special case to aid the implementation of sbrk(3C), if given a
       89 +         * new brk of 0, return the current brk.  We'll hide this in brk(3C).
       90 +         */
       91 +        if (nva == 0) {
       92 +                as_rangeunlock(p->p_as);
       93 +                return ((intptr_t)(p->p_brkbase + p->p_brksize));
       94 +        }
       95 +
  80   96          if (use_brk_lpg && (p->p_flag & SAUTOLPG) != 0) {
  81   97                  error = brk_lpg(nva);
  82   98          } else {
  83   99                  error = brk_internal(nva, p->p_brkpageszc);
  84  100          }
  85  101          as_rangeunlock(p->p_as);
  86  102          return ((error != 0 ? set_errno(error) : 0));
  87  103  }
  88  104  
  89  105  /*
↓ open down ↓ 393 lines elided ↑ open up ↑
 483  499                          cmn_err(CE_WARN, "Sorry, no swap space to grow stack "
 484  500                              "for pid %d (%s)", p->p_pid, PTOU(p)->u_comm);
 485  501                  }
 486  502                  return (error);
 487  503          }
 488  504          p->p_stksize = newsize;
 489  505          return (0);
 490  506  }
 491  507  
 492  508  /*
 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.
      509 + * Find address for user to map.  If MAP_FIXED is not specified, we can pick
      510 + * any address we want, but we will first try the value in *addrp if it is
      511 + * non-NULL and _MAP_RANDOMIZE is not set.  Thus this is implementing a way to
      512 + * try and get a preferred address.
 497  513   */
 498  514  int
 499  515  choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
 500  516      int vacalign, uint_t flags)
 501  517  {
 502  518          caddr_t basep = (caddr_t)(uintptr_t)((uintptr_t)*addrp & PAGEMASK);
 503  519          size_t lenp = len;
 504  520  
 505  521          ASSERT(AS_ISCLAIMGAP(as));      /* searches should be serialized */
 506  522          if (flags & MAP_FIXED) {
 507  523                  (void) as_unmap(as, *addrp, len);
 508  524                  return (0);
 509      -        } else if (basep != NULL && ((flags & MAP_ALIGN) == 0) &&
      525 +        } else if (basep != NULL &&
      526 +            ((flags & (MAP_ALIGN | _MAP_RANDOMIZE)) == 0) &&
 510  527              !as_gap(as, len, &basep, &lenp, 0, *addrp)) {
 511  528                  /* User supplied address was available */
 512  529                  *addrp = basep;
 513  530          } else {
 514  531                  /*
 515  532                   * No user supplied address or the address supplied was not
 516  533                   * available.
 517  534                   */
 518  535                  map_addr(addrp, len, off, vacalign, flags);
 519  536          }
↓ open down ↓ 60 lines elided ↑ open up ↑
 580  597          vn_a.maxprot = PROT_ALL;
 581  598          vn_a.flags = flags & ~MAP_TYPE;
 582  599          vn_a.cred = CRED();
 583  600          vn_a.amp = NULL;
 584  601          vn_a.szc = 0;
 585  602          vn_a.lgrp_mem_policy_flags = 0;
 586  603  
 587  604          return (as_map(as, *addrp, len, segvn_create, &vn_a));
 588  605  }
 589  606  
      607 +#define RANDOMIZABLE_MAPPING(addr, flags) (((flags & MAP_FIXED) == 0) && \
      608 +        !(((flags & MAP_ALIGN) == 0) && (addr != 0) && aslr_respect_mmap_hint))
      609 +
 590  610  static int
 591  611  smmap_common(caddr_t *addrp, size_t len,
 592  612      int prot, int flags, struct file *fp, offset_t pos)
 593  613  {
 594  614          struct vnode *vp;
 595  615          struct as *as = curproc->p_as;
 596  616          uint_t uprot, maxprot, type;
 597  617          int error;
 598  618          int in_crit = 0;
 599  619  
↓ open down ↓ 5 lines elided ↑ open up ↑
 605  625          }
 606  626  
 607  627          if ((flags & MAP_TEXT) && !(prot & PROT_EXEC)) {
 608  628                  return (EINVAL);
 609  629          }
 610  630  
 611  631          if ((flags & (MAP_TEXT | MAP_INITDATA)) == (MAP_TEXT | MAP_INITDATA)) {
 612  632                  return (EINVAL);
 613  633          }
 614  634  
      635 +        if ((flags & (MAP_FIXED | _MAP_RANDOMIZE)) ==
      636 +            (MAP_FIXED | _MAP_RANDOMIZE)) {
      637 +                return (EINVAL);
      638 +        }
      639 +
      640 +        /*
      641 +         * If it's not a fixed allocation and mmap ASLR is enabled, randomize
      642 +         * it.
      643 +         */
      644 +        if (RANDOMIZABLE_MAPPING(*addrp, flags) &&
      645 +            secflag_enabled(curproc, PROC_SEC_ASLR))
      646 +                flags |= _MAP_RANDOMIZE;
      647 +
 615  648  #if defined(__sparc)
 616  649          /*
 617  650           * See if this is an "old mmap call".  If so, remember this
 618  651           * fact and convert the flags value given to mmap to indicate
 619  652           * the specified address in the system call must be used.
 620  653           * _MAP_NEW is turned set by all new uses of mmap.
 621  654           */
 622  655          if ((flags & _MAP_NEW) == 0)
 623  656                  flags |= MAP_FIXED;
 624  657  #endif
 625  658          flags &= ~_MAP_NEW;
 626  659  
 627  660          type = flags & MAP_TYPE;
 628  661          if (type != MAP_PRIVATE && type != MAP_SHARED)
 629  662                  return (EINVAL);
 630  663  
 631  664  
 632  665          if (flags & MAP_ALIGN) {
 633      -
 634  666                  if (flags & MAP_FIXED)
 635  667                          return (EINVAL);
 636  668  
 637  669                  /* alignment needs to be a power of 2 >= page size */
 638  670                  if (((uintptr_t)*addrp < PAGESIZE && (uintptr_t)*addrp != 0) ||
 639  671                      !ISP2((uintptr_t)*addrp))
 640  672                          return (EINVAL);
 641  673          }
 642  674          /*
 643  675           * Check for bad lengths and file position.
↓ open down ↓ 380 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX