LCOV - code coverage report
Current view: directory - src/trusted/desc/posix - nacl_desc_imc_bound_desc.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 72 48 66.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.
       9                 :  * Bound IMC descriptors.
      10                 :  */
      11                 : 
      12                 : #include <assert.h>
      13                 : #include <errno.h>
      14                 : #include <stdlib.h>
      15                 : #include <string.h>
      16                 : #include <sys/socket.h>
      17                 : 
      18                 : #include "native_client/src/include/portability.h"
      19                 : #include "native_client/src/shared/imc/nacl_imc_c.h"
      20                 : #include "native_client/src/shared/platform/nacl_check.h"
      21                 : #include "native_client/src/shared/platform/nacl_log.h"
      22                 : 
      23                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      24                 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
      25                 : #include "native_client/src/trusted/desc/nacl_desc_imc_bound_desc.h"
      26                 : 
      27                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      28                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      29                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      30                 : 
      31                 : 
      32                 : static struct NaClDescVtbl const kNaClDescImcBoundDescVtbl;  /* fwd */
      33                 : 
      34                 : int NaClDescImcBoundDescCtor(struct NaClDescImcBoundDesc  *self,
      35              36 :                              NaClHandle                   h) {
      36              36 :   struct NaClDesc *basep = (struct NaClDesc *) self;
      37                 : 
      38              36 :   basep->base.vtbl = (struct NaClRefCountVtbl const *) NULL;
      39              36 :   if (!NaClDescCtor(basep)) {
      40               0 :     return 0;
      41                 :   }
      42              36 :   self->h = h;
      43              36 :   basep->base.vtbl =
      44                 :       (struct NaClRefCountVtbl const *) &kNaClDescImcBoundDescVtbl;
      45              36 :   return 1;
      46                 : }
      47                 : 
      48              12 : void NaClDescImcBoundDescDtor(struct NaClRefCount *vself) {
      49              12 :   struct NaClDescImcBoundDesc *self = (struct NaClDescImcBoundDesc *) vself;
      50                 : 
      51              12 :   NaClClose(self->h);
      52              12 :   self->h = NACL_INVALID_HANDLE;
      53              12 :   vself->vtbl = (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
      54              12 :   (*vself->vtbl->Dtor)(vself);
      55              12 : }
      56                 : 
      57                 : int NaClDescImcBoundDescFstat(struct NaClDesc          *vself,
      58               0 :                               struct nacl_abi_stat     *statbuf) {
      59                 :   UNREFERENCED_PARAMETER(vself);
      60                 : 
      61               0 :   memset(statbuf, 0, sizeof *statbuf);
      62               0 :   statbuf->nacl_abi_st_mode = NACL_ABI_S_IFBOUNDSOCK;
      63               0 :   return 0;
      64                 : }
      65                 : 
      66                 : int NaClDescImcBoundDescAcceptConn(struct NaClDesc *vself,
      67              25 :                                    struct NaClDesc **result) {
      68                 :   /*
      69                 :    * See NaClDescConnCapConnectAddr code in nacl_desc_conn_cap.c
      70                 :    */
      71              25 :   struct NaClDescImcBoundDesc *self = (struct NaClDescImcBoundDesc *) vself;
      72                 :   int                         retval;
      73                 :   NaClHandle                  received_fd;
      74                 :   struct NaClDescImcDesc      *peer;
      75                 :   struct iovec                iovec;
      76                 :   struct msghdr               accept_msg;
      77                 :   struct cmsghdr              *cmsg;
      78                 :   char                        data_buf[1];
      79                 :   char                        control_buf[CMSG_SPACE_KHANDLE_COUNT_MAX_INTS];
      80                 :   int                         received;
      81                 : 
      82                 :   assert(CMSG_SPACE(sizeof(int)) <= CMSG_SPACE_KHANDLE_COUNT_MAX_INTS);
      83                 : 
      84              25 :   peer = malloc(sizeof(*peer));
      85              25 :   if (peer == NULL) {
      86               0 :     return -NACL_ABI_ENOMEM;
      87                 :   }
      88                 : 
      89              25 :   iovec.iov_base = data_buf;
      90              25 :   iovec.iov_len = sizeof(data_buf);
      91              25 :   accept_msg.msg_iov = &iovec;
      92              25 :   accept_msg.msg_iovlen = 1;
      93              25 :   accept_msg.msg_name = NULL;
      94              25 :   accept_msg.msg_namelen = 0;
      95              25 :   accept_msg.msg_control = control_buf;
      96              25 :   accept_msg.msg_controllen = sizeof(control_buf);
      97                 : 
      98              25 :   NaClLog(3,
      99                 :           ("NaClDescImcBoundDescAcceptConn(0x%08"NACL_PRIxPTR", "
     100                 :            " h = %d\n"),
     101                 :           (uintptr_t) vself,
     102                 :           self->h);
     103                 : 
     104              25 :   received_fd = NACL_INVALID_HANDLE;
     105                 : 
     106              25 :   received = recvmsg(self->h, &accept_msg, 0);
     107              19 :   if (received != 1 || data_buf[0] != 'c') {
     108               0 :     NaClLog(LOG_ERROR,
     109                 :             ("NaClDescImcBoundDescAcceptConn:"
     110                 :              " could not receive connection message, errno %d\n"),
     111                 :             errno);
     112               0 :     retval = -NACL_ABI_EIO;
     113               0 :     goto cleanup;
     114                 :   }
     115                 : 
     116              19 :   retval = 0;
     117                 :   /*
     118                 :    * If we got more than one fd in the message, we must clean up by
     119                 :    * closing those extra descriptors.  Given that control_buf is
     120                 :    * CMSG_SPACE(sizeof(int)) in size, this shouldn't actualy happen.
     121                 :    *
     122                 :    * We follow the principle of being strict in what we send and
     123                 :    * tolerant in what we accept, and simply discard the extra
     124                 :    * descriptors without signaling an error (other than a log
     125                 :    * message).  This makes it easier to rev the protocol w/o
     126                 :    * necessarily requiring a protocol version number bump.
     127                 :    */
     128              19 :   for (cmsg = CMSG_FIRSTHDR(&accept_msg);
     129              57 :        cmsg != NULL;
     130              19 :        cmsg = CMSG_NXTHDR(&accept_msg, cmsg)) {
     131              19 :     if (cmsg->cmsg_level == SOL_SOCKET &&
     132                 :         cmsg->cmsg_type == SCM_RIGHTS &&
     133                 :         cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
     134              19 :       if (NACL_INVALID_HANDLE != received_fd) {
     135                 :         int bad_fd;
     136                 : 
     137                 :         /* can only be true on 2nd time through */
     138               0 :         NaClLog(LOG_ERROR, ("NaClDescImcBoundDescAcceptConn: connection"
     139                 :                             " message contains more than 1 descriptors?!?\n"));
     140               0 :         memcpy(&bad_fd, CMSG_DATA(cmsg), sizeof bad_fd);
     141               0 :         (void) close(bad_fd);
     142                 :         /*
     143                 :          * If we want to NOT be tolerant about what we receive, we could
     144                 :          * uncomment this:
     145                 :          *
     146                 :          * retval = -NACL_ABI_EIO;
     147                 :          */
     148               0 :         continue;
     149                 :       }
     150                 :       /*
     151                 :        * We use memcpy() rather than assignment through a cast to avoid
     152                 :        * strict-aliasing warnings
     153                 :        */
     154              19 :       memcpy(&received_fd, CMSG_DATA(cmsg), sizeof received_fd);
     155                 :     }
     156                 :   }
     157              19 :   if (0 != retval) {
     158               0 :     goto cleanup;
     159                 :   }
     160              19 :   if (NACL_INVALID_HANDLE == received_fd) {
     161               0 :     NaClLog(LOG_ERROR, ("NaClDescImcBoundDescAcceptConn: connection"
     162                 :                         " message contains NO descriptors?!?\n"));
     163               0 :     retval = -NACL_ABI_EIO;
     164               0 :     goto cleanup;
     165                 :   }
     166                 : 
     167                 :   if (NACL_OSX) {
     168                 :     /*
     169                 :      * Send a message to acknowledge that we received the socket FD
     170                 :      * successfully.  This is part of a workaround for a Mac OS X
     171                 :      * kernel bug.
     172                 :      * See http://code.google.com/p/nativeclient/issues/detail?id=1796
     173                 :      */
     174              19 :     ssize_t sent = send(received_fd, "a", 1, 0);
     175              19 :     if (sent != 1) {
     176               0 :       retval = -NACL_ABI_EIO;
     177               0 :       goto cleanup;
     178                 :     }
     179                 :   }
     180                 : 
     181              19 :   if (!NaClDescImcDescCtor(peer, received_fd)) {
     182               0 :     retval = -NACL_ABI_EMFILE;
     183               0 :     goto cleanup;
     184                 :   }
     185              19 :   received_fd = NACL_INVALID_HANDLE;
     186                 : 
     187              19 :   *result = (struct NaClDesc *) peer;
     188              19 :   retval = 0;
     189                 : 
     190              19 : cleanup:
     191              19 :   if (retval < 0) {
     192               0 :     if (received_fd != NACL_INVALID_HANDLE) {
     193               0 :       (void) close(received_fd);
     194                 :     }
     195               0 :     free(peer);
     196                 :   }
     197              19 :   return retval;
     198                 : }
     199                 : 
     200                 : static struct NaClDescVtbl const kNaClDescImcBoundDescVtbl = {
     201                 :   {
     202                 :     NaClDescImcBoundDescDtor,
     203                 :   },
     204                 :   NaClDescMapNotImplemented,
     205                 :   NaClDescUnmapUnsafeNotImplemented,
     206                 :   NaClDescUnmapNotImplemented,
     207                 :   NaClDescReadNotImplemented,
     208                 :   NaClDescWriteNotImplemented,
     209                 :   NaClDescSeekNotImplemented,
     210                 :   NaClDescIoctlNotImplemented,
     211                 :   NaClDescImcBoundDescFstat,
     212                 :   NaClDescGetdentsNotImplemented,
     213                 :   NACL_DESC_BOUND_SOCKET,
     214                 :   NaClDescExternalizeSizeNotImplemented,
     215                 :   NaClDescExternalizeNotImplemented,
     216                 :   NaClDescLockNotImplemented,
     217                 :   NaClDescTryLockNotImplemented,
     218                 :   NaClDescUnlockNotImplemented,
     219                 :   NaClDescWaitNotImplemented,
     220                 :   NaClDescTimedWaitAbsNotImplemented,
     221                 :   NaClDescSignalNotImplemented,
     222                 :   NaClDescBroadcastNotImplemented,
     223                 :   NaClDescSendMsgNotImplemented,
     224                 :   NaClDescRecvMsgNotImplemented,
     225                 :   NaClDescConnectAddrNotImplemented,
     226                 :   NaClDescImcBoundDescAcceptConn,
     227                 :   NaClDescPostNotImplemented,
     228                 :   NaClDescSemWaitNotImplemented,
     229                 :   NaClDescGetValueNotImplemented,
     230                 : };

Generated by: LCOV version 1.7