LCOV - code coverage report
Current view: directory - src/trusted/desc - nacl_desc_io.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 222 181 81.5 %
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.  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 <string.h>
      20                 : 
      21                 : #include "native_client/src/include/nacl_macros.h"
      22                 : #include "native_client/src/shared/imc/nacl_imc_c.h"
      23                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      24                 : #include "native_client/src/trusted/desc/nacl_desc_effector.h"
      25                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      26                 : 
      27                 : #include "native_client/src/shared/platform/nacl_find_addrsp.h"
      28                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      29                 : #include "native_client/src/shared/platform/nacl_log.h"
      30                 : 
      31                 : #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
      32                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      33                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      34                 : #include "native_client/src/trusted/service_runtime/internal_errno.h"
      35                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      36                 : 
      37                 : 
      38                 : /*
      39                 :  * This file contains the implementation for the NaClIoDesc subclass
      40                 :  * of NaClDesc.
      41                 :  *
      42                 :  * NaClDescIoDesc is the subclass that wraps host-OS descriptors
      43                 :  * provided by NaClHostDesc (which gives an OS-independent abstraction
      44                 :  * for host-OS descriptors).
      45                 :  */
      46                 : 
      47                 : static struct NaClDescVtbl const kNaClDescIoDescVtbl;  /* fwd */
      48                 : 
      49            1388 : static int NaClDescIoDescSubclassCtor(struct NaClDescIoDesc  *self,
      50            1388 :                                       struct NaClHostDesc    *hd) {
      51            1388 :   struct NaClDesc *basep = (struct NaClDesc *) self;
      52                 : 
      53            1388 :   self->hd = hd;
      54            1388 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) &kNaClDescIoDescVtbl;
      55            1388 :   return 1;
      56                 : }
      57                 : 
      58                 : /*
      59                 :  * Takes ownership of hd, will close in Dtor.
      60                 :  */
      61            1351 : int NaClDescIoDescCtor(struct NaClDescIoDesc  *self,
      62            1351 :                        struct NaClHostDesc    *hd) {
      63            1351 :   struct NaClDesc *basep = (struct NaClDesc *) self;
      64            1351 :   int rv;
      65                 : 
      66            1351 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) NULL;
      67            1351 :   if (!NaClDescCtor(basep)) {
      68               0 :     return 0;
      69                 :   }
      70            1351 :   rv = NaClDescIoDescSubclassCtor(self, hd);
      71            1351 :   if (!rv) {
      72               0 :     (*NACL_VTBL(NaClRefCount, basep)->Dtor)((struct NaClRefCount *) basep);
      73               0 :   }
      74            1351 :   (*NACL_VTBL(NaClDesc, basep)->
      75                 :    SetFlags)(basep, hd->flags & NACL_ABI_O_ACCMODE);
      76            1351 :   return rv;
      77            1351 : }
      78                 : 
      79             975 : static void NaClDescIoDescDtor(struct NaClRefCount *vself) {
      80             975 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
      81                 : 
      82             975 :   NaClLog(4, "NaClDescIoDescDtor(0x%08"NACL_PRIxPTR").\n",
      83                 :           (uintptr_t) vself);
      84             975 :   if (0 != NaClHostDescClose(self->hd)) {
      85               0 :     NaClLog(LOG_FATAL, "NaClDescIoDescDtor: NaClHostDescClose failed\n");
      86               0 :   }
      87             975 :   free(self->hd);
      88             975 :   self->hd = NULL;
      89             975 :   vself->vtbl = (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
      90             975 :   (*vself->vtbl->Dtor)(vself);
      91             975 : }
      92                 : 
      93            1349 : struct NaClDescIoDesc *NaClDescIoDescMake(struct NaClHostDesc *nhdp) {
      94            1349 :   struct NaClDescIoDesc *ndp;
      95                 : 
      96            1349 :   ndp = malloc(sizeof *ndp);
      97            1349 :   if (NULL == ndp) {
      98               0 :     NaClLog(LOG_FATAL,
      99                 :             "NaClDescIoDescMake: no memory for 0x%08"NACL_PRIxPTR"\n",
     100                 :             (uintptr_t) nhdp);
     101               0 :   }
     102            1349 :   if (!NaClDescIoDescCtor(ndp, nhdp)) {
     103               0 :     NaClLog(LOG_FATAL,
     104                 :             ("NaClDescIoDescMake:"
     105                 :              " NaClDescIoDescCtor(0x%08"NACL_PRIxPTR",0x%08"NACL_PRIxPTR
     106                 :              ") failed\n"),
     107                 :             (uintptr_t) ndp,
     108                 :             (uintptr_t) nhdp);
     109               0 :   }
     110            1349 :   return ndp;
     111                 : }
     112                 : 
     113              14 : struct NaClDesc *NaClDescIoDescFromHandleAllocCtor(NaClHandle handle,
     114              14 :                                                    int flags) {
     115              14 :   int posix_d;
     116                 : 
     117                 : #if NACL_WINDOWS
     118                 :   int win_flags = 0;
     119                 : 
     120                 :   switch (flags & NACL_ABI_O_ACCMODE) {
     121                 :     case NACL_ABI_O_RDONLY:
     122                 :       win_flags = _O_RDONLY | _O_BINARY;
     123                 :       break;
     124                 :     case NACL_ABI_O_WRONLY:
     125                 :       win_flags = _O_WRONLY | _O_BINARY;
     126                 :       break;
     127                 :     case NACL_ABI_O_RDWR:
     128                 :       win_flags = _O_RDWR | _O_BINARY;
     129                 :       break;
     130                 :   }
     131                 :   if (0 == win_flags) {
     132                 :     return NULL;
     133                 :   }
     134                 :   posix_d = _open_osfhandle((intptr_t) handle, win_flags);
     135                 :   if (-1 == posix_d) {
     136                 :     return NULL;
     137                 :   }
     138                 : #else
     139              14 :   posix_d = handle;
     140                 : #endif
     141              14 :   return NaClDescIoDescFromDescAllocCtor(posix_d, flags);
     142                 : }
     143                 : 
     144              22 : struct NaClDesc *NaClDescIoDescFromDescAllocCtor(int desc,
     145              22 :                                                  int flags) {
     146              22 :   struct NaClHostDesc *nhdp;
     147                 : 
     148              22 :   nhdp = NaClHostDescPosixMake(desc, flags);
     149              22 :   if (NULL == nhdp) {
     150                 :     /*
     151                 :      * BUG: In Windows, we leak posix_d representation in the POSIX
     152                 :      * layer, since caller will continue to own |handle| on a failure
     153                 :      * return, but we cannot close |posix_d| without implicitly
     154                 :      * invoking CloseHandle on |handle|.
     155                 :      */
     156               0 :     return NULL;
     157                 :   }
     158              22 :   return (struct NaClDesc *) NaClDescIoDescMake(nhdp);
     159              22 : }
     160                 : 
     161             294 : struct NaClDescIoDesc *NaClDescIoDescOpen(char const *path,
     162             294 :                                           int mode,
     163             294 :                                           int perms) {
     164             294 :   struct NaClHostDesc *nhdp;
     165                 : 
     166             294 :   nhdp = malloc(sizeof *nhdp);
     167             294 :   if (NULL == nhdp) {
     168               0 :     NaClLog(LOG_FATAL, "NaClDescIoDescOpen: no memory for %s\n", path);
     169               0 :   }
     170             294 :   if (0 != NaClHostDescOpen(nhdp, path, mode, perms)) {
     171               1 :     NaClLog(4,
     172                 :             "NaClDescIoDescOpen: NaClHostDescOpen failed for %s\n",
     173                 :             path);
     174               1 :     return NULL;
     175                 :   }
     176             293 :   return NaClDescIoDescMake(nhdp);
     177             294 : }
     178                 : 
     179           71487 : static uintptr_t NaClDescIoDescMap(struct NaClDesc         *vself,
     180           71487 :                                    struct NaClDescEffector *effp,
     181           71487 :                                    void                    *start_addr,
     182           71487 :                                    size_t                  len,
     183           71487 :                                    int                     prot,
     184           71487 :                                    int                     flags,
     185           71487 :                                    nacl_off64_t            offset) {
     186           71487 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     187           71487 :   uintptr_t             status;
     188           71487 :   uintptr_t             addr;
     189                 : 
     190                 :   /*
     191                 :    * prot must only contain NACL_ABI_PROT_* flags.
     192                 :    */
     193           71487 :   if (0 != (~(NACL_ABI_PROT_MASK) & prot)) {
     194               0 :     NaClLog(LOG_INFO,
     195                 :             ("NaClDescIoDescMap: prot has other bits"
     196                 :              " than NACL_ABI_PROT_{READ|WRITE|EXEC}\n"));
     197               0 :     return -NACL_ABI_EINVAL;
     198                 :   }
     199                 : 
     200           71487 :   if (0 == (NACL_ABI_MAP_FIXED & flags)) {
     201              19 :     if (!NaClFindAddressSpace(&addr, len)) {
     202               0 :       NaClLog(1, "NaClDescIoDescMap: no address space?\n");
     203               0 :       return -NACL_ABI_ENOMEM;
     204                 :     }
     205              19 :     NaClLog(4,
     206                 :             "NaClDescIoDescMap: NaClFindAddressSpace"
     207                 :             " returned 0x%"NACL_PRIxPTR"\n",
     208                 :             addr);
     209              19 :     start_addr = (void *) addr;
     210              19 :   }
     211           71487 :   flags |= NACL_ABI_MAP_FIXED;
     212                 : 
     213          214461 :   status = NaClHostDescMap((NULL == self) ? NULL : self->hd,
     214                 :                            effp,
     215                 :                            (void *) start_addr,
     216                 :                            len,
     217                 :                            prot,
     218                 :                            flags,
     219                 :                            offset);
     220           71487 :   NaClLog(4, "NaClDescIoDescMap returning %"NACL_PRIxPTR"\n", status);
     221           71487 :   return status;
     222           71487 : }
     223                 : 
     224           71420 : uintptr_t NaClDescIoDescMapAnon(struct NaClDescEffector *effp,
     225           71420 :                                 void                    *start_addr,
     226           71420 :                                 size_t                  len,
     227           71420 :                                 int                     prot,
     228           71420 :                                 int                     flags,
     229           71420 :                                 nacl_off64_t            offset) {
     230           71420 :   return NaClDescIoDescMap((struct NaClDesc *) NULL, effp, start_addr, len,
     231                 :                            prot, flags, offset);
     232                 : }
     233                 : 
     234                 : #if NACL_WINDOWS
     235                 : static int NaClDescIoDescUnmapUnsafe(struct NaClDesc  *vself,
     236                 :                                      void             *start_addr,
     237                 :                                      size_t           len) {
     238                 :   UNREFERENCED_PARAMETER(vself);
     239                 :   return NaClHostDescUnmapUnsafe(start_addr, len);
     240                 : }
     241                 : #endif
     242                 : 
     243             155 : static ssize_t NaClDescIoDescRead(struct NaClDesc          *vself,
     244             155 :                                   void                     *buf,
     245             155 :                                   size_t                   len) {
     246             155 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     247                 : 
     248             155 :   return NaClHostDescRead(self->hd, buf, len);
     249                 : }
     250                 : 
     251           58568 : static ssize_t NaClDescIoDescWrite(struct NaClDesc         *vself,
     252           58568 :                                    void const              *buf,
     253           58568 :                                    size_t                  len) {
     254           58568 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     255                 : 
     256           58568 :   return NaClHostDescWrite(self->hd, buf, len);
     257                 : }
     258                 : 
     259            6752 : static nacl_off64_t NaClDescIoDescSeek(struct NaClDesc          *vself,
     260            6752 :                                        nacl_off64_t             offset,
     261            6752 :                                        int                      whence) {
     262            6752 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     263                 : 
     264            6752 :   return NaClHostDescSeek(self->hd, offset, whence);
     265                 : }
     266                 : 
     267            1480 : static ssize_t NaClDescIoDescPRead(struct NaClDesc *vself,
     268            1480 :                                    void *buf,
     269            1480 :                                    size_t len,
     270            1480 :                                    nacl_off64_t offset) {
     271            1480 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     272                 : 
     273            1480 :   return NaClHostDescPRead(self->hd, buf, len, offset);
     274                 : }
     275                 : 
     276              10 : static ssize_t NaClDescIoDescPWrite(struct NaClDesc *vself,
     277              10 :                                     void const *buf,
     278              10 :                                     size_t len,
     279              10 :                                     nacl_off64_t offset) {
     280              10 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     281                 : 
     282              10 :   return NaClHostDescPWrite(self->hd, buf, len, offset);
     283                 : }
     284                 : 
     285             237 : static int NaClDescIoDescFstat(struct NaClDesc         *vself,
     286             237 :                                struct nacl_abi_stat    *statbuf) {
     287             237 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     288             237 :   int                   rv;
     289             237 :   nacl_host_stat_t      hstatbuf;
     290                 : 
     291             237 :   rv = NaClHostDescFstat(self->hd, &hstatbuf);
     292             237 :   if (0 != rv) {
     293               0 :     return rv;
     294                 :   }
     295             237 :   return NaClAbiStatHostDescStatXlateCtor(statbuf, &hstatbuf);
     296             237 : }
     297                 : 
     298               2 : static int32_t NaClDescIoIsatty(struct NaClDesc *vself) {
     299               2 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     300                 : 
     301               2 :   return NaClHostDescIsatty(self->hd);
     302                 : }
     303                 : 
     304              49 : static int NaClDescIoDescExternalizeSize(struct NaClDesc *vself,
     305              49 :                                          size_t          *nbytes,
     306              49 :                                          size_t          *nhandles) {
     307              49 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     308              49 :   int rv;
     309                 : 
     310              49 :   rv = NaClDescExternalizeSize(vself, nbytes, nhandles);
     311              49 :   if (0 != rv) {
     312               0 :     return rv;
     313                 :   }
     314              49 :   *nhandles += 1;
     315              49 :   *nbytes += sizeof self->hd->flags;
     316                 :   /* For Windows, we do not need to send flProtect since it is a cache */
     317              49 :   return 0;
     318              49 : }
     319                 : 
     320              49 : static int NaClDescIoDescExternalize(struct NaClDesc           *vself,
     321              49 :                                      struct NaClDescXferState  *xfer) {
     322              49 :   struct NaClDescIoDesc *self = (struct NaClDescIoDesc *) vself;
     323              49 :   int rv;
     324                 : #if NACL_WINDOWS
     325                 :   HANDLE  h;
     326                 : #endif
     327                 : 
     328              49 :   rv = NaClDescExternalize(vself, xfer);
     329              49 :   if (0 != rv) {
     330               0 :     return rv;
     331                 :   }
     332                 : 
     333             147 :   memcpy(xfer->next_byte, &self->hd->flags, sizeof self->hd->flags);
     334              49 :   xfer->next_byte += sizeof self->hd->flags;
     335                 : #if NACL_WINDOWS
     336                 :   h = (HANDLE) _get_osfhandle(self->hd->d);
     337                 :   *xfer->next_handle++ = (NaClHandle) h;
     338                 : #else
     339              49 :   *xfer->next_handle++ = self->hd->d;
     340                 : #endif
     341              49 :   return 0;
     342              49 : }
     343                 : 
     344                 : static struct NaClDescVtbl const kNaClDescIoDescVtbl = {
     345                 :   {
     346                 :     NaClDescIoDescDtor,
     347                 :   },
     348                 :   NaClDescIoDescMap,
     349                 : #if NACL_WINDOWS
     350                 :   NaClDescIoDescUnmapUnsafe,
     351                 : #else
     352                 :   NACL_DESC_UNMAP_NOT_IMPLEMENTED
     353                 : #endif
     354                 :   NaClDescIoDescRead,
     355                 :   NaClDescIoDescWrite,
     356                 :   NaClDescIoDescSeek,
     357                 :   NaClDescIoDescPRead,
     358                 :   NaClDescIoDescPWrite,
     359                 :   NaClDescIoDescFstat,
     360                 :   NaClDescGetdentsNotImplemented,
     361                 :   NaClDescIoDescExternalizeSize,
     362                 :   NaClDescIoDescExternalize,
     363                 :   NaClDescLockNotImplemented,
     364                 :   NaClDescTryLockNotImplemented,
     365                 :   NaClDescUnlockNotImplemented,
     366                 :   NaClDescWaitNotImplemented,
     367                 :   NaClDescTimedWaitAbsNotImplemented,
     368                 :   NaClDescSignalNotImplemented,
     369                 :   NaClDescBroadcastNotImplemented,
     370                 :   NaClDescSendMsgNotImplemented,
     371                 :   NaClDescRecvMsgNotImplemented,
     372                 :   NaClDescLowLevelSendMsgNotImplemented,
     373                 :   NaClDescLowLevelRecvMsgNotImplemented,
     374                 :   NaClDescConnectAddrNotImplemented,
     375                 :   NaClDescAcceptConnNotImplemented,
     376                 :   NaClDescPostNotImplemented,
     377                 :   NaClDescSemWaitNotImplemented,
     378                 :   NaClDescGetValueNotImplemented,
     379                 :   NaClDescSetMetadata,
     380                 :   NaClDescGetMetadata,
     381                 :   NaClDescSetFlags,
     382                 :   NaClDescGetFlags,
     383                 :   NaClDescIoIsatty,
     384                 :   NACL_DESC_HOST_IO,
     385                 : };
     386                 : 
     387                 : /* set *out_desc to struct NaClDescIo * output */
     388              38 : int NaClDescIoInternalize(struct NaClDesc               **out_desc,
     389              38 :                           struct NaClDescXferState      *xfer,
     390              38 :                           struct NaClDescQuotaInterface *quota_interface) {
     391              38 :   int                   rv;
     392              38 :   NaClHandle            h;
     393              38 :   int                   d;
     394              38 :   int                   flags;
     395              38 :   struct NaClHostDesc   *nhdp;
     396              38 :   struct NaClDescIoDesc *ndidp;
     397                 : 
     398              76 :   UNREFERENCED_PARAMETER(quota_interface);
     399              38 :   rv = -NACL_ABI_EIO;  /* catch-all */
     400              38 :   h = NACL_INVALID_HANDLE;
     401              38 :   nhdp = NULL;
     402              38 :   ndidp = NULL;
     403                 : 
     404              38 :   nhdp = malloc(sizeof *nhdp);
     405              38 :   if (NULL == nhdp) {
     406               0 :     rv = -NACL_ABI_ENOMEM;
     407               0 :     goto cleanup;
     408                 :   }
     409              38 :   ndidp = malloc(sizeof *ndidp);
     410              38 :   if (!ndidp) {
     411               0 :     rv = -NACL_ABI_ENOMEM;
     412               0 :     goto cleanup;
     413                 :   }
     414              38 :   if (!NaClDescInternalizeCtor((struct NaClDesc *) ndidp, xfer)) {
     415               0 :     rv = -NACL_ABI_ENOMEM;
     416               0 :     goto cleanup;
     417                 :   }
     418              76 :   if (xfer->next_handle == xfer->handle_buffer_end ||
     419                 :       xfer->next_byte + sizeof ndidp->hd->flags > xfer->byte_buffer_end) {
     420               0 :     rv = -NACL_ABI_EIO;
     421               0 :     goto cleanup_ndidp_dtor;
     422                 :   }
     423                 : 
     424              76 :   NACL_COMPILE_TIME_ASSERT(sizeof flags == sizeof(ndidp->hd->flags));
     425              38 :   memcpy(&flags, xfer->next_byte, sizeof flags);
     426              38 :   xfer->next_byte += sizeof flags;
     427                 : 
     428              38 :   h = *xfer->next_handle;
     429              38 :   *xfer->next_handle++ = NACL_INVALID_HANDLE;
     430                 : #if NACL_WINDOWS
     431                 :   if (-1 == (d = _open_osfhandle((intptr_t) h, _O_RDWR | _O_BINARY))) {
     432                 :     rv = -NACL_ABI_EIO;
     433                 :     goto cleanup_ndidp_dtor;
     434                 :   }
     435                 : #else
     436              38 :   d = h;
     437                 : #endif
     438                 :   /*
     439                 :    * We mark it as read/write, but don't really know for sure until we
     440                 :    * try to make those syscalls (in which case we'd get EBADF).
     441                 :    */
     442              38 :   if ((rv = NaClHostDescPosixTake(nhdp, d, flags)) < 0) {
     443               0 :     goto cleanup_ndidp_dtor;
     444                 :   }
     445              38 :   h = NACL_INVALID_HANDLE;  /* nhdp took ownership of h */
     446                 : 
     447              38 :   if (!NaClDescIoDescSubclassCtor(ndidp, nhdp)) {
     448               0 :     rv = -NACL_ABI_ENOMEM;
     449               0 :     goto cleanup_nhdp_dtor;
     450                 :   }
     451                 :   /*
     452                 :    * ndidp took ownership of nhdp, now give ownership of ndidp to caller.
     453                 :    */
     454              38 :   *out_desc = (struct NaClDesc *) ndidp;
     455              38 :   rv = 0;
     456                 :  cleanup_nhdp_dtor:
     457              38 :   if (rv < 0) {
     458               0 :     if (0 != NaClHostDescClose(nhdp)) {
     459               0 :       NaClLog(LOG_FATAL, "NaClDescIoInternalize: NaClHostDescClose failed\n");
     460               0 :     }
     461              38 :   }
     462                 :  cleanup_ndidp_dtor:
     463              38 :   if (rv < 0) {
     464               0 :     NaClDescSafeUnref((struct NaClDesc *) ndidp);
     465               0 :     ndidp = NULL;
     466              38 :   }
     467                 :  cleanup:
     468              38 :   if (rv < 0) {
     469               0 :     free(nhdp);
     470               0 :     free(ndidp);
     471               0 :     if (NACL_INVALID_HANDLE != h) {
     472               0 :       (void) NaClClose(h);
     473               0 :     }
     474               0 :   }
     475              38 :   return rv;
     476                 : }

Generated by: LCOV version 1.7