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

Generated by: LCOV version 1.7