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


  35  * UNIX machine dependent virtual memory support.
  36  */
  37 
  38 #include <sys/vm.h>
  39 #include <sys/exec.h>
  40 #include <sys/cmn_err.h>
  41 #include <sys/cpu_module.h>
  42 #include <sys/cpu.h>
  43 #include <sys/elf_SPARC.h>
  44 #include <sys/archsystm.h>
  45 #include <vm/hat_sfmmu.h>
  46 #include <sys/memnode.h>
  47 #include <sys/mem_cage.h>
  48 #include <vm/vm_dep.h>
  49 #include <sys/error.h>
  50 #include <sys/machsystm.h>
  51 #include <vm/seg_kmem.h>
  52 #include <sys/stack.h>
  53 #include <sys/atomic.h>
  54 #include <sys/promif.h>

  55 
  56 uint_t page_colors = 0;
  57 uint_t page_colors_mask = 0;
  58 uint_t page_coloring_shift = 0;
  59 int consistent_coloring;
  60 int update_proc_pgcolorbase_after_fork = 1;
  61 
  62 uint_t mmu_page_sizes = MMU_PAGE_SIZES;
  63 uint_t max_mmu_page_sizes = MMU_PAGE_SIZES;
  64 uint_t mmu_hashcnt = MAX_HASHCNT;
  65 uint_t max_mmu_hashcnt = MAX_HASHCNT;
  66 size_t mmu_ism_pagesize = DEFAULT_ISM_PAGESIZE;
  67 
  68 /*
  69  * A bitmask of the page sizes supported by hardware based upon szc.
  70  * The base pagesize (p_szc == 0) must always be supported by the hardware.
  71  */
  72 int mmu_exported_pagesize_mask;
  73 uint_t mmu_exported_page_sizes;
  74 


 151 static  kmutex_t        contig_mem_lock;
 152 #define CONTIG_MEM_ARENA_QUANTUM        64
 153 #define CONTIG_MEM_SLAB_ARENA_QUANTUM   MMU_PAGESIZE64K
 154 
 155 /* contig_mem_arena import slab sizes, in decreasing size order */
 156 static size_t contig_mem_import_sizes[] = {
 157         MMU_PAGESIZE4M,
 158         MMU_PAGESIZE512K,
 159         MMU_PAGESIZE64K
 160 };
 161 #define NUM_IMPORT_SIZES        \
 162         (sizeof (contig_mem_import_sizes) / sizeof (size_t))
 163 static size_t contig_mem_import_size_max        = MMU_PAGESIZE4M;
 164 size_t contig_mem_slab_size                     = MMU_PAGESIZE4M;
 165 
 166 /* Boot-time allocated buffer to pre-populate the contig_mem_arena */
 167 static size_t contig_mem_prealloc_size;
 168 static void *contig_mem_prealloc_buf;
 169 
 170 /*







 171  * map_addr_proc() is the routine called when the system is to
 172  * choose an address for the user.  We will pick an address
 173  * range which is just below the current stack limit.  The
 174  * algorithm used for cache consistency on machines with virtual
 175  * address caches is such that offset 0 in the vnode is always
 176  * on a shm_alignment'ed aligned address.  Unfortunately, this
 177  * means that vnodes which are demand paged will not be mapped
 178  * cache consistently with the executable images.  When the
 179  * cache alignment for a given object is inconsistent, the
 180  * lower level code must manage the translations so that this
 181  * is not seen here (at the cost of efficiency, of course).
 182  *
 183  * Every mapping will have a redzone of a single page on either side of
 184  * the request. This is done to leave one page unmapped between segments.
 185  * This is not required, but it's useful for the user because if their
 186  * program strays across a segment boundary, it will catch a fault
 187  * immediately making debugging a little easier.  Currently the redzone
 188  * is mandatory.
 189  *
 190  * addrp is a value/result parameter.


 303 
 304                 /*
 305                  * addr is the highest possible address to use since we have
 306                  * a PAGESIZE redzone at the beginning and end.
 307                  */
 308                 addr = base + slen - (PAGESIZE + len);
 309                 as_addr = addr;
 310                 /*
 311                  * Round address DOWN to the alignment amount and
 312                  * add the offset in.
 313                  * If addr is greater than as_addr, len would not be large
 314                  * enough to include the redzone, so we must adjust down
 315                  * by the alignment amount.
 316                  */
 317                 addr = (caddr_t)((uintptr_t)addr & (~(align_amount - 1l)));
 318                 addr += (long)off;
 319                 if (addr > as_addr) {
 320                         addr -= align_amount;
 321                 }
 322 

















 323                 ASSERT(addr > base);
 324                 ASSERT(addr + len < base + slen);
 325                 ASSERT(((uintptr_t)addr & (align_amount - 1l)) ==
 326                     ((uintptr_t)(off)));
 327                 *addrp = addr;
 328 
 329         } else {
 330                 *addrp = NULL;  /* no more virtual space */
 331         }
 332 }
 333 
 334 /*
 335  * Platform-dependent page scrub call.
 336  * We call hypervisor to scrub the page.
 337  */
 338 void
 339 pagescrub(page_t *pp, uint_t off, uint_t len)
 340 {
 341         uint64_t pa, length;
 342 


 758                     chunkp += contig_mem_import_size_max) {
 759 
 760                         if (prom_alloc(chunkp, contig_mem_import_size_max,
 761                             MMU_PAGESIZE4M) != chunkp) {
 762                                 break;
 763                         }
 764                 }
 765                 contig_mem_prealloc_size = chunkp - alloc_base;
 766                 ASSERT(contig_mem_prealloc_size != 0);
 767         }
 768 
 769         if (contig_mem_prealloc_size != 0) {
 770                 contig_mem_prealloc_buf = alloc_base;
 771         } else {
 772                 contig_mem_prealloc_buf = NULL;
 773         }
 774         alloc_base += contig_mem_prealloc_size;
 775 
 776         return (alloc_base);
 777 }
 778 
 779 static uint_t sp_color_stride = 16;
 780 static uint_t sp_color_mask = 0x1f;
 781 static uint_t sp_current_color = (uint_t)-1;
 782 
 783 size_t
 784 exec_get_spslew(void)
 785 {
 786         uint_t spcolor = atomic_inc_32_nv(&sp_current_color);
 787         return ((size_t)((spcolor & sp_color_mask) * SA(sp_color_stride)));
 788 }


  35  * UNIX machine dependent virtual memory support.
  36  */
  37 
  38 #include <sys/vm.h>
  39 #include <sys/exec.h>
  40 #include <sys/cmn_err.h>
  41 #include <sys/cpu_module.h>
  42 #include <sys/cpu.h>
  43 #include <sys/elf_SPARC.h>
  44 #include <sys/archsystm.h>
  45 #include <vm/hat_sfmmu.h>
  46 #include <sys/memnode.h>
  47 #include <sys/mem_cage.h>
  48 #include <vm/vm_dep.h>
  49 #include <sys/error.h>
  50 #include <sys/machsystm.h>
  51 #include <vm/seg_kmem.h>
  52 #include <sys/stack.h>
  53 #include <sys/atomic.h>
  54 #include <sys/promif.h>
  55 #include <sys/random.h>
  56 
  57 uint_t page_colors = 0;
  58 uint_t page_colors_mask = 0;
  59 uint_t page_coloring_shift = 0;
  60 int consistent_coloring;
  61 int update_proc_pgcolorbase_after_fork = 1;
  62 
  63 uint_t mmu_page_sizes = MMU_PAGE_SIZES;
  64 uint_t max_mmu_page_sizes = MMU_PAGE_SIZES;
  65 uint_t mmu_hashcnt = MAX_HASHCNT;
  66 uint_t max_mmu_hashcnt = MAX_HASHCNT;
  67 size_t mmu_ism_pagesize = DEFAULT_ISM_PAGESIZE;
  68 
  69 /*
  70  * A bitmask of the page sizes supported by hardware based upon szc.
  71  * The base pagesize (p_szc == 0) must always be supported by the hardware.
  72  */
  73 int mmu_exported_pagesize_mask;
  74 uint_t mmu_exported_page_sizes;
  75 


 152 static  kmutex_t        contig_mem_lock;
 153 #define CONTIG_MEM_ARENA_QUANTUM        64
 154 #define CONTIG_MEM_SLAB_ARENA_QUANTUM   MMU_PAGESIZE64K
 155 
 156 /* contig_mem_arena import slab sizes, in decreasing size order */
 157 static size_t contig_mem_import_sizes[] = {
 158         MMU_PAGESIZE4M,
 159         MMU_PAGESIZE512K,
 160         MMU_PAGESIZE64K
 161 };
 162 #define NUM_IMPORT_SIZES        \
 163         (sizeof (contig_mem_import_sizes) / sizeof (size_t))
 164 static size_t contig_mem_import_size_max        = MMU_PAGESIZE4M;
 165 size_t contig_mem_slab_size                     = MMU_PAGESIZE4M;
 166 
 167 /* Boot-time allocated buffer to pre-populate the contig_mem_arena */
 168 static size_t contig_mem_prealloc_size;
 169 static void *contig_mem_prealloc_buf;
 170 
 171 /*
 172  * The maximum amount a randomized mapping will be slewed.  We should perhaps
 173  * arrange things so these tunables can be separate for mmap, mmapobj, and
 174  * ld.so
 175  */
 176 volatile size_t aslr_max_map_skew = 256 * 1024 * 1024; /* 256MB */
 177 
 178 /*
 179  * map_addr_proc() is the routine called when the system is to
 180  * choose an address for the user.  We will pick an address
 181  * range which is just below the current stack limit.  The
 182  * algorithm used for cache consistency on machines with virtual
 183  * address caches is such that offset 0 in the vnode is always
 184  * on a shm_alignment'ed aligned address.  Unfortunately, this
 185  * means that vnodes which are demand paged will not be mapped
 186  * cache consistently with the executable images.  When the
 187  * cache alignment for a given object is inconsistent, the
 188  * lower level code must manage the translations so that this
 189  * is not seen here (at the cost of efficiency, of course).
 190  *
 191  * Every mapping will have a redzone of a single page on either side of
 192  * the request. This is done to leave one page unmapped between segments.
 193  * This is not required, but it's useful for the user because if their
 194  * program strays across a segment boundary, it will catch a fault
 195  * immediately making debugging a little easier.  Currently the redzone
 196  * is mandatory.
 197  *
 198  * addrp is a value/result parameter.


 311 
 312                 /*
 313                  * addr is the highest possible address to use since we have
 314                  * a PAGESIZE redzone at the beginning and end.
 315                  */
 316                 addr = base + slen - (PAGESIZE + len);
 317                 as_addr = addr;
 318                 /*
 319                  * Round address DOWN to the alignment amount and
 320                  * add the offset in.
 321                  * If addr is greater than as_addr, len would not be large
 322                  * enough to include the redzone, so we must adjust down
 323                  * by the alignment amount.
 324                  */
 325                 addr = (caddr_t)((uintptr_t)addr & (~(align_amount - 1l)));
 326                 addr += (long)off;
 327                 if (addr > as_addr) {
 328                         addr -= align_amount;
 329                 }
 330 
 331                 /*
 332                  * If randomization is requested, slew the allocation
 333                  * backwards, within the same gap, by a random amount.
 334                  *
 335                  * XXX: This will fall over in processes like Java, which
 336                  * commonly have a great many small mappings.
 337                  */
 338                 if (flags & _MAP_RANDOMIZE) {
 339                         uint32_t slew;
 340 
 341                         (void) random_get_pseudo_bytes((uint8_t *)&slew,
 342                             sizeof (slew));
 343 
 344                         slew = slew % MIN(aslr_max_map_skew, (addr - base));
 345                         addr -= P2ALIGN(slew, align_amount);
 346                 }
 347 
 348                 ASSERT(addr > base);
 349                 ASSERT(addr + len < base + slen);
 350                 ASSERT(((uintptr_t)addr & (align_amount - 1l)) ==
 351                     ((uintptr_t)(off)));
 352                 *addrp = addr;
 353 
 354         } else {
 355                 *addrp = NULL;  /* no more virtual space */
 356         }
 357 }
 358 
 359 /*
 360  * Platform-dependent page scrub call.
 361  * We call hypervisor to scrub the page.
 362  */
 363 void
 364 pagescrub(page_t *pp, uint_t off, uint_t len)
 365 {
 366         uint64_t pa, length;
 367 


 783                     chunkp += contig_mem_import_size_max) {
 784 
 785                         if (prom_alloc(chunkp, contig_mem_import_size_max,
 786                             MMU_PAGESIZE4M) != chunkp) {
 787                                 break;
 788                         }
 789                 }
 790                 contig_mem_prealloc_size = chunkp - alloc_base;
 791                 ASSERT(contig_mem_prealloc_size != 0);
 792         }
 793 
 794         if (contig_mem_prealloc_size != 0) {
 795                 contig_mem_prealloc_buf = alloc_base;
 796         } else {
 797                 contig_mem_prealloc_buf = NULL;
 798         }
 799         alloc_base += contig_mem_prealloc_size;
 800 
 801         return (alloc_base);
 802 }