LCOV - code coverage report
Current view: directory - src/trusted/desc - nacl_desc_io.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 130 88 67.7 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 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.  I/O Descriptor / Handle abstraction.  Memory
       9                 :  * mapping using descriptors.
      10                 :  */
      11                 : 
      12                 : #include "native_client/src/include/portability.h"
      13                 : 
      14                 : #if NACL_WINDOWS
      15                 : # include "io.h"
      16                 : # include "fcntl.h"
      17                 : #endif
      18                 : 
      19                 : #include "native_client/src/shared/imc/nacl_imc_c.h"
      20                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      21                 : #include "native_client/src/trusted/desc/nacl_desc_effector.h"
      22                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      23                 : 
      24                 : #include "native_client/src/shared/platform/nacl_find_addrsp.h"
      25                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      26                 : #include "native_client/src/shared/platform/nacl_log.h"
      27                 : 
      28                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      29                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      30                 : #include "native_client/src/trusted/service_runtime/include/sys/mman.h"
      31                 : #include "native_client/src/trusted/service_runtime/internal_errno.h"
      32                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      33                 : 
      34                 : 
      35                 : /*
      36                 :  * This file contains the implementation for the NaClIoDesc subclass
      37                 :  * of NaClDesc.
      38                 :  *
      39                 :  * NaClDescIoDesc is the subclass that wraps host-OS descriptors
      40                 :  * provided by NaClHostDesc (which gives an OS-independent abstraction
      41                 :  * for host-OS descriptors).
      42                 :  */
      43                 : 
      44                 : static struct NaClDescVtbl const kNaClDescIoDescVtbl;  /* fwd */
      45                 : /*
      46                 :  * Takes ownership of hd, will close in Dtor.
      47                 :  */
      48                 : int NaClDescIoDescCtor(struct NaClDescIoDesc  *self,
      49              94 :                        struct NaClHostDesc    *hd) {
      50              94 :   struct NaClDesc *basep = (struct NaClDesc *) self;
      51                 : 
      52              94 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) NULL;
      53              94 :   if (!NaClDescCtor(basep)) {
      54               0 :     return 0;
      55                 :   }
      56              94 :   self->hd = hd;
      57              94 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) &kNaClDescIoDescVtbl;
      58              94 :   return 1;
      59                 : }
      60                 : 
      61              33 : static void NaClDescIoDescDtor(struct NaClRefCount *vself) {
      62              33 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
      63                 : 
      64              33 :   NaClLog(4, "NaClDescIoDescDtor(0x%08"NACL_PRIxPTR").\n",
      65                 :           (uintptr_t) vself);
      66              33 :   NaClHostDescClose(self->hd);
      67              33 :   free(self->hd);
      68              33 :   self->hd = NULL;
      69              33 :   vself->vtbl = (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
      70              33 :   (*vself->vtbl->Dtor)(vself);
      71              33 : }
      72                 : 
      73              93 : struct NaClDescIoDesc *NaClDescIoDescMake(struct NaClHostDesc *nhdp) {
      74                 :   struct NaClDescIoDesc *ndp;
      75                 : 
      76              93 :   ndp = malloc(sizeof *ndp);
      77              93 :   if (NULL == ndp) {
      78               0 :     NaClLog(LOG_FATAL,
      79                 :             "NaClDescIoDescMake: no memory for 0x%08"NACL_PRIxPTR"\n",
      80                 :             (uintptr_t) nhdp);
      81                 :   }
      82              93 :   if (!NaClDescIoDescCtor(ndp, nhdp)) {
      83               0 :     NaClLog(LOG_FATAL,
      84                 :             ("NaClDescIoDescMake:"
      85                 :              " NaClDescIoDescCtor(0x%08"NACL_PRIxPTR",0x%08"NACL_PRIxPTR
      86                 :              ") failed\n"),
      87                 :             (uintptr_t) ndp,
      88                 :             (uintptr_t) nhdp);
      89                 :   }
      90              93 :   return ndp;
      91                 : }
      92                 : 
      93                 : struct NaClDescIoDesc *NaClDescIoDescOpen(char  *path,
      94                 :                                           int   mode,
      95               4 :                                           int   perms) {
      96                 :   struct NaClHostDesc *nhdp;
      97                 : 
      98               4 :   nhdp = malloc(sizeof *nhdp);
      99               4 :   if (NULL == nhdp) {
     100               0 :     NaClLog(LOG_FATAL, "NaClDescIoDescOpen: no memory for %s\n", path);
     101                 :   }
     102               4 :   if (0 != NaClHostDescOpen(nhdp, path, mode, perms)) {
     103               0 :     NaClLog(LOG_FATAL, "NaClDescIoDescOpen: NaClHostDescOpen failed for %s\n",
     104                 :             path);
     105                 :   }
     106               4 :   return NaClDescIoDescMake(nhdp);
     107                 : }
     108                 : 
     109                 : static uintptr_t NaClDescIoDescMap(struct NaClDesc         *vself,
     110                 :                                    struct NaClDescEffector *effp,
     111                 :                                    void                    *start_addr,
     112                 :                                    size_t                  len,
     113                 :                                    int                     prot,
     114                 :                                    int                     flags,
     115               3 :                                    nacl_off64_t            offset) {
     116               3 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     117                 :   int                   rv;
     118                 :   uintptr_t             status;
     119                 :   uintptr_t             addr;
     120                 :   uintptr_t             end_addr;
     121                 :   nacl_off64_t          tmp_off;
     122                 : 
     123                 :   /*
     124                 :    * prot must be PROT_NONE or a combination of PROT_{READ|WRITE}
     125                 :    */
     126               3 :   if (0 != (~(NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE) & prot)) {
     127               0 :     NaClLog(LOG_INFO,
     128                 :             ("NaClDescIoDescMap: prot has other bits"
     129                 :              " than PROT_{READ|WRITE}\n"));
     130               0 :     return -NACL_ABI_EINVAL;
     131                 :   }
     132                 : 
     133               3 :   if (0 == (NACL_ABI_MAP_FIXED & flags) && NULL == start_addr) {
     134               0 :     NaClLog(LOG_INFO,
     135                 :             ("NaClDescIoDescMap: Mapping not NACL_ABI_MAP_FIXED"
     136                 :              " but start_addr is NULL\n"));
     137                 :   }
     138                 : 
     139               3 :   if (0 == (NACL_ABI_MAP_FIXED & flags)) {
     140               0 :     if (!NaClFindAddressSpace(&addr, len)) {
     141               0 :       NaClLog(1, "NaClDescIoDescMap: no address space?\n");
     142               0 :       return -NACL_ABI_ENOMEM;
     143                 :     }
     144               0 :     start_addr = (void *) addr;
     145                 :   }
     146               3 :   flags |= NACL_ABI_MAP_FIXED;
     147                 : 
     148                 :   for (addr = (uintptr_t) start_addr,
     149                 :            end_addr = addr + len,
     150               3 :            tmp_off = offset;
     151               9 :        addr < end_addr;
     152                 :        addr += NACL_MAP_PAGESIZE,
     153               3 :            tmp_off += NACL_MAP_PAGESIZE) {
     154                 :     size_t map_size;
     155                 : 
     156               3 :     if (0 != (rv = (*effp->vtbl->UnmapMemory)(effp,
     157                 :                                               addr,
     158                 :                                               NACL_MAP_PAGESIZE))) {
     159               0 :       NaClLog(LOG_FATAL,
     160                 :               ("NaClDescIoDescMap: error %d --"
     161                 :                " could not unmap 0x%08"NACL_PRIxPTR
     162                 :                ", length 0x%"NACL_PRIxS"\n"),
     163                 :               rv,
     164                 :               addr,
     165                 :               (size_t) NACL_MAP_PAGESIZE);
     166                 :     }
     167                 : 
     168               3 :     map_size = end_addr - addr;
     169               3 :     if (map_size > NACL_MAP_PAGESIZE) {
     170               0 :       map_size = NACL_MAP_PAGESIZE;
     171                 :     }
     172               3 :     status = NaClHostDescMap((NULL == self) ? NULL : self->hd,
     173                 :                              (void *) addr,
     174                 :                              map_size,
     175                 :                              prot,
     176                 :                              flags,
     177                 :                              tmp_off);
     178               3 :     if (NACL_MAP_FAILED == (void *) status) {
     179               0 :       return -NACL_ABI_E_MOVE_ADDRESS_SPACE;
     180                 :     }
     181                 :   }
     182               3 :   return (uintptr_t) start_addr;
     183                 : }
     184                 : 
     185                 : uintptr_t NaClDescIoDescMapAnon(struct NaClDescEffector *effp,
     186                 :                                 void                    *start_addr,
     187                 :                                 size_t                  len,
     188                 :                                 int                     prot,
     189                 :                                 int                     flags,
     190               2 :                                 nacl_off64_t            offset) {
     191               2 :   return NaClDescIoDescMap((struct NaClDesc *) NULL, effp, start_addr, len,
     192                 :                            prot, flags, offset);
     193                 : }
     194                 : 
     195                 : static int NaClDescIoDescUnmapCommon(struct NaClDesc         *vself,
     196                 :                                      struct NaClDescEffector *effp,
     197                 :                                      void                    *start_addr,
     198                 :                                      size_t                  len,
     199               0 :                                      int                     safe_mode) {
     200                 :   int status;
     201                 : 
     202                 :   UNREFERENCED_PARAMETER(vself);
     203                 :   UNREFERENCED_PARAMETER(effp);
     204                 : 
     205               0 :   if (safe_mode) {
     206               0 :     status = NaClHostDescUnmap(start_addr, len);
     207                 :   } else {
     208               0 :     status = NaClHostDescUnmapUnsafe(start_addr, len);
     209                 :   }
     210                 : 
     211               0 :   return status;
     212                 : }
     213                 : 
     214                 : /*
     215                 :  * NB: User code should never be able to invoke the Unsafe method.
     216                 :  */
     217                 : static int NaClDescIoDescUnmapUnsafe(struct NaClDesc         *vself,
     218                 :                                      struct NaClDescEffector *effp,
     219                 :                                      void                    *start_addr,
     220               0 :                                      size_t                  len) {
     221               0 :   return NaClDescIoDescUnmapCommon(vself, effp, start_addr, len, 0);
     222                 : }
     223                 : 
     224                 : static int NaClDescIoDescUnmap(struct NaClDesc         *vself,
     225                 :                                struct NaClDescEffector *effp,
     226                 :                                void                    *start_addr,
     227               0 :                                size_t                  len) {
     228               0 :   return NaClDescIoDescUnmapCommon(vself, effp, start_addr, len, 1);
     229                 : }
     230                 : 
     231                 : static ssize_t NaClDescIoDescRead(struct NaClDesc          *vself,
     232                 :                                   void                     *buf,
     233             116 :                                   size_t                   len) {
     234             116 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     235                 : 
     236             116 :   return NaClHostDescRead(self->hd, buf, len);
     237                 : }
     238                 : 
     239                 : static ssize_t NaClDescIoDescWrite(struct NaClDesc         *vself,
     240                 :                                    void const              *buf,
     241            6805 :                                    size_t                  len) {
     242            6805 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     243                 : 
     244            6805 :   return NaClHostDescWrite(self->hd, buf, len);
     245                 : }
     246                 : 
     247                 : static nacl_off64_t NaClDescIoDescSeek(struct NaClDesc          *vself,
     248                 :                                        nacl_off64_t             offset,
     249            6700 :                                        int                      whence) {
     250            6700 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     251                 : 
     252            6700 :   return NaClHostDescSeek(self->hd, offset, whence);
     253                 : }
     254                 : 
     255                 : static int NaClDescIoDescIoctl(struct NaClDesc         *vself,
     256                 :                                int                     request,
     257               0 :                                void                    *arg) {
     258               0 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     259                 : 
     260               0 :   return NaClHostDescIoctl(self->hd, request, arg);
     261                 : }
     262                 : 
     263                 : static int NaClDescIoDescFstat(struct NaClDesc         *vself,
     264               6 :                                struct nacl_abi_stat    *statbuf) {
     265               6 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     266                 :   int                   rv;
     267                 :   nacl_host_stat_t      hstatbuf;
     268                 : 
     269               6 :   rv = NaClHostDescFstat(self->hd, &hstatbuf);
     270               6 :   if (0 != rv) {
     271               0 :     return rv;
     272                 :   }
     273               6 :   return NaClAbiStatHostDescStatXlateCtor(statbuf, &hstatbuf);
     274                 : }
     275                 : 
     276                 : static int NaClDescIoDescExternalizeSize(struct NaClDesc *vself,
     277                 :                                          size_t          *nbytes,
     278              13 :                                          size_t          *nhandles) {
     279                 :   UNREFERENCED_PARAMETER(vself);
     280                 : 
     281              13 :   *nbytes = 0;
     282              13 :   *nhandles = 1;
     283              13 :   return 0;
     284                 : }
     285                 : 
     286                 : static int NaClDescIoDescExternalize(struct NaClDesc           *vself,
     287              13 :                                      struct NaClDescXferState  *xfer) {
     288              13 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     289                 : 
     290                 : #if NACL_WINDOWS
     291                 :   HANDLE  h = (HANDLE) _get_osfhandle(self->hd->d);
     292                 : 
     293                 :   NaClLog(LOG_WARNING, "NaClDescIoDescExternalize is EXPERIMENTAL\n");
     294                 :   NaClLog(LOG_WARNING, "handle 0x%x\n", (uintptr_t) h);
     295                 : 
     296                 :   *xfer->next_handle++ = (NaClHandle) h;
     297                 : #else
     298              13 :   *xfer->next_handle++ = self->hd->d;
     299                 : #endif
     300              13 :   return 0;
     301                 : }
     302                 : 
     303                 : static struct NaClDescVtbl const kNaClDescIoDescVtbl = {
     304                 :   {
     305                 :     NaClDescIoDescDtor,
     306                 :   },
     307                 :   NaClDescIoDescMap,
     308                 :   NaClDescIoDescUnmapUnsafe,
     309                 :   NaClDescIoDescUnmap,
     310                 :   NaClDescIoDescRead,
     311                 :   NaClDescIoDescWrite,
     312                 :   NaClDescIoDescSeek,
     313                 :   NaClDescIoDescIoctl,
     314                 :   NaClDescIoDescFstat,
     315                 :   NaClDescGetdentsNotImplemented,
     316                 :   NACL_DESC_HOST_IO,
     317                 :   NaClDescIoDescExternalizeSize,
     318                 :   NaClDescIoDescExternalize,
     319                 :   NaClDescLockNotImplemented,
     320                 :   NaClDescTryLockNotImplemented,
     321                 :   NaClDescUnlockNotImplemented,
     322                 :   NaClDescWaitNotImplemented,
     323                 :   NaClDescTimedWaitAbsNotImplemented,
     324                 :   NaClDescSignalNotImplemented,
     325                 :   NaClDescBroadcastNotImplemented,
     326                 :   NaClDescSendMsgNotImplemented,
     327                 :   NaClDescRecvMsgNotImplemented,
     328                 :   NaClDescConnectAddrNotImplemented,
     329                 :   NaClDescAcceptConnNotImplemented,
     330                 :   NaClDescPostNotImplemented,
     331                 :   NaClDescSemWaitNotImplemented,
     332                 :   NaClDescGetValueNotImplemented,
     333                 : };
     334                 : 
     335                 : /* set *out_desc to struct NaClDescIo * output */
     336                 : int NaClDescIoInternalize(struct NaClDesc               **out_desc,
     337                 :                           struct NaClDescXferState      *xfer,
     338               1 :                           struct NaClDescQuotaInterface *quota_interface) {
     339                 :   int                   rv;
     340                 :   NaClHandle            h;
     341                 :   int                   d;
     342                 :   struct NaClHostDesc   *nhdp;
     343                 :   struct NaClDescIoDesc *ndidp;
     344                 : 
     345                 :   UNREFERENCED_PARAMETER(quota_interface);
     346               1 :   rv = -NACL_ABI_EIO;  /* catch-all */
     347               1 :   h = NACL_INVALID_HANDLE;
     348               1 :   nhdp = NULL;
     349               1 :   ndidp = NULL;
     350                 : 
     351               1 :   if (xfer->next_handle == xfer->handle_buffer_end) {
     352               0 :     rv = -NACL_ABI_EIO;
     353               0 :     goto cleanup;
     354                 :   }
     355               1 :   nhdp = malloc(sizeof *nhdp);
     356               1 :   if (NULL == nhdp) {
     357               0 :     rv = -NACL_ABI_ENOMEM;
     358               0 :     goto cleanup;
     359                 :   }
     360               1 :   ndidp = malloc(sizeof *ndidp);
     361               1 :   if (!ndidp) {
     362               0 :     rv = -NACL_ABI_ENOMEM;
     363               0 :     goto cleanup;
     364                 :   }
     365               1 :   h = *xfer->next_handle;
     366               1 :   *xfer->next_handle++ = NACL_INVALID_HANDLE;
     367                 : #if NACL_WINDOWS
     368                 :   if (-1 == (d = _open_osfhandle((intptr_t) h, _O_RDWR | _O_BINARY))) {
     369                 :     rv = -NACL_ABI_EIO;
     370                 :     goto cleanup;
     371                 :   }
     372                 : #else
     373               1 :   d = h;
     374                 : #endif
     375                 :   /*
     376                 :    * We mark it as read/write, but don't really know for sure until we
     377                 :    * try to make those syscalls (in which case we'd get EBADF).
     378                 :    */
     379               1 :   if ((rv = NaClHostDescPosixTake(nhdp, d, NACL_ABI_O_RDWR)) < 0) {
     380               0 :     goto cleanup;
     381                 :   }
     382               1 :   h = NACL_INVALID_HANDLE;  /* nhdp took ownership of h */
     383                 : 
     384               1 :   if (!NaClDescIoDescCtor(ndidp, nhdp)) {
     385               0 :     rv = -NACL_ABI_ENOMEM;
     386               0 :     goto cleanup_hd_dtor;
     387                 :   }
     388                 :   /*
     389                 :    * ndidp took ownership of nhdp, now give ownership of ndidp to caller.
     390                 :    */
     391               1 :   *out_desc = (struct NaClDesc *) ndidp;
     392               1 :   rv = 0;
     393               1 : cleanup_hd_dtor:
     394               1 :   if (rv < 0) {
     395               0 :     (void) NaClHostDescClose(nhdp);
     396                 :   }
     397               1 : cleanup:
     398               1 :   if (rv < 0) {
     399               0 :     free(nhdp);
     400               0 :     free(ndidp);
     401               0 :     if (NACL_INVALID_HANDLE != h) {
     402               0 :       (void) NaClClose(h);
     403                 :     }
     404                 :   }
     405               1 :   return rv;
     406                 : }

Generated by: LCOV version 1.7