LCOV - code coverage report
Current view: directory - src/trusted/desc - nacl_desc_imc_shm.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 162 0 0.0 %
Date: 2014-09-25 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.  Transferrable shared memory objects.
       9                 :  */
      10                 : 
      11                 : #include "native_client/src/include/portability.h"
      12                 : #include "native_client/src/include/nacl_platform.h"
      13                 : 
      14                 : #include <stdlib.h>
      15                 : #include <string.h>
      16                 : 
      17                 : #include "native_client/src/shared/imc/nacl_imc_c.h"
      18                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      19                 : #include "native_client/src/trusted/desc/nacl_desc_effector.h"
      20                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      21                 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
      22                 : 
      23                 : #include "native_client/src/shared/platform/nacl_find_addrsp.h"
      24                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      25                 : #include "native_client/src/shared/platform/nacl_log.h"
      26                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      27                 : 
      28                 : #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
      29                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      30                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      31                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      32                 : #include "native_client/src/trusted/service_runtime/internal_errno.h"
      33                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      34                 : 
      35                 : #ifndef SIZE_T_MAX
      36                 : # define SIZE_T_MAX   (~(size_t) 0)
      37                 : #endif
      38                 : 
      39                 : /*
      40                 :  * This file contains the implementation of the NaClDescImcShm
      41                 :  * subclass of NaClDesc.
      42                 :  *
      43                 :  * NaClDescImcShm is the subclass that wraps IMC shm descriptors.
      44                 :  */
      45                 : 
      46                 : static struct NaClDescVtbl const kNaClDescImcShmVtbl;  /* fwd */
      47                 : 
      48                 : static int NaClDescImcShmSubclassCtor(struct NaClDescImcShm  *self,
      49                 :                                       NaClHandle             h,
      50               0 :                                       nacl_off64_t           size) {
      51               0 :   struct NaClDesc *basep = (struct NaClDesc *) self;
      52                 : 
      53                 :   /*
      54                 :    * off_t is signed, but size_t are not; historically size_t is for
      55                 :    * sizeof and similar, and off_t is also used for stat structure
      56                 :    * st_size member.  This runtime test detects large object sizes
      57                 :    * that are silently converted to negative values.
      58                 :    */
      59               0 :   if (size < 0 || SIZE_T_MAX < (uint64_t) size) {
      60               0 :     return 0;
      61                 :   }
      62               0 :   self->h = h;
      63               0 :   self->size = size;
      64               0 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) &kNaClDescImcShmVtbl;
      65               0 :   return 1;
      66               0 : }
      67                 : 
      68                 : int NaClDescImcShmCtor(struct NaClDescImcShm  *self,
      69                 :                        NaClHandle             h,
      70               0 :                        nacl_off64_t           size) {
      71               0 :   struct NaClDesc *basep = (struct NaClDesc *) self;
      72                 :   int rv;
      73                 : 
      74               0 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) NULL;
      75                 : 
      76               0 :   if (!NaClDescCtor(basep)) {
      77               0 :     return 0;
      78                 :   }
      79               0 :   rv = NaClDescImcShmSubclassCtor(self, h, size);
      80               0 :   if (!rv) {
      81                 :     /* NaClDescImcShm construction failed, still a NaClDesc object */
      82               0 :     (*NACL_VTBL(NaClRefCount, basep)->Dtor)((struct NaClRefCount *) basep);
      83                 :   }
      84               0 :   (*NACL_VTBL(NaClDesc, basep)->SetFlags)(basep, NACL_ABI_O_RDWR);
      85               0 :   return 1;
      86               0 : }
      87                 : 
      88                 : int NaClDescImcShmAllocCtor(struct NaClDescImcShm  *self,
      89                 :                             nacl_off64_t           size,
      90               0 :                             int                    executable) {
      91                 :   NaClHandle h;
      92                 :   int        rv;
      93                 : 
      94               0 :   if (size < 0 || SIZE_T_MAX < (uint64_t) size) {
      95                 :     NaClLog(4,
      96                 :             "NaClDescImcShmAllocCtor: requested size 0x%08"NACL_PRIx64
      97                 :             " (0x%08"NACL_PRId64") too large\n",
      98               0 :             size, size);
      99               0 :     return 0;
     100                 :   }
     101               0 :   h = NaClCreateMemoryObject((size_t) size, executable);
     102               0 :   if (NACL_INVALID_HANDLE == h) {
     103               0 :     return 0;
     104                 :   }
     105               0 :   if (0 == (rv = NaClDescImcShmCtor(self, h, size))) {
     106               0 :     (void) NaClClose(h);
     107                 :   }
     108               0 :   return rv;
     109               0 : }
     110                 : 
     111               0 : struct NaClDesc *NaClDescImcShmMake(NaClHandle handle, nacl_off64_t size) {
     112               0 :   struct NaClDescImcShm *desc = malloc(sizeof(*desc));
     113               0 :   if (NULL == desc) {
     114               0 :     return NULL;
     115                 :   }
     116               0 :   if (!NaClDescImcShmCtor(desc, handle, size)) {
     117               0 :     free(desc);
     118               0 :     return NULL;
     119                 :   }
     120               0 :   return &desc->base;
     121               0 : }
     122                 : 
     123               0 : static void NaClDescImcShmDtor(struct NaClRefCount *vself) {
     124               0 :   struct NaClDescImcShm  *self = (struct NaClDescImcShm *) vself;
     125                 : 
     126               0 :   (void) NaClClose(self->h);
     127               0 :   self->h = NACL_INVALID_HANDLE;
     128               0 :   vself->vtbl = (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
     129               0 :   (*vself->vtbl->Dtor)(vself);
     130               0 : }
     131                 : 
     132                 : static uintptr_t NaClDescImcShmMap(struct NaClDesc         *vself,
     133                 :                                    struct NaClDescEffector *effp,
     134                 :                                    void                    *start_addr,
     135                 :                                    size_t                  len,
     136                 :                                    int                     prot,
     137                 :                                    int                     flags,
     138               0 :                                    nacl_off64_t            offset) {
     139               0 :   struct NaClDescImcShm  *self = (struct NaClDescImcShm *) vself;
     140                 : 
     141                 :   int           nacl_imc_prot;
     142                 :   int           nacl_imc_flags;
     143                 :   uintptr_t     addr;
     144                 :   void          *result;
     145                 :   nacl_off64_t  tmp_off64;
     146                 : 
     147                 :   /*
     148                 :    * shm must have NACL_ABI_MAP_SHARED in flags, and all calls through
     149                 :    * this API must supply a start_addr, so NACL_ABI_MAP_FIXED is
     150                 :    * assumed.
     151                 :    */
     152               0 :   if (NACL_ABI_MAP_SHARED != (flags & NACL_ABI_MAP_SHARING_MASK)) {
     153                 :     NaClLog(LOG_INFO,
     154                 :             ("NaClDescImcShmMap: Mapping not NACL_ABI_MAP_SHARED,"
     155                 :              " flags 0x%x\n"),
     156               0 :             flags);
     157               0 :     return -NACL_ABI_EINVAL;
     158                 :   }
     159               0 :   if (0 != (NACL_ABI_MAP_FIXED & flags) && NULL == start_addr) {
     160                 :     NaClLog(LOG_INFO,
     161                 :             ("NaClDescImcShmMap: Mapping NACL_ABI_MAP_FIXED"
     162               0 :              " but start_addr is NULL\n"));
     163                 :   }
     164                 :   /* post-condition: if NULL == start_addr, then NACL_ABI_MAP_FIXED not set */
     165                 : 
     166                 :   /*
     167                 :    * prot must not contain bits other than PROT_{READ|WRITE|EXEC}.
     168                 :    */
     169                 :   if (0 != (~(NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE | NACL_ABI_PROT_EXEC)
     170               0 :             & prot)) {
     171                 :     NaClLog(LOG_INFO,
     172                 :             "NaClDescImcShmMap: prot has other bits than"
     173               0 :             " PROT_{READ|WRITE|EXEC}\n");
     174               0 :     return -NACL_ABI_EINVAL;
     175                 :   }
     176                 :   /*
     177                 :    * Map from NACL_ABI_ prot and flags bits to IMC library flags,
     178                 :    * which will later map back into posix-style prot/flags on *x
     179                 :    * boxen, and to MapViewOfFileEx arguments on Windows.
     180                 :    */
     181               0 :   nacl_imc_prot = 0;
     182               0 :   if (NACL_ABI_PROT_READ & prot) {
     183               0 :     nacl_imc_prot |= NACL_PROT_READ;
     184                 :   }
     185               0 :   if (NACL_ABI_PROT_WRITE & prot) {
     186               0 :     nacl_imc_prot |= NACL_PROT_WRITE;
     187                 :   }
     188               0 :   if (NACL_ABI_PROT_EXEC & prot) {
     189               0 :     nacl_imc_prot |= NACL_PROT_EXEC;
     190                 :   }
     191               0 :   nacl_imc_flags = NACL_MAP_SHARED;
     192               0 :   if (0 == (NACL_ABI_MAP_FIXED & flags)) {
     193                 :     /* start_addr is a hint, and we just ignore the hint... */
     194               0 :     if (!NaClFindAddressSpace(&addr, len)) {
     195               0 :       NaClLog(1, "NaClDescImcShmMap: no address space?!?\n");
     196               0 :       return -NACL_ABI_ENOMEM;
     197                 :     }
     198               0 :     start_addr = (void *) addr;
     199                 :   }
     200               0 :   nacl_imc_flags |= NACL_MAP_FIXED;
     201                 : 
     202               0 :   tmp_off64 = offset + len;
     203                 :   /* just NaClRoundAllocPage, but in 64 bits */
     204                 :   tmp_off64 = ((tmp_off64 + NACL_MAP_PAGESIZE - 1)
     205               0 :              & ~(uint64_t) (NACL_MAP_PAGESIZE - 1));
     206               0 :   if (tmp_off64 > INT32_MAX) {
     207                 :     NaClLog(LOG_INFO,
     208               0 :             "NaClDescImcShmMap: total offset exceeds 32-bits\n");
     209               0 :     return -NACL_ABI_EOVERFLOW;
     210                 :   }
     211                 : 
     212                 :   result = NaClMap(effp,
     213                 :                    (void *) start_addr,
     214                 :                    len,
     215                 :                    nacl_imc_prot,
     216                 :                    nacl_imc_flags,
     217                 :                    self->h,
     218               0 :                    (off_t) offset);
     219               0 :   if (NACL_MAP_FAILED == result) {
     220               0 :     return -NACL_ABI_E_MOVE_ADDRESS_SPACE;
     221                 :   }
     222               0 :   if (0 != (NACL_ABI_MAP_FIXED & flags) && result != (void *) start_addr) {
     223                 :     NaClLog(LOG_FATAL,
     224                 :             ("NaClDescImcShmMap: NACL_MAP_FIXED but got %p instead of %p\n"),
     225               0 :             result, start_addr);
     226                 :   }
     227               0 :   return (uintptr_t) start_addr;
     228               0 : }
     229                 : 
     230                 : #if NACL_WINDOWS
     231                 : static int NaClDescImcShmUnmapUnsafe(struct NaClDesc  *vself,
     232                 :                                      void             *start_addr,
     233               0 :                                      size_t           len) {
     234                 :   int       retval;
     235                 :   uintptr_t addr;
     236                 :   uintptr_t end_addr;
     237                 : 
     238                 :   UNREFERENCED_PARAMETER(vself);
     239                 : 
     240               0 :   retval = -NACL_ABI_EINVAL;
     241                 : 
     242                 :   for (addr = (uintptr_t) start_addr, end_addr = addr + len;
     243                 :        addr < end_addr;
     244               0 :        addr += NACL_MAP_PAGESIZE) {
     245                 :     int       status;
     246                 : 
     247                 :     /*
     248                 :      * On windows, we must unmap "properly", since overmapping will
     249                 :      * not tear down existing page mappings.
     250                 :      */
     251               0 :     status = NaClUnmap((void *) addr, NACL_MAP_PAGESIZE);
     252               0 :     if (0 != status) {
     253               0 :       NaClLog(LOG_FATAL, "NaClDescImcShmUnmapCommon: NaClUnmap failed\n");
     254               0 :       goto done;
     255                 :     }
     256               0 :   }
     257               0 :   retval = 0;
     258                 : done:
     259               0 :   return retval;
     260               0 : }
     261                 : #endif
     262                 : 
     263                 : static int NaClDescImcShmFstat(struct NaClDesc         *vself,
     264               0 :                                struct nacl_abi_stat    *stbp) {
     265               0 :   struct NaClDescImcShm  *self = (struct NaClDescImcShm *) vself;
     266                 : 
     267               0 :   if (self->size > INT32_MAX) {
     268               0 :     return -NACL_ABI_EOVERFLOW;
     269                 :   }
     270                 : 
     271               0 :   stbp->nacl_abi_st_dev = 0;
     272               0 :   stbp->nacl_abi_st_ino = 0x6c43614e;
     273                 :   stbp->nacl_abi_st_mode = (NACL_ABI_S_IFSHM |
     274                 :                             NACL_ABI_S_IRUSR |
     275               0 :                             NACL_ABI_S_IWUSR);
     276               0 :   stbp->nacl_abi_st_nlink = 1;
     277               0 :   stbp->nacl_abi_st_uid = -1;
     278               0 :   stbp->nacl_abi_st_gid = -1;
     279               0 :   stbp->nacl_abi_st_rdev = 0;
     280               0 :   stbp->nacl_abi_st_size = (nacl_abi_off_t) self->size;
     281               0 :   stbp->nacl_abi_st_blksize = 0;
     282               0 :   stbp->nacl_abi_st_blocks = 0;
     283               0 :   stbp->nacl_abi_st_atime = 0;
     284               0 :   stbp->nacl_abi_st_mtime = 0;
     285               0 :   stbp->nacl_abi_st_ctime = 0;
     286                 : 
     287               0 :   return 0;
     288               0 : }
     289                 : 
     290                 : static int NaClDescImcShmExternalizeSize(struct NaClDesc *vself,
     291                 :                                          size_t          *nbytes,
     292               0 :                                          size_t          *nhandles) {
     293               0 :   struct NaClDescImcShm  *self = (struct NaClDescImcShm *) vself;
     294                 :   int rv;
     295                 : 
     296               0 :   rv = NaClDescExternalizeSize(vself, nbytes, nhandles);
     297               0 :   if (0 != rv) {
     298               0 :     return rv;
     299                 :   }
     300               0 :   *nbytes += sizeof self->size;
     301               0 :   *nhandles += 1;
     302                 : 
     303               0 :   return 0;
     304               0 : }
     305                 : 
     306                 : static int NaClDescImcShmExternalize(struct NaClDesc           *vself,
     307               0 :                                      struct NaClDescXferState  *xfer) {
     308               0 :   struct NaClDescImcShm  *self = (struct NaClDescImcShm *) vself;
     309                 :   int rv;
     310                 : 
     311               0 :   rv = NaClDescExternalize(vself, xfer);
     312               0 :   if (0 != rv) {
     313               0 :     return rv;
     314                 :   }
     315               0 :   *xfer->next_handle++ = self->h;
     316               0 :   memcpy(xfer->next_byte, &self->size, sizeof self->size);
     317               0 :   xfer->next_byte += sizeof self->size;
     318               0 :   return 0;
     319               0 : }
     320                 : 
     321                 : static struct NaClDescVtbl const kNaClDescImcShmVtbl = {
     322                 :   {
     323                 :     NaClDescImcShmDtor,
     324                 :   },
     325                 :   NaClDescImcShmMap,
     326                 : #if NACL_WINDOWS
     327                 :   NaClDescImcShmUnmapUnsafe,
     328                 : #else
     329                 :   NACL_DESC_UNMAP_NOT_IMPLEMENTED
     330                 : #endif
     331                 :   NaClDescReadNotImplemented,
     332                 :   NaClDescWriteNotImplemented,
     333                 :   NaClDescSeekNotImplemented,
     334                 :   NaClDescPReadNotImplemented,
     335                 :   NaClDescPWriteNotImplemented,
     336                 :   NaClDescImcShmFstat,
     337                 :   NaClDescGetdentsNotImplemented,
     338                 :   NaClDescImcShmExternalizeSize,
     339                 :   NaClDescImcShmExternalize,
     340                 :   NaClDescLockNotImplemented,
     341                 :   NaClDescTryLockNotImplemented,
     342                 :   NaClDescUnlockNotImplemented,
     343                 :   NaClDescWaitNotImplemented,
     344                 :   NaClDescTimedWaitAbsNotImplemented,
     345                 :   NaClDescSignalNotImplemented,
     346                 :   NaClDescBroadcastNotImplemented,
     347                 :   NaClDescSendMsgNotImplemented,
     348                 :   NaClDescRecvMsgNotImplemented,
     349                 :   NaClDescLowLevelSendMsgNotImplemented,
     350                 :   NaClDescLowLevelRecvMsgNotImplemented,
     351                 :   NaClDescConnectAddrNotImplemented,
     352                 :   NaClDescAcceptConnNotImplemented,
     353                 :   NaClDescPostNotImplemented,
     354                 :   NaClDescSemWaitNotImplemented,
     355                 :   NaClDescGetValueNotImplemented,
     356                 :   NaClDescSetMetadata,
     357                 :   NaClDescGetMetadata,
     358                 :   NaClDescSetFlags,
     359                 :   NaClDescGetFlags,
     360                 :   NaClDescIsattyNotImplemented,
     361                 :   NACL_DESC_SHM,
     362                 : };
     363                 : 
     364                 : int NaClDescImcShmInternalize(struct NaClDesc               **out_desc,
     365                 :                               struct NaClDescXferState      *xfer,
     366               0 :                               struct NaClDescQuotaInterface *quota_interface) {
     367                 :   int                   rv;
     368                 :   struct NaClDescImcShm *ndisp;
     369                 :   NaClHandle            h;
     370                 :   nacl_off64_t          hsize;
     371                 : 
     372                 :   UNREFERENCED_PARAMETER(quota_interface);
     373               0 :   rv = -NACL_ABI_EIO;
     374                 : 
     375               0 :   ndisp = malloc(sizeof *ndisp);
     376               0 :   if (NULL == ndisp) {
     377               0 :     rv = -NACL_ABI_ENOMEM;
     378               0 :     goto cleanup;
     379                 :   }
     380               0 :   if (!NaClDescInternalizeCtor((struct NaClDesc *) ndisp, xfer)) {
     381               0 :     free(ndisp);
     382               0 :     ndisp = NULL;
     383               0 :     rv = -NACL_ABI_ENOMEM;
     384               0 :     goto cleanup;
     385                 :   }
     386                 : 
     387               0 :   if (xfer->next_handle == xfer->handle_buffer_end) {
     388               0 :     rv = -NACL_ABI_EIO;
     389               0 :     goto cleanup;
     390                 :   }
     391               0 :   if (xfer->next_byte + sizeof ndisp->size > xfer->byte_buffer_end) {
     392               0 :     rv = -NACL_ABI_EIO;
     393               0 :     goto cleanup;
     394                 :   }
     395                 : 
     396               0 :   h = *xfer->next_handle;
     397               0 :   *xfer->next_handle++ = NACL_INVALID_HANDLE;
     398               0 :   memcpy(&hsize, xfer->next_byte, sizeof hsize);
     399               0 :   xfer->next_byte += sizeof hsize;
     400                 : 
     401               0 :   if (!NaClDescImcShmSubclassCtor(ndisp, h, hsize)) {
     402               0 :     rv = -NACL_ABI_EIO;
     403               0 :     goto cleanup;
     404                 :   }
     405                 : 
     406               0 :   *out_desc = (struct NaClDesc *) ndisp;
     407               0 :   rv = 0;
     408                 : 
     409                 : cleanup:
     410               0 :   if (rv < 0) {
     411               0 :     NaClDescSafeUnref((struct NaClDesc *) ndisp);
     412                 :   }
     413               0 :   return rv;
     414               0 : }

Generated by: LCOV version 1.7