LCOV - code coverage report
Current view: directory - src/trusted/service_runtime/posix - sel_memory.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 60 46 76.7 %
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 Service Runtime memory allocation code
       9                 :  */
      10                 : 
      11                 : #include <sys/mman.h>
      12                 : #include <sys/stat.h>
      13                 : #include <sys/types.h>
      14                 : 
      15                 : #include <errno.h>
      16                 : #include <fcntl.h>
      17                 : #include <stdint.h>
      18                 : #include <stdio.h>
      19                 : #include <string.h>
      20                 : #include <unistd.h>
      21                 : 
      22                 : #include "native_client/src/include/nacl_platform.h"
      23                 : #include "native_client/src/include/portability.h"
      24                 : #include "native_client/src/shared/platform/nacl_exit.h"
      25                 : #include "native_client/src/shared/platform/nacl_global_secure_random.h"
      26                 : #include "native_client/src/shared/platform/nacl_log.h"
      27                 : #include "native_client/src/trusted/service_runtime/sel_memory.h"
      28                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      29                 : #include "native_client/src/trusted/service_runtime/include/machine/_types.h"
      30                 : 
      31            1264 : void NaClPageFree(void *p, size_t size) {
      32            2528 :   if (p == 0 || size == 0)
      33               0 :     return;
      34            1264 :   if (munmap(p, size) != 0) {
      35               0 :     NaClLog(LOG_FATAL, "NaClPageFree: munmap() failed");
      36               0 :   }
      37            1264 : }
      38                 : 
      39            1270 : static int NaClPageAllocInternalFlags(void **p, size_t size, int map_flags) {
      40            1270 :   void *addr;
      41                 : 
      42            1270 :   map_flags |= MAP_PRIVATE | MAP_ANONYMOUS;
      43                 : 
      44            1270 :   NaClLog(4,
      45                 :           "NaClPageAllocInternalFlags:"
      46                 :           " mmap(%p, %"NACL_PRIxS", %#x, %#x, %d, %"NACL_PRIdNACL_OFF64")\n",
      47                 :           *p, size, PROT_NONE, map_flags, -1,
      48                 :           (nacl_abi_off64_t) 0);
      49            1270 :   addr = mmap(*p, size, PROT_NONE, map_flags, -1, (off_t) 0);
      50            1270 :   if (MAP_FAILED == addr) {
      51               0 :     addr = NULL;
      52               0 :   }
      53            1270 :   if (NULL != addr) {
      54            1270 :     *p = addr;
      55            1270 :   }
      56            1270 :   return (NULL == addr) ? -ENOMEM : 0;
      57                 : }
      58                 : 
      59                 : /*
      60                 :  * Note that NaClPageAlloc does not allocate pages that satisify
      61                 :  * NaClIsAllocPageMultiple.  On linux/osx, the system does not impose
      62                 :  * any such restrictions, and we only need to enforce the restriction
      63                 :  * on NaCl app code to ensure that the app code is portable across all
      64                 :  * host OSes.
      65                 :  */
      66            1005 : static int NaClPageAllocInternal(void **p, size_t size) {
      67            1005 :   int map_flags = 0;
      68                 : 
      69            1005 :   if (NULL != *p) {
      70               0 :     map_flags |= MAP_FIXED;
      71               0 :   }
      72                 :  #if NACL_LINUX
      73                 :   /*
      74                 :    * Indicate to the kernel that we just want these pages allocated, not
      75                 :    * committed.  This is important for systems with relatively little RAM+swap.
      76                 :    * See bug 251.
      77                 :    */
      78                 :   map_flags |= MAP_NORESERVE;
      79                 : #elif NACL_OSX
      80                 :   /*
      81                 :    * TODO(cbiffle): This file is used by Mac OS X as well as Linux.
      82                 :    * An equivalent fix may require this to stop, since we might have
      83                 :    * to drop to the xnu layer and use vm_allocate.
      84                 :    *
      85                 :    * Currently this code is not guaranteed to work for non-x86-32 Mac OS X.
      86                 :    */
      87                 : #else
      88                 : # error This file should be included only by Linux and (surprisingly) OS X.
      89                 : #endif
      90            1005 :   return NaClPageAllocInternalFlags(p, size, map_flags);
      91                 : }
      92                 : 
      93                 : /*
      94                 :  * Pick a "hint" address that is random.
      95                 :  */
      96             265 : int NaClPageAllocRandomized(void **p, size_t size) {
      97             265 :   uintptr_t       addr;
      98             265 :   int             neg_errno = -ENOMEM;  /* in case we change kNumTries to 0 */
      99             265 :   int             tries;
     100             265 :   const int       kNumTries = 4;
     101                 :   /*
     102                 :    * linux permits 128 TB of user address space.
     103                 :    */
     104                 : 
     105             530 :   for (tries = 0; tries < kNumTries; ++tries) {
     106                 : #if NACL_HOST_WORDSIZE == 32
     107                 :     addr = NaClGlobalSecureRngUint32();
     108                 :     NaClLog(2, "NaClPageAllocRandomized: 0x%"NACL_PRIxPTR"\n", addr);
     109                 :     /* linux permits 3-4 GB of user address space */
     110                 :     *p = (void *) (addr & ~((uintptr_t) NACL_MAP_PAGESIZE - 1)
     111                 :                    & ((~(uintptr_t) 0) >> 1));
     112                 : #elif NACL_HOST_WORDSIZE == 64
     113             265 :     addr = NaClGlobalSecureRngUint32();
     114             265 :     NaClLog(2, "NaClPageAllocRandomized: 0x%"NACL_PRIxPTR"\n", addr);
     115                 :     /*
     116                 :      * linux permits 128 TB of user address space, and we keep the low
     117                 :      * 16 bits free (64K alignment to match Windows), so we have
     118                 :      * 47-16=31 bits of entropy.
     119                 :      */
     120             265 :     *p = (void *) ((addr << NACL_MAP_PAGESHIFT)  /* bits [47:16] are random */
     121                 :                    & ((((uintptr_t) 1) << 47) - 1));  /* now bits [46:16] */
     122                 : #else
     123                 : # error "where am i?"
     124                 : #endif
     125                 : 
     126             265 :     NaClLog(2, "NaClPageAllocRandomized: hint 0x%"NACL_PRIxPTR"\n",
     127                 :             (uintptr_t) *p);
     128             265 :     neg_errno = NaClPageAllocInternalFlags(p, size, 0);
     129             265 :     if (0 == neg_errno) {
     130             265 :       break;
     131                 :     }
     132               0 :   }
     133             265 :   if (0 != neg_errno) {
     134               0 :     NaClLog(LOG_INFO,
     135                 :             "NaClPageAllocRandomized: failed (%d), dropping hints\n",
     136                 :             -neg_errno);
     137               0 :     *p = 0;
     138               0 :     neg_errno = NaClPageAllocInternalFlags(p, size, 0);
     139               0 :   }
     140             265 :   return neg_errno;
     141                 : }
     142                 : 
     143            1005 : int NaClPageAlloc(void **p, size_t size) {
     144            1005 :   void *addr = NULL;
     145            1005 :   int rv;
     146                 : 
     147            1005 :   if (0 == (rv = NaClPageAllocInternal(&addr, size))) {
     148            1005 :     *p = addr;
     149            1005 :   }
     150                 : 
     151            1005 :   return rv;
     152                 : }
     153                 : 
     154               0 : int NaClPageAllocAtAddr(void **p, size_t size) {
     155               0 :   return NaClPageAllocInternal(p, size);
     156                 : }
     157                 : 
     158                 : /*
     159                 : * This is critical to make the text region non-writable, and the data
     160                 : * region read/write but no exec.  Of course, some kernels do not
     161                 : * respect the lack of PROT_EXEC.
     162                 : */
     163            2214 : int NaClMprotect(void *addr, size_t len, int prot) {
     164            2214 :   int  ret = mprotect(addr, len, prot);
     165                 : 
     166            6642 :   return ret == -1 ? -errno : ret;
     167                 : }
     168                 : 
     169                 : 
     170             279 : int NaClMadvise(void *start, size_t length, int advice) {
     171             279 :   int ret = madvise(start, length, advice);
     172                 : 
     173                 :   /*
     174                 :    * MADV_DONTNEED and MADV_NORMAL are needed
     175                 :    */
     176             837 :   return ret == -1 ? -errno : ret;
     177                 : }

Generated by: LCOV version 1.7