LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sys_fdio.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 243 207 85.2 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2013 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                 : #include "native_client/src/trusted/service_runtime/sys_fdio.h"
       8                 : 
       9                 : #include <string.h>
      10                 : 
      11                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      12                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      13                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      14                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      15                 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
      16                 : #include "native_client/src/trusted/service_runtime/nacl_copy.h"
      17                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
      18                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      19                 : 
      20                 : 
      21                 : static size_t const kdefault_io_buffer_bytes_to_log = 64;
      22                 : 
      23              10 : int32_t NaClSysDup(struct NaClAppThread *natp,
      24              10 :                    int                  oldfd) {
      25              10 :   struct NaClApp  *nap = natp->nap;
      26              10 :   int             retval;
      27              10 :   struct NaClDesc *old_nd;
      28                 : 
      29              10 :   NaClLog(3, "NaClSysDup(0x%08"NACL_PRIxPTR", %d)\n",
      30                 :           (uintptr_t) natp, oldfd);
      31              10 :   old_nd = NaClAppGetDesc(nap, oldfd);
      32              10 :   if (NULL == old_nd) {
      33               0 :     retval = -NACL_ABI_EBADF;
      34               0 :     goto done;
      35                 :   }
      36              10 :   retval = NaClAppSetDescAvail(nap, old_nd);
      37                 : done:
      38              10 :   return retval;
      39                 : }
      40                 : 
      41               3 : int32_t NaClSysDup2(struct NaClAppThread  *natp,
      42               3 :                     int                   oldfd,
      43               3 :                     int                   newfd) {
      44               3 :   struct NaClApp  *nap = natp->nap;
      45               3 :   int             retval;
      46               3 :   struct NaClDesc *old_nd;
      47                 : 
      48               3 :   NaClLog(3, "NaClSysDup(0x%08"NACL_PRIxPTR", %d, %d)\n",
      49                 :           (uintptr_t) natp, oldfd, newfd);
      50               3 :   if (newfd < 0) {
      51               0 :     retval = -NACL_ABI_EINVAL;
      52               0 :     goto done;
      53                 :   }
      54                 :   /*
      55                 :    * TODO(bsy): is this a reasonable largest sane value?  The
      56                 :    * descriptor array shouldn't get too large.
      57                 :    */
      58               3 :   if (newfd >= NACL_MAX_FD) {
      59               0 :     retval = -NACL_ABI_EINVAL;
      60               0 :     goto done;
      61                 :   }
      62               3 :   old_nd = NaClAppGetDesc(nap, oldfd);
      63               3 :   if (NULL == old_nd) {
      64               0 :     retval = -NACL_ABI_EBADF;
      65               0 :     goto done;
      66                 :   }
      67               3 :   NaClAppSetDesc(nap, newfd, old_nd);
      68               3 :   retval = newfd;
      69                 : done:
      70               3 :   return retval;
      71                 : }
      72                 : 
      73             676 : int32_t NaClSysClose(struct NaClAppThread *natp,
      74             676 :                      int                  d) {
      75             676 :   struct NaClApp  *nap = natp->nap;
      76             676 :   int             retval = -NACL_ABI_EBADF;
      77             676 :   struct NaClDesc *ndp;
      78                 : 
      79             676 :   NaClLog(3, "Entered NaClSysClose(0x%08"NACL_PRIxPTR", %d)\n",
      80                 :           (uintptr_t) natp, d);
      81                 : 
      82             676 :   NaClFastMutexLock(&nap->desc_mu);
      83             676 :   ndp = NaClAppGetDescMu(nap, d);
      84             676 :   if (NULL != ndp) {
      85             669 :     NaClAppSetDescMu(nap, d, NULL);  /* Unref the desc_tbl */
      86             669 :   }
      87             676 :   NaClFastMutexUnlock(&nap->desc_mu);
      88             676 :   NaClLog(5, "Invoking Close virtual function of object 0x%08"NACL_PRIxPTR"\n",
      89                 :           (uintptr_t) ndp);
      90             676 :   if (NULL != ndp) {
      91             669 :     NaClDescUnref(ndp);
      92             669 :     retval = 0;
      93             669 :   }
      94                 : 
      95             676 :   return retval;
      96                 : }
      97                 : 
      98               3 : int32_t NaClSysIsatty(struct NaClAppThread *natp,
      99               3 :                       int                  d) {
     100               3 :   struct NaClApp  *nap = natp->nap;
     101               3 :   int             retval = -NACL_ABI_EBADF;
     102               3 :   struct NaClDesc *ndp;
     103                 : 
     104               3 :   NaClLog(3, "Entered NaClSysIsatty(0x%08"NACL_PRIxPTR", %d)\n",
     105                 :           (uintptr_t) natp, d);
     106                 : 
     107               3 :   if (!NaClAclBypassChecks) {
     108               0 :     return -NACL_ABI_EACCES;
     109                 :   }
     110                 : 
     111               3 :   ndp = NaClAppGetDesc(nap, d);
     112               3 :   if (NULL == ndp) {
     113               1 :     NaClLog(4, "bad desc\n");
     114               1 :     return -NACL_ABI_EBADF;
     115                 :   }
     116                 : 
     117               2 :   retval = (*((struct NaClDescVtbl const *) ndp->base.vtbl)->Isatty)(ndp);
     118               2 :   NaClDescUnref(ndp);
     119               2 :   return retval;
     120               3 : }
     121                 : 
     122               8 : int32_t NaClSysGetdents(struct NaClAppThread *natp,
     123               8 :                         int                  d,
     124               8 :                         void                 *dirp,
     125               8 :                         size_t               count) {
     126               8 :   struct NaClApp  *nap = natp->nap;
     127               8 :   int32_t         retval = -NACL_ABI_EINVAL;
     128               8 :   ssize_t         getdents_ret;
     129               8 :   uintptr_t       sysaddr;
     130               8 :   struct NaClDesc *ndp;
     131                 : 
     132               8 :   NaClLog(3,
     133                 :           ("Entered NaClSysGetdents(0x%08"NACL_PRIxPTR", "
     134                 :            "%d, 0x%08"NACL_PRIxPTR", "
     135                 :            "%"NACL_PRIuS"[0x%"NACL_PRIxS"])\n"),
     136                 :           (uintptr_t) natp, d, (uintptr_t) dirp, count, count);
     137                 : 
     138               8 :   ndp = NaClAppGetDesc(nap, d);
     139               8 :   if (NULL == ndp) {
     140               0 :     retval = -NACL_ABI_EBADF;
     141               0 :     goto cleanup;
     142                 :   }
     143                 : 
     144                 :   /*
     145                 :    * Generic NaClCopyOutToUser is not sufficient, since buffer size
     146                 :    * |count| is arbitrary and we wouldn't want to have to allocate
     147                 :    * memory in trusted address space to match.
     148                 :    */
     149               8 :   sysaddr = NaClUserToSysAddrRange(nap, (uintptr_t) dirp, count);
     150               8 :   if (kNaClBadAddress == sysaddr) {
     151               0 :     NaClLog(4, " illegal address for directory data\n");
     152               0 :     retval = -NACL_ABI_EFAULT;
     153               0 :     goto cleanup_unref;
     154                 :   }
     155                 : 
     156                 :   /*
     157                 :    * Clamp count to INT32_MAX to avoid the possibility of Getdents returning
     158                 :    * a value that is outside the range of an int32.
     159                 :    */
     160               8 :   if (count > INT32_MAX) {
     161               0 :     count = INT32_MAX;
     162               0 :   }
     163                 :   /*
     164                 :    * Grab addr space lock; getdents should not normally block, though
     165                 :    * if the directory is on a networked filesystem this could, and
     166                 :    * cause mmap to be slower on Windows.
     167                 :    */
     168               8 :   NaClXMutexLock(&nap->mu);
     169               8 :   getdents_ret = (*((struct NaClDescVtbl const *) ndp->base.vtbl)->
     170                 :                   Getdents)(ndp,
     171                 :                             (void *) sysaddr,
     172                 :                             count);
     173               8 :   NaClXMutexUnlock(&nap->mu);
     174                 :   /* drop addr space lock */
     175              16 :   if ((getdents_ret < INT32_MIN && !NaClSSizeIsNegErrno(&getdents_ret))
     176                 :       || INT32_MAX < getdents_ret) {
     177                 :     /* This should never happen, because we already clamped the input count */
     178               0 :     NaClLog(LOG_FATAL, "Overflow in Getdents: return value is %"NACL_PRIxS,
     179                 :             (size_t) getdents_ret);
     180               0 :   } else {
     181               8 :     retval = (int32_t) getdents_ret;
     182                 :   }
     183               8 :   if (retval > 0) {
     184               6 :     NaClLog(4, "getdents returned %d bytes\n", retval);
     185               6 :     NaClLog(8, "getdents result: %.*s\n", retval, (char *) sysaddr);
     186               6 :   } else {
     187               2 :     NaClLog(4, "getdents returned %d\n", retval);
     188               8 :   }
     189                 : 
     190                 : cleanup_unref:
     191               8 :   NaClDescUnref(ndp);
     192                 : 
     193                 : cleanup:
     194               8 :   return retval;
     195                 : }
     196                 : 
     197              50 : int32_t NaClSysRead(struct NaClAppThread  *natp,
     198              50 :                     int                   d,
     199              50 :                     void                  *buf,
     200              50 :                     size_t                count) {
     201              50 :   struct NaClApp  *nap = natp->nap;
     202              50 :   int32_t         retval = -NACL_ABI_EINVAL;
     203              50 :   ssize_t         read_result = -NACL_ABI_EINVAL;
     204              50 :   uintptr_t       sysaddr;
     205              50 :   struct NaClDesc *ndp;
     206              50 :   size_t          log_bytes;
     207              50 :   char const      *ellipsis = "";
     208                 : 
     209              50 :   NaClLog(3,
     210                 :           ("Entered NaClSysRead(0x%08"NACL_PRIxPTR", "
     211                 :            "%d, 0x%08"NACL_PRIxPTR", "
     212                 :            "%"NACL_PRIuS"[0x%"NACL_PRIxS"])\n"),
     213                 :           (uintptr_t) natp, d, (uintptr_t) buf, count, count);
     214                 : 
     215              50 :   ndp = NaClAppGetDesc(nap, d);
     216              50 :   if (NULL == ndp) {
     217               3 :     retval = -NACL_ABI_EBADF;
     218               3 :     goto cleanup;
     219                 :   }
     220                 : 
     221              47 :   sysaddr = NaClUserToSysAddrRange(nap, (uintptr_t) buf, count);
     222              47 :   if (kNaClBadAddress == sysaddr) {
     223               1 :     NaClDescUnref(ndp);
     224               1 :     retval = -NACL_ABI_EFAULT;
     225               1 :     goto cleanup;
     226                 :   }
     227                 : 
     228                 :   /*
     229                 :    * The maximum length for read and write is INT32_MAX--anything larger and
     230                 :    * the return value would overflow. Passing larger values isn't an error--
     231                 :    * we'll just clamp the request size if it's too large.
     232                 :    */
     233              46 :   if (count > INT32_MAX) {
     234               0 :     count = INT32_MAX;
     235               0 :   }
     236                 : 
     237              46 :   NaClVmIoWillStart(nap,
     238                 :                     (uint32_t) (uintptr_t) buf,
     239                 :                     (uint32_t) (((uintptr_t) buf) + count - 1));
     240              46 :   read_result = (*((struct NaClDescVtbl const *) ndp->base.vtbl)->
     241                 :                  Read)(ndp, (void *) sysaddr, count);
     242              46 :   NaClVmIoHasEnded(nap,
     243                 :                     (uint32_t) (uintptr_t) buf,
     244                 :                     (uint32_t) (((uintptr_t) buf) + count - 1));
     245              46 :   if (read_result > 0) {
     246              41 :     NaClLog(4, "read returned %"NACL_PRIdS" bytes\n", read_result);
     247              41 :     log_bytes = (size_t) read_result;
     248              41 :     if (log_bytes > INT32_MAX) {
     249               0 :       log_bytes = INT32_MAX;
     250               0 :       ellipsis = "...";
     251               0 :     }
     252              41 :     if (NaClLogGetVerbosity() < 10) {
     253              41 :       if (log_bytes > kdefault_io_buffer_bytes_to_log) {
     254              16 :         log_bytes = kdefault_io_buffer_bytes_to_log;
     255              16 :         ellipsis = "...";
     256              16 :       }
     257              41 :     }
     258              41 :     NaClLog(8, "read result: %.*s%s\n",
     259                 :             (int) log_bytes, (char *) sysaddr, ellipsis);
     260              41 :   } else {
     261               5 :     NaClLog(4, "read returned %"NACL_PRIdS"\n", read_result);
     262                 :   }
     263              46 :   NaClDescUnref(ndp);
     264                 : 
     265                 :   /* This cast is safe because we clamped count above.*/
     266              46 :   retval = (int32_t) read_result;
     267                 : cleanup:
     268              50 :   return retval;
     269                 : }
     270                 : 
     271           51907 : int32_t NaClSysWrite(struct NaClAppThread *natp,
     272           51907 :                      int                  d,
     273           51907 :                      void                 *buf,
     274           51907 :                      size_t               count) {
     275           51907 :   struct NaClApp  *nap = natp->nap;
     276           51907 :   int32_t         retval = -NACL_ABI_EINVAL;
     277           51907 :   ssize_t         write_result = -NACL_ABI_EINVAL;
     278           51907 :   uintptr_t       sysaddr;
     279           51907 :   char const      *ellipsis = "";
     280           51907 :   struct NaClDesc *ndp;
     281           51907 :   size_t          log_bytes;
     282                 : 
     283           51907 :   NaClLog(3,
     284                 :           "Entered NaClSysWrite(0x%08"NACL_PRIxPTR", "
     285                 :           "%d, 0x%08"NACL_PRIxPTR", "
     286                 :           "%"NACL_PRIuS"[0x%"NACL_PRIxS"])\n",
     287                 :           (uintptr_t) natp, d, (uintptr_t) buf, count, count);
     288                 : 
     289           51907 :   ndp = NaClAppGetDesc(nap, d);
     290           51907 :   NaClLog(4, " ndp = %"NACL_PRIxPTR"\n", (uintptr_t) ndp);
     291           51907 :   if (NULL == ndp) {
     292               5 :     retval = -NACL_ABI_EBADF;
     293               5 :     goto cleanup;
     294                 :   }
     295                 : 
     296           51902 :   sysaddr = NaClUserToSysAddrRange(nap, (uintptr_t) buf, count);
     297           51902 :   if (kNaClBadAddress == sysaddr) {
     298               1 :     NaClDescUnref(ndp);
     299               1 :     retval = -NACL_ABI_EFAULT;
     300               1 :     goto cleanup;
     301                 :   }
     302                 : 
     303           51901 :   log_bytes = count;
     304           51901 :   if (log_bytes > INT32_MAX) {
     305               0 :     log_bytes = INT32_MAX;
     306               0 :     ellipsis = "...";
     307               0 :   }
     308           51901 :   if (NaClLogGetVerbosity() < 10) {
     309           51901 :     if (log_bytes > kdefault_io_buffer_bytes_to_log) {
     310            1397 :       log_bytes = kdefault_io_buffer_bytes_to_log;
     311            1397 :       ellipsis = "...";
     312            1397 :     }
     313           51901 :   }
     314           51901 :   NaClLog(8, "In NaClSysWrite(%d, %.*s%s, %"NACL_PRIuS")\n",
     315                 :           d, (int) log_bytes, (char *) sysaddr, ellipsis, count);
     316                 : 
     317                 :   /*
     318                 :    * The maximum length for read and write is INT32_MAX--anything larger and
     319                 :    * the return value would overflow. Passing larger values isn't an error--
     320                 :    * we'll just clamp the request size if it's too large.
     321                 :    */
     322           51901 :   if (count > INT32_MAX) {
     323               0 :     count = INT32_MAX;
     324               0 :   }
     325                 : 
     326           51901 :   NaClVmIoWillStart(nap,
     327                 :                     (uint32_t) (uintptr_t) buf,
     328                 :                     (uint32_t) (((uintptr_t) buf) + count - 1));
     329           51901 :   write_result = (*((struct NaClDescVtbl const *) ndp->base.vtbl)->
     330                 :                   Write)(ndp, (void *) sysaddr, count);
     331           51901 :   NaClVmIoHasEnded(nap,
     332                 :                    (uint32_t) (uintptr_t) buf,
     333                 :                    (uint32_t) (((uintptr_t) buf) + count - 1));
     334                 : 
     335           51901 :   NaClDescUnref(ndp);
     336                 : 
     337                 :   /* This cast is safe because we clamped count above.*/
     338           51901 :   retval = (int32_t) write_result;
     339                 : 
     340                 : cleanup:
     341           51907 :   return retval;
     342                 : }
     343                 : 
     344                 : /*
     345                 :  * This implements 64-bit offsets, so we use |offp| as an in/out
     346                 :  * address so we can have a 64 bit return value.
     347                 :  */
     348              46 : int32_t NaClSysLseek(struct NaClAppThread *natp,
     349              46 :                      int                  d,
     350              46 :                      nacl_abi_off_t       *offp,
     351              46 :                      int                  whence) {
     352              46 :   struct NaClApp  *nap = natp->nap;
     353              46 :   nacl_abi_off_t  offset;
     354              46 :   nacl_off64_t    retval64;
     355              46 :   int32_t         retval = -NACL_ABI_EINVAL;
     356              46 :   struct NaClDesc *ndp;
     357                 : 
     358              46 :   NaClLog(3,
     359                 :           ("Entered NaClSysLseek(0x%08"NACL_PRIxPTR", %d,"
     360                 :            " 0x%08"NACL_PRIxPTR", %d)\n"),
     361                 :           (uintptr_t) natp, d, (uintptr_t) offp, whence);
     362                 : 
     363              46 :   ndp = NaClAppGetDesc(nap, d);
     364              46 :   if (NULL == ndp) {
     365               1 :     retval = -NACL_ABI_EBADF;
     366               1 :     goto cleanup;
     367                 :   }
     368                 : 
     369              45 :   if (!NaClCopyInFromUser(nap, &offset, (uintptr_t) offp, sizeof offset)) {
     370               0 :     retval = -NACL_ABI_EFAULT;
     371               0 :     goto cleanup_unref;
     372                 :   }
     373              45 :   NaClLog(4, "offset 0x%08"NACL_PRIxNACL_OFF"\n", offset);
     374                 : 
     375              45 :   retval64 = (*((struct NaClDescVtbl const *) ndp->base.vtbl)->
     376                 :               Seek)(ndp, (nacl_off64_t) offset, whence);
     377              45 :   if (NaClOff64IsNegErrno(&retval64)) {
     378               3 :     retval = (int32_t) retval64;
     379               3 :   } else {
     380              42 :     if (NaClCopyOutToUser(nap, (uintptr_t) offp, &retval64, sizeof retval64)) {
     381              42 :       retval = 0;
     382              42 :     } else {
     383               0 :       NaClLog(LOG_FATAL,
     384                 :               "NaClSysLseek: in/out ptr became invalid at copyout?\n");
     385                 :     }
     386              45 :   }
     387                 : cleanup_unref:
     388              45 :   NaClDescUnref(ndp);
     389                 : cleanup:
     390              46 :   return retval;
     391                 : }
     392                 : 
     393             191 : int32_t NaClSysFstat(struct NaClAppThread *natp,
     394             191 :                      int                  d,
     395             191 :                      struct nacl_abi_stat *nasp) {
     396             191 :   struct NaClApp        *nap = natp->nap;
     397             191 :   int32_t               retval = -NACL_ABI_EINVAL;
     398             191 :   struct NaClDesc       *ndp;
     399             191 :   struct nacl_abi_stat  result;
     400                 : 
     401             191 :   NaClLog(3,
     402                 :           ("Entered NaClSysFstat(0x%08"NACL_PRIxPTR
     403                 :            ", %d, 0x%08"NACL_PRIxPTR")\n"),
     404                 :           (uintptr_t) natp,
     405                 :           d, (uintptr_t) nasp);
     406                 : 
     407             191 :   NaClLog(4,
     408                 :           " sizeof(struct nacl_abi_stat) = %"NACL_PRIuS" (0x%"NACL_PRIxS")\n",
     409                 :           sizeof *nasp, sizeof *nasp);
     410                 : 
     411             191 :   ndp = NaClAppGetDesc(nap, d);
     412             191 :   if (NULL == ndp) {
     413               0 :     NaClLog(4, "bad desc\n");
     414               0 :     retval = -NACL_ABI_EBADF;
     415               0 :     goto cleanup;
     416                 :   }
     417                 : 
     418             191 :   retval = (*((struct NaClDescVtbl const *) ndp->base.vtbl)->
     419                 :             Fstat)(ndp, &result);
     420             191 :   if (0 == retval) {
     421             191 :     if (!NaClCopyOutToUser(nap, (uintptr_t) nasp,
     422                 :                            &result, sizeof result)) {
     423               0 :       retval = -NACL_ABI_EFAULT;
     424               0 :     }
     425             191 :   }
     426                 : 
     427             191 :   NaClDescUnref(ndp);
     428                 : cleanup:
     429             191 :   return retval;
     430                 : }

Generated by: LCOV version 1.7