LCOV - code coverage report
Current view: directory - src/shared/imc/posix - nacl_imc_posix.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 46 23 50.0 %
Date: 2014-10-23 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                 : /*
       9                 :  * NaCl inter-module communication primitives.
      10                 :  *
      11                 :  * This file implements common parts of IMC for "UNIX like systems" (i.e. not
      12                 :  * used on Windows).
      13                 :  */
      14                 : 
      15                 : #include <assert.h>
      16                 : #include <ctype.h>
      17                 : #include <errno.h>
      18                 : #include <fcntl.h>
      19                 : #include <limits.h>
      20                 : #include <stdio.h>
      21                 : #include <unistd.h>
      22                 : #include <sys/mman.h>
      23                 : #include <sys/types.h>
      24                 : #if NACL_ANDROID
      25                 : #include <linux/ashmem.h>
      26                 : #endif
      27                 : 
      28                 : #include <algorithm>
      29                 : 
      30                 : #include "native_client/src/include/atomic_ops.h"
      31                 : 
      32                 : #include "native_client/src/shared/imc/nacl_imc_c.h"
      33                 : #include "native_client/src/shared/platform/nacl_check.h"
      34                 : 
      35                 : 
      36                 : #if NACL_LINUX && defined(NACL_ENABLE_TMPFS_REDIRECT_VAR)
      37                 : static const char kNaClTempPrefixVar[] = "NACL_TMPFS_PREFIX";
      38                 : #endif
      39                 : 
      40                 : /*
      41                 :  * The pathname or SHM-namespace prefixes for memory objects created
      42                 :  * by CreateMemoryObject().
      43                 :  */
      44                 : static const char kShmTempPrefix[] = "/tmp/google-nacl-shm-";
      45                 : static const char kShmOpenPrefix[] = "/google-nacl-shm-";
      46                 : 
      47                 : static NaClCreateMemoryObjectFunc g_create_memory_object_func = NULL;
      48                 : 
      49                 : 
      50                 : /* Duplicate a file descriptor. */
      51               0 : NaClHandle NaClDuplicateNaClHandle(NaClHandle handle) {
      52               0 :   return dup(handle);
      53                 : }
      54                 : 
      55               0 : void NaClSetCreateMemoryObjectFunc(NaClCreateMemoryObjectFunc func) {
      56               0 :   g_create_memory_object_func = func;
      57               0 : }
      58                 : 
      59                 : #if NACL_ANDROID
      60                 : #define ASHMEM_DEVICE "/dev/ashmem"
      61                 : 
      62                 : static int AshmemCreateRegion(size_t size) {
      63                 :   int fd;
      64                 : 
      65                 :   fd = open(ASHMEM_DEVICE, O_RDWR);
      66                 :   if (fd < 0)
      67                 :     return -1;
      68                 : 
      69                 :   if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) {
      70                 :     close(fd);
      71                 :     return -1;
      72                 :   }
      73                 : 
      74                 :   return fd;
      75                 : }
      76                 : #endif
      77                 : 
      78               0 : int NaClWouldBlock(void) {
      79               0 :   return errno == EAGAIN;
      80                 : }
      81                 : 
      82                 : #if !NACL_ANDROID
      83                 : static Atomic32 memory_object_count = 0;
      84                 : 
      85             300 : static int TryShmOrTempOpen(size_t length, const char* prefix, bool use_temp) {
      86                 :   char name[PATH_MAX];
      87             300 :   if (0 == length) {
      88               0 :     return -1;
      89                 :   }
      90                 : 
      91               0 :   for (;;) {
      92                 :     int m;
      93                 :     snprintf(name, sizeof name, "%s-%u.%u", prefix,
      94                 :              getpid(),
      95             300 :              (int) AtomicIncrement(&memory_object_count, 1));
      96             300 :     if (use_temp) {
      97               0 :       m = open(name, O_RDWR | O_CREAT | O_EXCL, 0);
      98                 :     } else {
      99                 :       /*
     100                 :        * Using 0 for the mode causes shm_unlink to fail with EACCES on Mac
     101                 :        * OS X 10.8. As of 10.8, the kernel requires the user to have write
     102                 :        * permission to successfully shm_unlink.
     103                 :        */
     104             300 :       m = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IWUSR);
     105                 :     }
     106             300 :     if (0 <= m) {
     107             300 :       if (use_temp) {
     108               0 :         int rc = unlink(name);
     109               0 :         DCHECK(rc == 0);
     110                 :       } else {
     111             300 :         int rc = shm_unlink(name);
     112             300 :         DCHECK(rc == 0);
     113                 :       }
     114             300 :       if (ftruncate(m, length) == -1) {
     115               0 :         close(m);
     116               0 :         m = -1;
     117                 :       }
     118             300 :       return m;
     119                 :     }
     120               0 :     if (errno != EEXIST) {
     121               0 :       return -1;
     122                 :     }
     123                 :     /* Retry only if we got EEXIST. */
     124                 :   }
     125                 : }
     126                 : #endif
     127                 : 
     128             300 : NaClHandle NaClCreateMemoryObject(size_t length, int executable) {
     129                 :   int fd;
     130                 : 
     131             300 :   if (0 == length) {
     132               0 :     return -1;
     133                 :   }
     134                 : 
     135             300 :   if (g_create_memory_object_func != NULL) {
     136               0 :     fd = g_create_memory_object_func(length, executable);
     137               0 :     if (fd >= 0)
     138               0 :       return fd;
     139                 :   }
     140                 : 
     141                 : #if NACL_ANDROID
     142                 :   return AshmemCreateRegion(length);
     143                 : #else
     144                 :   /*
     145                 :    * /dev/shm is not always available on Linux.
     146                 :    * Sometimes it's mounted as noexec.
     147                 :    * To handle this case, sel_ldr can take a path
     148                 :    * to tmpfs from the environment.
     149                 :    */
     150                 : #if NACL_LINUX && defined(NACL_ENABLE_TMPFS_REDIRECT_VAR)
     151                 :   if (NACL_ENABLE_TMPFS_REDIRECT_VAR) {
     152                 :     const char* prefix = getenv(kNaClTempPrefixVar);
     153                 :     if (prefix != NULL) {
     154                 :       fd = TryShmOrTempOpen(length, prefix, true);
     155                 :       if (fd >= 0) {
     156                 :         return fd;
     157                 :       }
     158                 :     }
     159                 :   }
     160                 : #endif
     161                 : 
     162                 :   if (NACL_OSX && executable) {
     163                 :     /*
     164                 :      * On Mac OS X, shm_open() gives us file descriptors that the OS
     165                 :      * won't mmap() with PROT_EXEC, which is no good for the dynamic
     166                 :      * code region, so we must use /tmp instead.
     167                 :      */
     168                 :     return TryShmOrTempOpen(length, kShmTempPrefix, true);
     169                 :   }
     170                 : 
     171                 :   /* Try shm_open(). */
     172             300 :   return TryShmOrTempOpen(length, kShmOpenPrefix, false);
     173                 : #endif  /* !NACL_ANDROID */
     174                 : }
     175                 : 
     176             382 : void* NaClMap(struct NaClDescEffector* effp,
     177                 :               void* start, size_t length, int prot, int flags,
     178                 :               NaClHandle memory, off_t offset) {
     179                 :   static const int kPosixProt[] = {
     180                 :     PROT_NONE,
     181                 :     PROT_READ,
     182                 :     PROT_WRITE,
     183                 :     PROT_READ | PROT_WRITE,
     184                 :     PROT_EXEC,
     185                 :     PROT_READ | PROT_EXEC,
     186                 :     PROT_WRITE | PROT_EXEC,
     187                 :     PROT_READ | PROT_WRITE | PROT_EXEC
     188                 :   };
     189             382 :   int adjusted = 0;
     190                 :   UNREFERENCED_PARAMETER(effp);
     191                 : 
     192             382 :   if (flags & NACL_MAP_SHARED) {
     193             382 :     adjusted |= MAP_SHARED;
     194                 :   }
     195             382 :   if (flags & NACL_MAP_PRIVATE) {
     196               0 :     adjusted |= MAP_PRIVATE;
     197                 :   }
     198             382 :   if (flags & NACL_MAP_FIXED) {
     199             382 :     adjusted |= MAP_FIXED;
     200                 :   }
     201             382 :   return mmap(start, length, kPosixProt[prot & 7], adjusted, memory, offset);
     202                 : }
     203                 : 
     204               0 : int NaClUnmap(void* start, size_t length) {
     205               0 :   return munmap(start, length);
     206                 : }

Generated by: LCOV version 1.7