LCOV - code coverage report
Current view: directory - src/shared/platform/linux - nacl_host_desc.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 130 86 66.2 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright 2008 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can
       4                 :  * be found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * NaCl Service Runtime.  I/O Descriptor / Handle abstraction.  Memory
       9                 :  * mapping using descriptors.
      10                 :  *
      11                 :  * Note that we avoid using the thread-specific data / thread local
      12                 :  * storage access to the "errno" variable, and instead use the raw
      13                 :  * system call return interface of small negative numbers as errors.
      14                 :  */
      15                 : 
      16                 : #include <stdint.h>
      17                 : #include <sys/types.h>
      18                 : #include <sys/stat.h>
      19                 : #include <fcntl.h>
      20                 : #include <errno.h>
      21                 : #include <sys/mman.h>
      22                 : #include <unistd.h>
      23                 : 
      24                 : #include "native_client/src/include/nacl_platform.h"
      25                 : #include "native_client/src/include/portability.h"
      26                 : 
      27                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      28                 : #include "native_client/src/shared/platform/nacl_log.h"
      29                 : 
      30                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      31                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      32                 : #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
      33                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      34                 : 
      35                 : 
      36                 : /*
      37                 :  * Map our ABI to the host OS's ABI.  On linux, this should be a big no-op.
      38                 :  */
      39              29 : static INLINE int NaClMapOpenFlags(int nacl_flags) {
      40                 :   int host_os_flags;
      41                 : 
      42              29 :   nacl_flags &= (NACL_ABI_O_ACCMODE | NACL_ABI_O_CREAT
      43                 :                  | NACL_ABI_O_TRUNC | NACL_ABI_O_APPEND);
      44                 : 
      45              29 :   host_os_flags = 0;
      46                 : #define C(H) case NACL_ABI_ ## H: \
      47                 :   host_os_flags |= H;             \
      48                 :   break;
      49              29 :   switch (nacl_flags & NACL_ABI_O_ACCMODE) {
      50              18 :     C(O_RDONLY);
      51               5 :     C(O_WRONLY);
      52               6 :     C(O_RDWR);
      53                 :   }
      54                 : #undef C
      55                 : #define M(H) do { \
      56                 :     if (0 != (nacl_flags & NACL_ABI_ ## H)) {   \
      57                 :       host_os_flags |= H;                       \
      58                 :     }                                           \
      59                 :   } while (0)
      60              29 :   M(O_CREAT);
      61              29 :   M(O_TRUNC);
      62              29 :   M(O_APPEND);
      63                 : #undef M
      64              29 :   return host_os_flags;
      65                 : }
      66                 : 
      67              29 : static INLINE int NaClMapOpenPerm(int nacl_perm) {
      68                 :   int host_os_perm;
      69                 : 
      70              29 :   host_os_perm = 0;
      71                 : #define M(H) do { \
      72                 :     if (0 != (nacl_perm & NACL_ABI_ ## H)) { \
      73                 :       host_os_perm |= H; \
      74                 :     } \
      75                 :   } while (0)
      76              29 :   M(S_IRUSR);
      77              29 :   M(S_IWUSR);
      78                 : #undef M
      79              29 :   return host_os_perm;
      80                 : }
      81                 : 
      82               4 : static INLINE int NaClMapFlagMap(int nacl_map_flags) {
      83                 :   int host_os_flags;
      84                 : 
      85               4 :   host_os_flags = 0;
      86                 : #define M(H) do { \
      87                 :     if (0 != (nacl_map_flags & NACL_ABI_ ## H)) { \
      88                 :       host_os_flags |= H; \
      89                 :     } \
      90                 :   } while (0)
      91               4 :   M(MAP_SHARED);
      92               4 :   M(MAP_PRIVATE);
      93               4 :   M(MAP_FIXED);
      94               4 :   M(MAP_ANONYMOUS);
      95                 : #undef M
      96                 : 
      97               4 :   return host_os_flags;
      98                 : }
      99                 : 
     100                 : /*
     101                 :  * TODO(bsy): handle the !NACL_ABI_MAP_FIXED case.
     102                 :  */
     103                 : uintptr_t NaClHostDescMap(struct NaClHostDesc *d,
     104                 :                           void                *start_addr,
     105                 :                           size_t              len,
     106                 :                           int                 prot,
     107                 :                           int                 flags,
     108               4 :                           nacl_off64_t        offset) {
     109                 :   int   desc;
     110                 :   void  *map_addr;
     111                 :   int   host_prot;
     112                 :   int   host_flags;
     113                 : 
     114               4 :   NaClLog(4,
     115                 :           ("NaClHostDescMap(0x%08"NACL_PRIxPTR", "
     116                 :            "0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxS", "
     117                 :            "0x%x, 0x%x, 0x%08"NACL_PRIx64")\n"),
     118                 :           (uintptr_t) d,
     119                 :           (uintptr_t) start_addr,
     120                 :           len,
     121                 :           prot,
     122                 :           flags,
     123                 :           (int64_t) offset);
     124               4 :   if (NULL == d && 0 == (flags & NACL_ABI_MAP_ANONYMOUS)) {
     125               0 :     NaClLog(LOG_FATAL, "NaClHostDescMap: 'this' is NULL and not anon map\n");
     126                 :   }
     127               4 :   prot &= (NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE);
     128                 :   /* may be PROT_NONE too, just not PROT_EXEC */
     129                 : 
     130                 : 
     131               4 :   if (flags & NACL_ABI_MAP_ANONYMOUS) {
     132               3 :     desc = -1;
     133                 :   } else {
     134               1 :     desc = d->d;
     135                 :   }
     136                 :   /*
     137                 :    * Translate flags, prot to host_flags, host_prot.
     138                 :    */
     139               4 :   host_flags = NaClMapFlagMap(flags);
     140               4 :   host_prot = NaClProtMap(prot);
     141                 : 
     142               4 :   NaClLog(4, "NaClHostDescMap: host_flags 0x%x, host_prot 0x%x\n",
     143                 :           host_flags, host_prot);
     144                 : 
     145               4 :   map_addr = mmap(start_addr, len, host_prot, host_flags, desc, offset);
     146                 : 
     147               4 :   if (MAP_FAILED == map_addr) {
     148               0 :     NaClLog(LOG_INFO,
     149                 :             ("NaClHostDescMap: "
     150                 :              "mmap(0x%08"NACL_PRIxPTR", 0x%"NACL_PRIxS", "
     151                 :              "0x%x, 0x%x, 0x%d, 0x%"NACL_PRIx64")"
     152                 :              " failed, errno %d.\n"),
     153                 :             (uintptr_t) start_addr, len, host_prot, host_flags, desc,
     154                 :             (int64_t) offset,
     155                 :             errno);
     156               0 :     return -NaClXlateErrno(errno);
     157                 :   }
     158               4 :   if (0 != (flags & NACL_ABI_MAP_FIXED) && map_addr != start_addr) {
     159               0 :     NaClLog(LOG_FATAL,
     160                 :             ("NaClHostDescMap: mmap with MAP_FIXED not fixed:"
     161                 :              " returned 0x%08"NACL_PRIxPTR" instead of 0x%08"NACL_PRIxPTR"\n"),
     162                 :             (uintptr_t) map_addr,
     163                 :             (uintptr_t) start_addr);
     164                 :   }
     165               4 :   NaClLog(4, "NaClHostDescMap: returning 0x%08"NACL_PRIxPTR"\n",
     166                 :           (uintptr_t) start_addr);
     167                 : 
     168               4 :   return (uintptr_t) start_addr;
     169                 : }
     170                 : 
     171                 : int NaClHostDescUnmapUnsafe(void    *start_addr,
     172               0 :                             size_t  len) {
     173                 :   int       retval;
     174               0 :   return ((-1 == (retval = munmap(start_addr, len)))
     175                 :           ? -NaClXlateErrno(errno)
     176                 :           : retval);
     177                 : }
     178                 : 
     179                 : int NaClHostDescUnmap(void    *start_addr,
     180               0 :                       size_t  len) {
     181                 :   int       retval;
     182               0 :   return ((-1 == (retval = (uintptr_t) mmap(start_addr,
     183                 :                                             len,
     184                 :                                             PROT_NONE,
     185                 :                                             (MAP_PRIVATE
     186                 :                                              | MAP_ANONYMOUS | MAP_FIXED),
     187                 :                                             -1,
     188                 :                                             (nacl_off64_t) 0)))
     189                 :           ? -NaClXlateErrno(errno) : retval);
     190                 : }
     191                 : 
     192                 : int NaClHostDescCtor(struct NaClHostDesc  *d,
     193              25 :                      int                  fd) {
     194              25 :   d->d = fd;
     195              25 :   NaClLog(3, "NaClHostDescCtor: success.\n");
     196              25 :   return 0;
     197                 : }
     198                 : 
     199                 : int NaClHostDescOpen(struct NaClHostDesc  *d,
     200                 :                      char const           *path,
     201                 :                      int                  flags,
     202              29 :                      int                  mode) {
     203                 :   int         host_desc;
     204                 :   struct stat stbuf;
     205                 : 
     206              29 :   NaClLog(3, "NaClHostDescOpen(0x%08"NACL_PRIxPTR", %s, 0x%x, 0x%x)\n",
     207                 :           (uintptr_t) d, path, flags, mode);
     208              29 :   if (NULL == d) {
     209               0 :     NaClLog(LOG_FATAL, "NaClHostDescOpen: 'this' is NULL\n");
     210                 :   }
     211                 :   /*
     212                 :    * Sanitize access flags.
     213                 :    */
     214              29 :   if (0 != (flags & ~NACL_ALLOWED_OPEN_FLAGS)) {
     215               0 :     return -NACL_ABI_EINVAL;
     216                 :   }
     217                 : 
     218              29 :   switch (flags & NACL_ABI_O_ACCMODE) {
     219                 :     case NACL_ABI_O_RDONLY:
     220                 :     case NACL_ABI_O_WRONLY:
     221                 :     case NACL_ABI_O_RDWR:
     222                 :       break;
     223                 :     default:
     224               0 :       NaClLog(LOG_ERROR,
     225                 :               "NaClHostDescOpen: bad access flags 0x%x.\n",
     226                 :               flags);
     227               0 :       return -NACL_ABI_EINVAL;
     228                 :   }
     229                 : 
     230              29 :   flags = NaClMapOpenFlags(flags);
     231              29 :   mode = NaClMapOpenPerm(mode);
     232                 : 
     233              29 :   NaClLog(3, "NaClHostDescOpen: invoking POSIX open(%s,0x%x,0%o)\n",
     234                 :           path, flags, mode);
     235              29 :   host_desc = open(path, flags, mode);
     236              29 :   NaClLog(3, "NaClHostDescOpen: got descriptor %d\n", host_desc);
     237              29 :   if (-1 == host_desc) {
     238               4 :     NaClLog(LOG_ERROR,
     239                 :             "NaClHostDescOpen: open returned -1, errno %d\n", errno);
     240               4 :     return -NaClXlateErrno(errno);
     241                 :   }
     242              25 :   if (-1 == fstat(host_desc, &stbuf)) {
     243               0 :     NaClLog(LOG_ERROR,
     244                 :             "NaClHostDescOpen: fstat failed?!?  errno %d\n", errno);
     245               0 :     (void) close(host_desc);
     246               0 :     return -NaClXlateErrno(errno);
     247                 :   }
     248              25 :   if (!S_ISREG(stbuf.st_mode)) {
     249               0 :     NaClLog(LOG_INFO,
     250                 :             "NaClHostDescOpen: file type 0x%x, not regular\n", stbuf.st_mode);
     251               0 :     (void) close(host_desc);
     252                 :     /* cannot access anything other than a real file */
     253               0 :     return -NACL_ABI_EPERM;
     254                 :   }
     255              25 :   return NaClHostDescCtor(d, host_desc);
     256                 : }
     257                 : 
     258                 : int NaClHostDescPosixDup(struct NaClHostDesc  *d,
     259                 :                          int                  posix_d,
     260               0 :                          int                  flags) {
     261                 :   int host_desc;
     262                 : 
     263               0 :   if (NULL == d) {
     264               0 :     NaClLog(LOG_FATAL, "NaClHostDescPosixDup: 'this' is NULL\n");
     265                 :   }
     266                 :   /*
     267                 :    * Sanitize access flags.
     268                 :    */
     269               0 :   if (0 != (flags & ~NACL_ALLOWED_OPEN_FLAGS)) {
     270               0 :     return -NACL_ABI_EINVAL;
     271                 :   }
     272                 : 
     273               0 :   switch (flags & NACL_ABI_O_ACCMODE) {
     274                 :     case NACL_ABI_O_RDONLY:
     275                 :     case NACL_ABI_O_WRONLY:
     276                 :     case NACL_ABI_O_RDWR:
     277                 :       break;
     278                 :     default:
     279               0 :       NaClLog(LOG_ERROR,
     280                 :               "NaClHostDescPosixDup: bad access flags 0x%x.\n",
     281                 :               flags);
     282               0 :       return -NACL_ABI_EINVAL;
     283                 :   }
     284                 : 
     285               0 :   host_desc = dup(posix_d);
     286               0 :   if (-1 == host_desc) {
     287               0 :     return -NACL_ABI_EINVAL;
     288                 :   }
     289               0 :   d->d = host_desc;
     290               0 :   return 0;
     291                 : }
     292                 : 
     293                 : int NaClHostDescPosixTake(struct NaClHostDesc *d,
     294                 :                           int                 posix_d,
     295              68 :                           int                 flags) {
     296              68 :   if (NULL == d) {
     297               0 :     NaClLog(LOG_FATAL, "NaClHostDescPosixTake: 'this' is NULL\n");
     298                 :   }
     299                 :   /*
     300                 :    * Sanitize access flags.
     301                 :    */
     302              68 :   if (0 != (flags & ~NACL_ALLOWED_OPEN_FLAGS)) {
     303               0 :     return -NACL_ABI_EINVAL;
     304                 :   }
     305                 : 
     306              68 :   switch (flags & NACL_ABI_O_ACCMODE) {
     307                 :     case NACL_ABI_O_RDONLY:
     308                 :     case NACL_ABI_O_WRONLY:
     309                 :     case NACL_ABI_O_RDWR:
     310                 :       break;
     311                 :     default:
     312               0 :       NaClLog(LOG_ERROR,
     313                 :               "NaClHostDescPosixTake: bad access flags 0x%x.\n",
     314                 :               flags);
     315               0 :       return -NACL_ABI_EINVAL;
     316                 :   }
     317                 : 
     318              68 :   d->d = posix_d;
     319              68 :   return 0;
     320                 : }
     321                 : 
     322                 : ssize_t NaClHostDescRead(struct NaClHostDesc  *d,
     323                 :                          void                 *buf,
     324             116 :                          size_t               len) {
     325                 :   ssize_t retval;
     326                 : 
     327             116 :   if (NULL == d) {
     328               0 :     NaClLog(LOG_FATAL, "NaClHostDescRead: 'this' is NULL\n");
     329                 :   }
     330             116 :   return ((-1 == (retval = read(d->d, buf, len)))
     331                 :           ? -NaClXlateErrno(errno) : retval);
     332                 : }
     333                 : 
     334                 : ssize_t NaClHostDescWrite(struct NaClHostDesc *d,
     335                 :                           void const          *buf,
     336            6805 :                           size_t              len) {
     337                 :   ssize_t retval;
     338                 : 
     339            6805 :   if (NULL == d) {
     340               0 :     NaClLog(LOG_FATAL, "NaClHostDescWrite: 'this' is NULL\n");
     341                 :   }
     342            6805 :   return ((-1 == (retval = write(d->d, buf, len)))
     343                 :           ? -NaClXlateErrno(errno) : retval);
     344                 : }
     345                 : 
     346                 : nacl_off64_t NaClHostDescSeek(struct NaClHostDesc  *d,
     347                 :                               nacl_off64_t         offset,
     348            6700 :                               int                  whence) {
     349                 :   nacl_off64_t retval;
     350                 : 
     351            6700 :   if (NULL == d) {
     352               0 :     NaClLog(LOG_FATAL, "NaClHostDescSeek: 'this' is NULL\n");
     353                 :   }
     354                 : #if NACL_LINUX
     355                 :   return ((-1 == (retval = lseek64(d->d, offset, whence)))
     356                 :           ? -NaClXlateErrno(errno) : retval);
     357                 : #elif NACL_OSX
     358            6700 :   return ((-1 == (retval = lseek(d->d, offset, whence)))
     359                 :           ? -NaClXlateErrno(errno) : retval);
     360                 : #else
     361                 : # error "What Unix-like OS is this?"
     362                 : #endif
     363                 : }
     364                 : 
     365                 : int NaClHostDescIoctl(struct NaClHostDesc *d,
     366                 :                       int                 request,
     367               0 :                       void                *arg) {
     368                 : #if 0
     369                 :   int retval;
     370                 : 
     371                 :   if (NULL == d) {
     372                 :     NaClLog(LOG_FATAL, "NaClHostDescIoctl: 'this' is NULL\n");
     373                 :   }
     374                 :   /*
     375                 :    * Validate arg according to request.  Arrgh indeed.
     376                 :    */
     377                 :   return ((-1 == (retval = ioctl(d->d, request, arg)))
     378                 :           ? -NaClXlateErrno(errno) : retval);
     379                 : #else
     380                 :   UNREFERENCED_PARAMETER(request);
     381                 :   UNREFERENCED_PARAMETER(arg);
     382                 : 
     383               0 :   if (NULL == d) {
     384               0 :     NaClLog(LOG_FATAL, "NaClHostDescIoctl: 'this' is NULL\n");
     385                 :   }
     386               0 :   return -NACL_ABI_ENOSYS;
     387                 : #endif
     388                 : }
     389                 : 
     390                 : /*
     391                 :  * See NaClHostDescStat below.
     392                 :  */
     393                 : int NaClHostDescFstat(struct NaClHostDesc  *d,
     394               6 :                       nacl_host_stat_t     *nhsp) {
     395                 : #if NACL_LINUX
     396                 :   if (fstat64(d->d, nhsp) == -1) {
     397                 :     return -errno;
     398                 :   }
     399                 : #elif NACL_OSX
     400               6 :   if (fstat(d->d, nhsp) == -1) {
     401               0 :     return -errno;
     402                 :   }
     403                 : #else
     404                 : # error "What OS?"
     405                 : #endif
     406                 : 
     407               6 :   return 0;
     408                 : }
     409                 : 
     410              33 : int NaClHostDescClose(struct NaClHostDesc *d) {
     411                 :   int retval;
     412                 : 
     413              33 :   if (NULL == d) {
     414               0 :     NaClLog(LOG_FATAL, "NaClHostDescClose: 'this' is NULL\n");
     415                 :   }
     416              33 :   retval = close(d->d);
     417              33 :   if (-1 != retval) {
     418              33 :     d->d = -1;
     419                 :   }
     420              33 :   return (-1 == retval) ? -NaClXlateErrno(errno) : retval;
     421                 : }
     422                 : 
     423                 : /*
     424                 :  * This is not a host descriptor function, but is closely related to
     425                 :  * fstat and should behave similarly.
     426                 :  */
     427                 : int NaClHostDescStat(char const       *host_os_pathname,
     428              25 :                      nacl_host_stat_t *nhsp) {
     429                 : 
     430                 : #if NACL_LINUX
     431                 :   if (stat64(host_os_pathname, nhsp) == -1) {
     432                 :     return -errno;
     433                 :   }
     434                 : #elif NACL_OSX
     435              25 :   if (stat(host_os_pathname, nhsp) == -1) {
     436               4 :     return -errno;
     437                 :   }
     438                 : #else
     439                 : # error "What OS?"
     440                 : #endif
     441                 : 
     442              21 :   return 0;
     443                 : }

Generated by: LCOV version 1.7