LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_addrspace.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 100 81 81.0 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * NaCl Simple/secure ELF loader (NaCl SEL).
       9                 :  */
      10                 : 
      11                 : #include <errno.h>
      12                 : 
      13                 : #include "native_client/src/include/nacl_platform.h"
      14                 : #include "native_client/src/include/portability.h"
      15                 : #include "native_client/src/shared/platform/nacl_log.h"
      16                 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
      17                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      18                 : #include "native_client/src/trusted/service_runtime/sel_memory.h"
      19                 : #include "native_client/src/trusted/service_runtime/sel_util.h"
      20                 : 
      21                 : #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
      22                 : 
      23             280 : NaClErrorCode NaClAllocAddrSpaceAslr(struct NaClApp *nap,
      24             280 :                                      enum NaClAslrMode aslr_mode) {
      25             280 :   void        *mem;
      26             280 :   int         rv;
      27             280 :   uintptr_t   hole_start;
      28             280 :   size_t      hole_size;
      29             280 :   uintptr_t   stack_start;
      30                 : 
      31             280 :   NaClLog(2,
      32                 :           "NaClAllocAddrSpace: calling NaClAllocateSpace(*,0x%016"
      33                 :           NACL_PRIxS")\n",
      34                 :           ((size_t) 1 << nap->addr_bits));
      35                 : 
      36             280 :   rv = NaClAllocateSpaceAslr(&mem, (uintptr_t) 1U << nap->addr_bits,
      37                 :                              aslr_mode);
      38             280 :   if (LOAD_OK != rv) {
      39               0 :     return rv;
      40                 :   }
      41                 : 
      42             280 :   nap->mem_start = (uintptr_t) mem;
      43                 :   /*
      44                 :    * The following should not be NaClLog(2, ...) because logging with
      45                 :    * any detail level higher than LOG_INFO is disabled in the release
      46                 :    * builds.  This was to reduce logging overhead, so as to eliminate
      47                 :    * at least a function call as well as possibly a TLS/TSD read if
      48                 :    * module-specific logging verbosity level comparisons are needed.
      49                 :    */
      50             280 :   NaClLog(LOG_INFO,
      51                 :           ("Native Client module will be loaded at"
      52                 :            " base address 0x%016"NACL_PRIxPTR"\n"),
      53                 :           nap->mem_start);
      54                 : 
      55             280 :   hole_start = NaClRoundAllocPage(nap->data_end);
      56                 : 
      57             280 :   if (nap->stack_size >= ((uintptr_t) 1U) << nap->addr_bits) {
      58               0 :     NaClLog(LOG_FATAL, "NaClAllocAddrSpace: stack too large!");
      59               0 :   }
      60             280 :   stack_start = (((uintptr_t) 1U) << nap->addr_bits) - nap->stack_size;
      61             280 :   stack_start = NaClTruncAllocPage(stack_start);
      62                 : 
      63             280 :   if (stack_start < hole_start) {
      64               1 :     return LOAD_DATA_OVERLAPS_STACK_SECTION;
      65                 :   }
      66                 : 
      67             279 :   hole_size = stack_start - hole_start;
      68             279 :   hole_size = NaClTruncAllocPage(hole_size);
      69                 : 
      70                 :   /*
      71                 :    * mprotect and madvise unused data space to "free" it up, but
      72                 :    * retain mapping so no other memory can be mapped into those
      73                 :    * addresses.
      74                 :    */
      75             279 :   if (hole_size == 0) {
      76               0 :     NaClLog(2, ("NaClAllocAddrSpace: hole between end of data and"
      77                 :                 " the beginning of stack is zero size.\n"));
      78               0 :   } else {
      79             279 :     NaClLog(2,
      80                 :             ("madvising 0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxS
      81                 :              ", MADV_DONTNEED\n"),
      82                 :             nap->mem_start + hole_start, hole_size);
      83             279 :     if (0 != NaClMadvise((void *) (nap->mem_start + hole_start),
      84                 :                          hole_size,
      85                 :                          MADV_DONTNEED)) {
      86               0 :       NaClLog(1, "madvise, errno %d\n", errno);
      87               0 :       return LOAD_MADVISE_FAIL;
      88                 :     }
      89             279 :     NaClLog(2,
      90                 :             "mprotecting 0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxS", PROT_NONE\n",
      91                 :             nap->mem_start + hole_start, hole_size);
      92             279 :     if (0 != NaClMprotect((void *) (nap->mem_start + hole_start),
      93                 :                           hole_size,
      94                 :                           PROT_NONE)) {
      95               0 :       NaClLog(1, "mprotect, errno %d\n", errno);
      96               0 :       return LOAD_MPROTECT_FAIL;
      97                 :     }
      98                 :   }
      99                 : 
     100             279 :   return LOAD_OK;
     101             280 : }
     102                 : 
     103              11 : NaClErrorCode NaClAllocAddrSpace(struct NaClApp *nap) {
     104              11 :   return NaClAllocAddrSpaceAslr(nap, 1);
     105                 : }
     106                 : 
     107                 : /*
     108                 :  * Apply memory protection to memory regions.
     109                 :  */
     110             265 : NaClErrorCode NaClMemoryProtection(struct NaClApp *nap) {
     111             265 :   uintptr_t start_addr;
     112             265 :   size_t    region_size;
     113             265 :   int       err;
     114                 : 
     115                 :   /*
     116                 :    * The first NACL_SYSCALL_START_ADDR bytes are mapped as PROT_NONE.
     117                 :    * This enables NULL pointer checking, and provides additional protection
     118                 :    * against addr16/data16 prefixed operations being used for attacks.
     119                 :    */
     120                 : 
     121             265 :   NaClLog(3, "Protecting guard pages for 0x%08"NACL_PRIxPTR"\n",
     122                 :           nap->mem_start);
     123                 :   /* Add the zero page to the mmap */
     124             265 :   NaClVmmapAdd(&nap->mem_map,
     125                 :                0,
     126                 :                NACL_SYSCALL_START_ADDR >> NACL_PAGESHIFT,
     127                 :                PROT_NONE,
     128                 :                NACL_ABI_MAP_PRIVATE,
     129                 :                NULL,
     130                 :                0,
     131                 :                0);
     132                 : 
     133             265 :   start_addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
     134                 :   /*
     135                 :    * The next pages up to NACL_TRAMPOLINE_END are the trampolines.
     136                 :    * Immediately following that is the loaded text section.
     137                 :    * These are collectively marked as PROT_READ | PROT_EXEC.
     138                 :    */
     139             265 :   region_size = NaClRoundPage(nap->static_text_end - NACL_SYSCALL_START_ADDR);
     140             265 :   NaClLog(3,
     141                 :           ("Trampoline/text region start 0x%08"NACL_PRIxPTR","
     142                 :            " size 0x%08"NACL_PRIxS", end 0x%08"NACL_PRIxPTR"\n"),
     143                 :           start_addr, region_size,
     144                 :           start_addr + region_size);
     145             265 :   if (0 != (err = NaClMprotect((void *) start_addr,
     146                 :                                region_size,
     147                 :                                PROT_READ | PROT_EXEC))) {
     148               0 :     NaClLog(LOG_ERROR,
     149                 :             ("NaClMemoryProtection: "
     150                 :              "NaClMprotect(0x%08"NACL_PRIxPTR", "
     151                 :              "0x%08"NACL_PRIxS", 0x%x) failed, "
     152                 :              "error %d (trampoline + code)\n"),
     153                 :             start_addr, region_size, PROT_READ | PROT_EXEC,
     154                 :             err);
     155               0 :     return LOAD_MPROTECT_FAIL;
     156                 :   }
     157             530 :   NaClVmmapAdd(&nap->mem_map,
     158             265 :                NaClSysToUser(nap, start_addr) >> NACL_PAGESHIFT,
     159                 :                region_size >> NACL_PAGESHIFT,
     160                 :                NACL_ABI_PROT_READ | NACL_ABI_PROT_EXEC,
     161                 :                NACL_ABI_MAP_PRIVATE,
     162                 :                NULL,
     163                 :                0,
     164                 :                0);
     165                 : 
     166             265 :   start_addr = NaClUserToSys(nap, nap->dynamic_text_start);
     167             265 :   region_size = nap->dynamic_text_end - nap->dynamic_text_start;
     168             265 :   NaClLog(3,
     169                 :           ("shm txt region start 0x%08"NACL_PRIxPTR", size 0x%08"NACL_PRIxS","
     170                 :            " end 0x%08"NACL_PRIxPTR"\n"),
     171                 :           start_addr, region_size,
     172                 :           start_addr + region_size);
     173             265 :   if (0 != region_size) {
     174                 :     /*
     175                 :      * Page protections for this region have already been set up by
     176                 :      * nacl_text.c.
     177                 :      *
     178                 :      * We record the mapping for consistency with other fixed
     179                 :      * mappings, but the record is not actually used.  Overmapping is
     180                 :      * prevented by a separate range check, which is done by
     181                 :      * NaClSysCommonAddrRangeContainsExecutablePages_mu().
     182                 :      */
     183             518 :     NaClVmmapAdd(&nap->mem_map,
     184             259 :                  NaClSysToUser(nap, start_addr) >> NACL_PAGESHIFT,
     185                 :                  region_size >> NACL_PAGESHIFT,
     186                 :                  NACL_ABI_PROT_READ | NACL_ABI_PROT_EXEC,
     187                 :                  NACL_ABI_MAP_PRIVATE,
     188                 :                  nap->text_shm,
     189                 :                  0,
     190                 :                  region_size);
     191             259 :   }
     192                 : 
     193             265 :   if (0 != nap->rodata_start) {
     194             261 :     uintptr_t rodata_end;
     195                 :     /*
     196                 :      * TODO(mseaborn): Could reduce the number of cases by ensuring
     197                 :      * that nap->data_start is always non-zero, even if
     198                 :      * nap->rodata_start == nap->data_start == nap->break_addr.
     199                 :      */
     200             261 :     if (0 != nap->data_start) {
     201             251 :       rodata_end = NaClTruncAllocPage(nap->data_start);
     202             251 :     }
     203                 :     else {
     204              10 :       rodata_end = nap->break_addr;
     205                 :     }
     206                 : 
     207             261 :     start_addr = NaClUserToSys(nap, nap->rodata_start);
     208             522 :     region_size = NaClRoundPage(NaClRoundAllocPage(rodata_end)
     209             261 :                                 - NaClSysToUser(nap, start_addr));
     210             261 :     NaClLog(3,
     211                 :             ("RO data region start 0x%08"NACL_PRIxPTR", size 0x%08"NACL_PRIxS","
     212                 :              " end 0x%08"NACL_PRIxPTR"\n"),
     213                 :             start_addr, region_size,
     214                 :             start_addr + region_size);
     215             261 :     if (0 != (err = NaClMprotect((void *) start_addr,
     216                 :                                  region_size,
     217                 :                                  PROT_READ))) {
     218               0 :       NaClLog(LOG_ERROR,
     219                 :               ("NaClMemoryProtection: "
     220                 :                "NaClMprotect(0x%08"NACL_PRIxPTR", "
     221                 :                "0x%08"NACL_PRIxS", 0x%x) failed, "
     222                 :                "error %d (rodata)\n"),
     223                 :               start_addr, region_size, PROT_READ,
     224                 :               err);
     225               0 :       return LOAD_MPROTECT_FAIL;
     226                 :     }
     227             522 :     NaClVmmapAdd(&nap->mem_map,
     228             261 :                  NaClSysToUser(nap, start_addr) >> NACL_PAGESHIFT,
     229                 :                  region_size >> NACL_PAGESHIFT,
     230                 :                  NACL_ABI_PROT_READ,
     231                 :                  NACL_ABI_MAP_PRIVATE,
     232                 :                  NULL,
     233                 :                  0,
     234                 :                  0);
     235             261 :   }
     236                 : 
     237                 :   /*
     238                 :    * data_end is max virtual addr seen, so start_addr <= data_end
     239                 :    * must hold.
     240                 :    */
     241                 : 
     242             265 :   if (0 != nap->data_start) {
     243             251 :     start_addr = NaClUserToSys(nap, NaClTruncAllocPage(nap->data_start));
     244             502 :     region_size = NaClRoundPage(NaClRoundAllocPage(nap->data_end)
     245             251 :                                 - NaClSysToUser(nap, start_addr));
     246             251 :     NaClLog(3,
     247                 :             ("RW data region start 0x%08"NACL_PRIxPTR", size 0x%08"NACL_PRIxS","
     248                 :              " end 0x%08"NACL_PRIxPTR"\n"),
     249                 :             start_addr, region_size,
     250                 :             start_addr + region_size);
     251             251 :     if (0 != (err = NaClMprotect((void *) start_addr,
     252                 :                                  region_size,
     253                 :                                  PROT_READ | PROT_WRITE))) {
     254               0 :       NaClLog(LOG_ERROR,
     255                 :               ("NaClMemoryProtection: "
     256                 :                "NaClMprotect(0x%08"NACL_PRIxPTR", "
     257                 :                "0x%08"NACL_PRIxS", 0x%x) failed, "
     258                 :                "error %d (data)\n"),
     259                 :               start_addr, region_size, PROT_READ | PROT_WRITE,
     260                 :               err);
     261               0 :       return LOAD_MPROTECT_FAIL;
     262                 :     }
     263             502 :     NaClVmmapAdd(&nap->mem_map,
     264             251 :                  NaClSysToUser(nap, start_addr) >> NACL_PAGESHIFT,
     265                 :                  region_size >> NACL_PAGESHIFT,
     266                 :                  NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE,
     267                 :                  NACL_ABI_MAP_PRIVATE,
     268                 :                  NULL,
     269                 :                  0,
     270                 :                  0);
     271             251 :   }
     272                 : 
     273                 :   /* stack is read/write but not execute */
     274             265 :   region_size = nap->stack_size;
     275             530 :   start_addr = NaClUserToSys(nap,
     276             265 :                              NaClTruncAllocPage(
     277                 :                                  ((uintptr_t) 1U << nap->addr_bits)
     278                 :                                  - nap->stack_size));
     279             265 :   NaClLog(3,
     280                 :           ("RW stack region start 0x%08"NACL_PRIxPTR", size 0x%08"NACL_PRIxS","
     281                 :            " end 0x%08"NACL_PRIxPTR"\n"),
     282                 :           start_addr, region_size,
     283                 :           start_addr + region_size);
     284             530 :   if (0 != (err = NaClMprotect((void *) start_addr,
     285             265 :                                NaClRoundAllocPage(nap->stack_size),
     286                 :                                PROT_READ | PROT_WRITE))) {
     287               0 :     NaClLog(LOG_ERROR,
     288                 :             ("NaClMemoryProtection: "
     289                 :              "NaClMprotect(0x%08"NACL_PRIxPTR", "
     290                 :              "0x%08"NACL_PRIxS", 0x%x) failed, "
     291                 :              "error %d (stack)\n"),
     292                 :             start_addr, region_size, PROT_READ | PROT_WRITE,
     293                 :             err);
     294               0 :     return LOAD_MPROTECT_FAIL;
     295                 :   }
     296                 : 
     297             530 :   NaClVmmapAdd(&nap->mem_map,
     298             265 :                NaClSysToUser(nap, start_addr) >> NACL_PAGESHIFT,
     299                 :                nap->stack_size >> NACL_PAGESHIFT,
     300                 :                NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE,
     301                 :                NACL_ABI_MAP_PRIVATE,
     302                 :                NULL,
     303                 :                0,
     304                 :                0);
     305             265 :   return LOAD_OK;
     306             265 : }
     307                 : 
     308               0 : NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) {
     309               0 :   return NaClAllocateSpaceAslr(mem, addrsp_size, 1);
     310                 : }

Generated by: LCOV version 1.7