LCOV - code coverage report
Current view: directory - src/trusted/desc - nacl_desc_wrapper.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 366 108 29.5 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : // Copyright (c) 2011 The Native Client Authors. All rights reserved.
       2                 : // Use of this source code is governed by a BSD-style license that can be
       3                 : // found in the LICENSE file.
       4                 : 
       5                 : #include <limits>
       6                 : #include <new>
       7                 : #include "base/shared_memory.h"
       8                 : #include "base/sync_socket.h"
       9                 : #include "native_client/src/include/portability.h"
      10                 : #include "native_client/src/include/portability_string.h"
      11                 : #include "native_client/src/shared/imc/nacl_imc.h"
      12                 : #include "native_client/src/shared/platform/nacl_check.h"
      13                 : #include "native_client/src/shared/platform/nacl_log.h"
      14                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      15                 : #if defined(NACL_LINUX)
      16                 : #include "native_client/src/trusted/desc/linux/nacl_desc_sysv_shm.h"
      17                 : #endif  // defined(NACL_LINUX)
      18                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      19                 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
      20                 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
      21                 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
      22                 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
      23                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      24                 : #include "native_client/src/trusted/desc/nacl_desc_quota.h"
      25                 : #include "native_client/src/trusted/desc/nacl_desc_rng.h"
      26                 : #include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
      27                 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
      28                 : #include "native_client/src/trusted/desc/nrd_xfer.h"
      29                 : #include "native_client/src/trusted/desc/nrd_xfer_effector.h"
      30                 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
      31                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      32                 : #include "native_client/src/trusted/service_runtime/include/sys/nacl_imc_api.h"
      33                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      34                 : 
      35                 : // TODO(polina): follow the style guide and replace "nhdp" and "ndiodp" with
      36                 : //               "host_desc" and "io_desc"
      37                 : 
      38                 : namespace {
      39              13 : static const size_t kSizeTMax = std::numeric_limits<size_t>::max();
      40                 : 
      41              11 : struct NaClDesc* OpenHostFileCommon(const char* fname, int flags, int mode) {
      42                 :   struct NaClHostDesc* nhdp =
      43              11 :     reinterpret_cast<struct NaClHostDesc*>(calloc(1, sizeof(*nhdp)));
      44              11 :   if (NULL == nhdp) {
      45               0 :     return NULL;
      46                 :   }
      47              11 :   if (0 != NaClHostDescOpen(nhdp, fname, flags, mode)) {
      48               0 :     free(nhdp);
      49               0 :     return NULL;
      50                 :   }
      51              11 :   struct NaClDescIoDesc* ndiodp = NaClDescIoDescMake(nhdp);
      52              11 :   if (NULL == ndiodp) {
      53               0 :     NaClHostDescClose(nhdp);
      54               0 :     free(nhdp);
      55               0 :     return NULL;
      56                 :   }
      57              11 :   return reinterpret_cast<struct NaClDesc*>(ndiodp);
      58                 : }
      59                 : 
      60               0 : struct NaClDesc* ImportHostDescCommon(int host_os_desc, int mode) {
      61               0 :   NaClHostDesc* nhdp = NaClHostDescPosixMake(host_os_desc, mode);
      62               0 :   if (NULL == nhdp) {
      63               0 :     return NULL;
      64                 :   }
      65               0 :   NaClDescIoDesc* ndiodp = NaClDescIoDescMake(nhdp);
      66               0 :   if (NULL == ndiodp) {
      67               0 :     NaClHostDescClose(nhdp);
      68               0 :     free(nhdp);
      69               0 :     return NULL;
      70                 :   }
      71               0 :   return reinterpret_cast<struct NaClDesc*>(ndiodp);
      72                 : }
      73                 : 
      74                 : struct NaClDesc* MakeQuotaCommon(const uint8_t* file_id,
      75               0 :                                  struct NaClDesc* desc) {
      76                 :   NaClDescQuota* ndqp =
      77               0 :       reinterpret_cast<NaClDescQuota*>(calloc(1, sizeof *ndqp));
      78               0 :   if ((NULL == ndqp) || !NaClDescQuotaCtor(ndqp, desc, file_id, NULL)) {
      79               0 :     free(ndqp);
      80               0 :     return NULL;
      81                 :   }
      82               0 :   return reinterpret_cast<struct NaClDesc*>(ndqp);
      83                 : }
      84                 : 
      85                 : }  // namespace
      86                 : 
      87                 : namespace nacl {
      88                 : 
      89                 : // Descriptor creation and manipulation sometimes requires additional state
      90                 : // (for instance, Effectors).  Therefore, we create an object that encapsulates
      91                 : // that state.
      92                 : class DescWrapperCommon {
      93                 :   friend class DescWrapperFactory;
      94                 : 
      95                 :  public:
      96                 :   typedef uint32_t RefCountType;
      97                 : 
      98                 :   // Get a pointer to the effector.
      99              40 :   struct NaClDescEffector* effp() {
     100              40 :     return reinterpret_cast<struct NaClDescEffector*>(&eff_);
     101                 :   }
     102                 : 
     103                 :   // Inform clients that the object was successfully initialized.
     104              24 :   bool is_initialized() const { return is_initialized_; }
     105                 : 
     106                 :   // Manipulate reference count
     107              57 :   DescWrapperCommon* Ref() {
     108                 :     // TODO(sehr): replace with a reference count class when we have one.
     109              57 :     NaClXMutexLock(&ref_count_mu_);
     110              57 :     if (std::numeric_limits<RefCountType>::max() == ref_count_) {
     111               0 :       NaClLog(LOG_FATAL, "DescWrapperCommon ref count overflow\n");
     112                 :     }
     113              57 :     ++ref_count_;
     114              57 :     NaClXMutexUnlock(&ref_count_mu_);
     115              57 :     return this;
     116                 :   }
     117                 : 
     118              75 :   void Unref() {
     119              75 :     NaClXMutexLock(&ref_count_mu_);
     120              75 :     if (0 == ref_count_) {
     121               0 :       NaClLog(LOG_FATAL, "DescWrapperCommon ref count already zero\n");
     122                 :     }
     123              75 :     --ref_count_;
     124              75 :     bool destroy = (0 == ref_count_);
     125              75 :     NaClXMutexUnlock(&ref_count_mu_);
     126              75 :     if (destroy) {
     127              20 :       delete this;
     128                 :     }
     129              75 :   }
     130                 : 
     131                 :  private:
     132              22 :   DescWrapperCommon() : is_initialized_(false), ref_count_(1) {
     133              22 :     NaClXMutexCtor(&ref_count_mu_);
     134              22 :   }
     135              20 :   ~DescWrapperCommon() {
     136              20 :     if (is_initialized_) {
     137              20 :       effp()->vtbl->Dtor(effp());
     138                 :     }
     139              20 :     NaClMutexDtor(&ref_count_mu_);
     140              20 :   }
     141                 : 
     142                 :   // Set up the state.  Returns true on success.
     143                 :   bool Init();
     144                 : 
     145                 :   // Boolean to indicate the object was successfully initialized.
     146                 :   bool is_initialized_;
     147                 :   // Effector for transferring descriptors.
     148                 :   struct NaClNrdXferEffector eff_;
     149                 :   // The reference count and the mutex to protect it.
     150                 :   RefCountType ref_count_;
     151                 :   struct NaClMutex ref_count_mu_;
     152                 : 
     153                 :   DISALLOW_COPY_AND_ASSIGN(DescWrapperCommon);
     154                 : };
     155                 : 
     156              22 : bool DescWrapperCommon::Init() {
     157                 :   // Set up the transfer effector.
     158              22 :   if (!NaClNrdXferEffectorCtor(&eff_)) {
     159               0 :     return false;
     160                 :   }
     161                 :   // Successfully initialized.
     162              22 :   is_initialized_ = true;
     163              22 :   return true;
     164                 : }
     165                 : 
     166              22 : DescWrapperFactory::DescWrapperFactory() {
     167              22 :   common_data_ = new(std::nothrow) DescWrapperCommon();
     168              22 :   if (NULL == common_data_) {
     169               0 :     return;
     170                 :   }
     171              22 :   if (!common_data_->Init()) {
     172               0 :     delete common_data_;
     173               0 :     common_data_ = NULL;
     174                 :   }
     175                 : }
     176                 : 
     177              20 : DescWrapperFactory::~DescWrapperFactory() {
     178              20 :   if (NULL != common_data_) {
     179              20 :     common_data_->Unref();
     180                 :   }
     181              20 : }
     182                 : 
     183               0 : int DescWrapperFactory::MakeBoundSock(DescWrapper* pair[2]) {
     184               0 :   CHECK(common_data_->is_initialized());
     185                 : 
     186               0 :   struct NaClDesc* descs[2] = { NULL, NULL };
     187               0 :   DescWrapper* tmp_pair[2] = { NULL, NULL };
     188                 : 
     189               0 :   int ret = NaClCommonDescMakeBoundSock(descs);
     190               0 :   if (0 != ret) {
     191               0 :     return ret;
     192                 :   }
     193               0 :   tmp_pair[0] = new(std::nothrow) DescWrapper(common_data_, descs[0]);
     194               0 :   if (NULL == tmp_pair[0]) {
     195               0 :     goto cleanup;
     196                 :   }
     197               0 :   descs[0] = NULL;  // DescWrapper took ownership of descs[0].
     198               0 :   tmp_pair[1] = new(std::nothrow) DescWrapper(common_data_, descs[1]);
     199               0 :   if (NULL == tmp_pair[1]) {
     200               0 :     goto cleanup;
     201                 :   }
     202               0 :   descs[1] = NULL;  // DescWrapper took ownership of descs[1].
     203               0 :   pair[0] = tmp_pair[0];
     204               0 :   pair[1] = tmp_pair[1];
     205               0 :   return 0;
     206                 : 
     207               0 :  cleanup:
     208               0 :   NaClDescSafeUnref(descs[0]);
     209               0 :   NaClDescSafeUnref(descs[1]);
     210               0 :   delete tmp_pair[0];
     211               0 :   delete tmp_pair[1];
     212               0 :   return -1;
     213                 : }
     214                 : 
     215              11 : DescWrapper* DescWrapperFactory::MakeImcSock(NaClHandle handle) {
     216                 :   struct NaClDescImcDesc* desc =
     217              11 :     reinterpret_cast<NaClDescImcDesc*>(calloc(1, sizeof *desc));
     218              11 :   if (NULL == desc) {
     219               0 :     return NULL;
     220                 :   }
     221              11 :   if (!NaClDescImcDescCtor(desc, handle)) {
     222               0 :     free(desc);
     223               0 :     return NULL;
     224                 :   }
     225                 : 
     226              11 :   return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
     227                 : }
     228                 : 
     229               0 : DescWrapper* DescWrapperFactory::MakeShm(size_t size) {
     230               0 :   CHECK(common_data_->is_initialized());
     231                 :   // HACK: there's an inlining issue with this.
     232                 :   // size_t rounded_size = NaClRoundAllocPage(size);
     233                 :   size_t rounded_size =
     234                 :       (size + NACL_MAP_PAGESIZE - 1) &
     235               0 :       ~static_cast<size_t>(NACL_MAP_PAGESIZE - 1);
     236                 :   // TODO(sehr): fix the inlining issue.
     237               0 :   NaClHandle handle = CreateMemoryObject(rounded_size, /* executable= */ false);
     238               0 :   if (kInvalidHandle == handle) {
     239               0 :     return NULL;
     240                 :   }
     241               0 :   return ImportShmHandle(handle, size);
     242                 : }
     243                 : 
     244                 : DescWrapper* DescWrapperFactory::ImportShmHandle(NaClHandle handle,
     245               0 :                                                  size_t size) {
     246                 :   struct NaClDescImcShm* desc =
     247               0 :     reinterpret_cast<NaClDescImcShm*>(calloc(1, sizeof *desc));
     248               0 :   if (NULL == desc) {
     249               0 :     return NULL;
     250                 :   }
     251               0 :   if (!NaClDescImcShmCtor(desc, handle, size)) {
     252               0 :     free(desc);
     253               0 :     return NULL;
     254                 :   }
     255                 : 
     256               0 :   return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
     257                 : }
     258                 : 
     259               0 : DescWrapper* DescWrapperFactory::ImportSyncSocketHandle(NaClHandle handle) {
     260                 :   struct NaClDescSyncSocket* desc =
     261               0 :     static_cast<NaClDescSyncSocket*>(calloc(1, sizeof *desc));
     262               0 :   if (NULL == desc) {
     263               0 :     return NULL;
     264                 :   }
     265               0 :   if (!NaClDescSyncSocketCtor(desc, handle)) {
     266               0 :     free(desc);
     267               0 :     return NULL;
     268                 :   }
     269                 : 
     270               0 :   return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
     271                 : }
     272                 : 
     273                 : #if NACL_LINUX
     274                 : DescWrapper* DescWrapperFactory::ImportSysvShm(int key, size_t size) {
     275                 :   if (kSizeTMax - NACL_PAGESIZE + 1 <= size) {
     276                 :     // Avoid overflow when rounding to the nearest 4K and casting to
     277                 :     // nacl_off64_t by preventing negative size.
     278                 :     return NULL;
     279                 :   }
     280                 :   // HACK: there's an inlining issue with using NaClRoundPage. (See above.)
     281                 :   // rounded_size = NaClRoundPage(size);
     282                 :   size_t rounded_size =
     283                 :       (size + NACL_PAGESIZE - 1) & ~static_cast<size_t>(NACL_PAGESIZE - 1);
     284                 :   struct NaClDescSysvShm* desc =
     285                 :     reinterpret_cast<NaClDescSysvShm*>(calloc(1, sizeof *desc));
     286                 :   if (NULL == desc) {
     287                 :     return NULL;
     288                 :   }
     289                 : 
     290                 :   if (!NaClDescSysvShmImportCtor(desc,
     291                 :                                  key,
     292                 :                                  static_cast<nacl_off64_t>(rounded_size))) {
     293                 :     // If rounded_size is negative due to overflow from rounding, it will be
     294                 :     // rejected here by NaClDescSysvShmImportCtor.
     295                 :     free(desc);
     296                 :     return NULL;
     297                 :   }
     298                 : 
     299                 :   return
     300                 :     MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
     301                 : }
     302                 : #endif  // NACL_LINUX
     303                 : 
     304                 : #if defined(NACL_STANDALONE)
     305                 : DescWrapper* DescWrapperFactory::ImportPepperSharedMemory(intptr_t shm_int,
     306               0 :                                                           size_t size) {
     307                 :   // PepperSharedMemory is only present in the Chrome hookup.
     308                 :   UNREFERENCED_PARAMETER(shm_int);
     309                 :   UNREFERENCED_PARAMETER(size);
     310               0 :   return NULL;
     311                 : }
     312                 : 
     313               0 : DescWrapper* DescWrapperFactory::ImportPepper2DSharedMemory(intptr_t shm_int) {
     314                 :   // Pepper2DSharedMemory is only present in the Chrome hookup.
     315                 :   UNREFERENCED_PARAMETER(shm_int);
     316               0 :   return NULL;
     317                 : }
     318                 : 
     319               0 : DescWrapper* DescWrapperFactory::ImportPepperSync(intptr_t sync_int) {
     320                 : #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
     321               0 :   base::SyncSocket* sock = reinterpret_cast<base::SyncSocket*>(sync_int);
     322               0 :   struct NaClDescSyncSocket* ss_desc = NULL;
     323               0 :   DescWrapper* wrapper = NULL;
     324                 : 
     325                 :   ss_desc = static_cast<NaClDescSyncSocket*>(
     326               0 :       calloc(1, sizeof(*ss_desc)));
     327               0 :   if (NULL == ss_desc) {
     328                 :     // TODO(sehr): Gotos are awful.  Add a scoped_ptr variant that
     329                 :     // invokes NaClDescSafeUnref.
     330               0 :     goto cleanup;
     331                 :   }
     332               0 :   if (!NaClDescSyncSocketCtor(ss_desc, sock->handle())) {
     333               0 :     free(ss_desc);
     334               0 :     ss_desc = NULL;
     335               0 :     goto cleanup;
     336                 :   }
     337               0 :   wrapper = new DescWrapper(common_data_, &ss_desc->base);
     338               0 :   if (NULL == wrapper) {
     339               0 :     goto cleanup;
     340                 :   }
     341               0 :   ss_desc = NULL;  // DescWrapper takes ownership of ss_desc.
     342               0 :   return wrapper;
     343                 : 
     344               0 :  cleanup:
     345               0 :   NaClDescSafeUnref(&ss_desc->base);
     346               0 :   return NULL;
     347                 : #else
     348                 :   UNREFERENCED_PARAMETER(sync_int);
     349                 :   return NULL;
     350                 : #endif
     351                 : }
     352                 : #endif  // NACL_STANDALONE
     353                 : 
     354               0 : DescWrapper* DescWrapperFactory::MakeGeneric(struct NaClDesc* desc) {
     355               0 :   CHECK(common_data_->is_initialized());
     356               0 :   return new(std::nothrow) DescWrapper(common_data_, desc);
     357                 : }
     358                 : 
     359                 : 
     360              24 : DescWrapper* DescWrapperFactory::MakeGenericCleanup(struct NaClDesc* desc) {
     361              24 :   CHECK(common_data_->is_initialized());
     362              24 :   DescWrapper* wrapper = new(std::nothrow) DescWrapper(common_data_, desc);
     363              24 :   if (NULL != wrapper) {
     364              24 :       return wrapper;
     365                 :   }
     366               0 :   NaClDescSafeUnref(desc);
     367               0 :   return NULL;
     368                 : }
     369                 : 
     370               0 : int DescWrapperFactory::MakeSocketPair(DescWrapper* pair[2]) {
     371               0 :   CHECK(common_data_->is_initialized());
     372               0 :   struct NaClDesc* descs[2] = { NULL, NULL };
     373               0 :   DescWrapper* tmp_pair[2] = { NULL, NULL };
     374                 : 
     375               0 :   int ret = NaClCommonDescSocketPair(descs);
     376               0 :   if (0 != ret) {
     377               0 :     return ret;
     378                 :   }
     379               0 :   tmp_pair[0] = new(std::nothrow) DescWrapper(common_data_, descs[0]);
     380               0 :   if (NULL == tmp_pair[0]) {
     381               0 :     goto cleanup;
     382                 :   }
     383               0 :   descs[0] = NULL;  // DescWrapper took ownership of descs[0].
     384               0 :   tmp_pair[1] = new(std::nothrow) DescWrapper(common_data_, descs[1]);
     385               0 :   if (NULL == tmp_pair[1]) {
     386               0 :     goto cleanup;
     387                 :   }
     388               0 :   descs[1] = NULL;  // DescWrapper took ownership of descs[1].
     389               0 :   pair[0] = tmp_pair[0];
     390               0 :   pair[1] = tmp_pair[1];
     391               0 :   return 0;
     392                 : 
     393               0 :  cleanup:
     394               0 :   NaClDescSafeUnref(descs[0]);
     395               0 :   NaClDescSafeUnref(descs[1]);
     396               0 :   delete tmp_pair[0];
     397               0 :   delete tmp_pair[1];
     398               0 :   return -1;
     399                 : }
     400                 : 
     401               0 : DescWrapper* DescWrapperFactory::MakeFileDesc(int host_os_desc, int mode) {
     402               0 :   struct NaClDesc* desc = ImportHostDescCommon(host_os_desc, mode);
     403               0 :   if (NULL == desc) {
     404               0 :     return NULL;
     405                 :   }
     406               0 :   return MakeGenericCleanup(desc);
     407                 : }
     408                 : 
     409                 : DescWrapper* DescWrapperFactory::MakeFileDescQuota(int host_os_desc,
     410                 :                                                    int mode,
     411               0 :                                                    const uint8_t* file_id) {
     412               0 :   struct NaClDesc* desc = ImportHostDescCommon(host_os_desc, mode);
     413               0 :   if (NULL == desc) {
     414               0 :     return NULL;
     415                 :   }
     416               0 :   struct NaClDesc* desc_quota = MakeQuotaCommon(file_id, desc);
     417               0 :   if (desc_quota == NULL) {
     418               0 :     NaClDescSafeUnref(desc);
     419               0 :     return NULL;
     420                 :   }
     421               0 :   return MakeGenericCleanup(desc_quota);
     422                 : }
     423                 : 
     424                 : DescWrapper* DescWrapperFactory::OpenHostFile(const char* fname,
     425                 :                                               int flags,
     426              11 :                                               int mode) {
     427              11 :   struct NaClDesc* desc = OpenHostFileCommon(fname, flags, mode);
     428              11 :   if (NULL == desc) {
     429               0 :     return NULL;
     430                 :   }
     431              11 :   return MakeGenericCleanup(desc);
     432                 : }
     433                 : 
     434                 : DescWrapper* DescWrapperFactory::OpenHostFileQuota(const char* fname,
     435                 :                                                    int flags,
     436                 :                                                    int mode,
     437               0 :                                                    const uint8_t* file_id) {
     438               0 :   struct NaClDesc* desc = OpenHostFileCommon(fname, flags, mode);
     439               0 :   if (NULL == desc) {
     440               0 :     return NULL;
     441                 :   }
     442               0 :   struct NaClDesc* desc_quota = MakeQuotaCommon(file_id, desc);
     443               0 :   if (NULL == desc_quota) {
     444               0 :     NaClDescSafeUnref(desc);
     445               0 :     return NULL;
     446                 :   }
     447               0 :   return MakeGenericCleanup(desc_quota);
     448                 : }
     449                 : 
     450               0 : DescWrapper* DescWrapperFactory::OpenRng() {
     451                 :   struct NaClDescRng* nhrp =
     452               0 :     reinterpret_cast<struct NaClDescRng*>(calloc(1, sizeof(*nhrp)));
     453               0 :   if (NULL == nhrp) {
     454               0 :     return NULL;
     455                 :   }
     456               0 :   if (!NaClDescRngCtor(nhrp)) {
     457               0 :     free(nhrp);
     458               0 :     return NULL;
     459                 :   }
     460                 : 
     461               0 :   return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(nhrp));
     462                 : }
     463                 : 
     464               0 : DescWrapper* DescWrapperFactory::MakeInvalid() {
     465                 :   struct NaClDescInvalid *desc =
     466               0 :       const_cast<NaClDescInvalid*>(NaClDescInvalidMake());
     467               0 :   if (NULL == desc) {
     468               0 :     return NULL;
     469                 :   }
     470                 : 
     471               0 :   return MakeGenericCleanup(reinterpret_cast<struct NaClDesc*>(desc));
     472                 : }
     473                 : 
     474                 : DescWrapper::DescWrapper(DescWrapperCommon* common_data,
     475              57 :                          struct NaClDesc* desc)
     476              57 :       : common_data_(common_data), desc_(desc) {
     477                 :   // DescWrapper takes ownership of desc from caller, so no Ref call here.
     478              57 :   if (NULL != common_data_) {
     479              57 :     common_data_->Ref();
     480                 :   }
     481              57 : }
     482                 : 
     483              55 : DescWrapper::~DescWrapper() {
     484              55 :   if (NULL != common_data_) {
     485              55 :     common_data_->Unref();
     486                 :   }
     487              55 :   NaClDescSafeUnref(desc_);
     488              55 :   desc_ = NULL;
     489              55 : }
     490                 : 
     491               0 : int DescWrapper::Map(void** addr, size_t* size) {
     492               0 :   return NaClDescMapDescriptor(desc_, common_data_->effp(), addr, size);
     493                 : }
     494                 : 
     495               0 : int DescWrapper::Unmap(void* start_addr, size_t len) {
     496                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     497                 :       Unmap(desc_,
     498                 :             common_data_->effp(),
     499               0 :             start_addr, len);
     500                 : }
     501                 : 
     502               0 : ssize_t DescWrapper::Read(void* buf, size_t len) {
     503                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     504               0 :       Read(desc_, buf, len);
     505                 : }
     506                 : 
     507               0 : ssize_t DescWrapper::Write(const void* buf, size_t len) {
     508                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     509               0 :       Write(desc_, buf, len);
     510                 : }
     511                 : 
     512               0 : nacl_off64_t DescWrapper::Seek(nacl_off64_t offset, int whence) {
     513                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     514                 :       Seek(desc_,
     515                 :            offset,
     516               0 :            whence);
     517                 : }
     518                 : 
     519               0 : int DescWrapper::Ioctl(int request, void* arg) {
     520                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     521               0 :       Ioctl(desc_, request, arg);
     522                 : }
     523                 : 
     524               0 : int DescWrapper::Fstat(struct nacl_abi_stat* statbuf) {
     525                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     526               0 :       Fstat(desc_, statbuf);
     527                 : }
     528                 : 
     529               0 : int DescWrapper::Close() {
     530               0 :   NaClRefCountUnref(&desc_->base);
     531               0 :   return 0;
     532                 : }
     533                 : 
     534               0 : ssize_t DescWrapper::Getdents(void* dirp, size_t count) {
     535                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     536                 :       Getdents(desc_,
     537                 :                dirp,
     538               0 :                count);
     539                 : }
     540                 : 
     541               0 : int DescWrapper::Lock() {
     542                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     543               0 :       Lock(desc_);
     544                 : }
     545                 : 
     546               0 : int DescWrapper::TryLock() {
     547                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     548               0 :       TryLock(desc_);
     549                 : }
     550                 : 
     551               0 : int DescWrapper::Unlock() {
     552                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     553               0 :       Unlock(desc_);
     554                 : }
     555                 : 
     556               0 : int DescWrapper::Wait(DescWrapper* mutex) {
     557                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     558               0 :       Wait(desc_, mutex->desc_);
     559                 : }
     560                 : 
     561                 : int DescWrapper::TimedWaitAbs(DescWrapper* mutex,
     562               0 :                               struct nacl_abi_timespec* ts) {
     563                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     564                 :       TimedWaitAbs(desc_,
     565                 :                    mutex->desc_,
     566               0 :                    ts);
     567                 : }
     568                 : 
     569               0 : int DescWrapper::Signal() {
     570                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     571               0 :       Signal(desc_);
     572                 : }
     573                 : 
     574               0 : int DescWrapper::Broadcast() {
     575                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     576               0 :       Broadcast(desc_);
     577                 : }
     578                 : 
     579               0 : ssize_t DescWrapper::SendMsg(const MsgHeader* dgram, int flags) {
     580                 :   struct NaClImcTypedMsgHdr header;
     581               0 :   ssize_t ret = -NACL_ABI_ENOMEM;
     582               0 :   nacl_abi_size_t diov_length = dgram->iov_length;
     583               0 :   nacl_abi_size_t ddescv_length = dgram->ndescv_length;
     584                 :   nacl_abi_size_t i;
     585                 : 
     586                 :   // Initialize to allow simple cleanups.
     587               0 :   header.ndescv = NULL;
     588                 :   // Allocate and copy IOV.
     589               0 :   if (kSizeTMax / sizeof(NaClImcMsgIoVec) <= diov_length) {
     590               0 :     goto cleanup;
     591                 :   }
     592                 :   header.iov = reinterpret_cast<NaClImcMsgIoVec*>(
     593               0 :       calloc(diov_length, sizeof(*(header.iov))));
     594               0 :   if (NULL == header.iov) {
     595               0 :     goto cleanup;
     596                 :   }
     597               0 :   header.iov_length = diov_length;
     598               0 :   for (i = 0; i < dgram->iov_length; ++i) {
     599               0 :     header.iov[i].base = dgram->iov[i].base;
     600               0 :     header.iov[i].length = dgram->iov[i].length;
     601                 :   }
     602                 :   // Allocate and copy the descriptor vector, removing DescWrappers.
     603               0 :   if (kHandleCountMax < dgram->ndescv_length) {
     604               0 :     goto cleanup;
     605                 :   }
     606               0 :   if (kSizeTMax / sizeof(header.ndescv[0]) <= ddescv_length) {
     607               0 :     goto cleanup;
     608                 :   }
     609                 :   header.ndescv = reinterpret_cast<NaClDesc**>(
     610               0 :       calloc(ddescv_length, sizeof(*(header.ndescv))));
     611               0 :   if (NULL == header.iov) {
     612               0 :     goto cleanup;
     613                 :   }
     614               0 :   header.ndesc_length = ddescv_length;
     615               0 :   for (i = 0; i < dgram->ndescv_length; ++i) {
     616               0 :     header.ndescv[i] = dgram->ndescv[i]->desc_;
     617                 :   }
     618                 :   // Send the message.
     619               0 :   ret = NaClImcSendTypedMessage(desc_, &header, flags);
     620                 : 
     621               0 :  cleanup:
     622               0 :   free(header.ndescv);
     623               0 :   free(header.iov);
     624               0 :   return ret;
     625                 : }
     626                 : 
     627                 : ssize_t DescWrapper::RecvMsg(MsgHeader* dgram, int flags,
     628              11 :                              struct NaClDescQuotaInterface *quota_interface) {
     629                 :   struct NaClImcTypedMsgHdr header;
     630              11 :   ssize_t ret = -NACL_ABI_ENOMEM;
     631              11 :   nacl_abi_size_t diov_length = dgram->iov_length;
     632              11 :   nacl_abi_size_t ddescv_length = dgram->ndescv_length;
     633                 :   nacl_abi_size_t i;
     634                 : 
     635                 :   // Initialize to allow simple cleanups.
     636              11 :   header.ndescv = NULL;
     637              99 :   for (i = 0; i < dgram->ndescv_length; ++i) {
     638              88 :     dgram->ndescv[i] = NULL;
     639                 :   }
     640                 : 
     641                 :   // Allocate and copy the IOV.
     642              11 :   if (kSizeTMax / sizeof(NaClImcMsgIoVec) <= diov_length) {
     643               0 :     goto cleanup;
     644                 :   }
     645                 :   header.iov = reinterpret_cast<NaClImcMsgIoVec*>(
     646              11 :       calloc(diov_length, sizeof(*(header.iov))));
     647              11 :   if (NULL == header.iov) {
     648               0 :     goto cleanup;
     649                 :   }
     650              11 :   header.iov_length = diov_length;
     651              22 :   for (i = 0; i < dgram->iov_length; ++i) {
     652              11 :     header.iov[i].base = dgram->iov[i].base;
     653              11 :     header.iov[i].length = dgram->iov[i].length;
     654                 :   }
     655                 :   // Allocate and copy the descriptor vector.
     656              11 :   if (kHandleCountMax < dgram->ndescv_length) {
     657               0 :     goto cleanup;
     658                 :   }
     659              11 :   if (kSizeTMax / sizeof(header.ndescv[0]) <= ddescv_length) {
     660               0 :     goto cleanup;
     661                 :   }
     662                 :   header.ndescv = reinterpret_cast<NaClDesc**>(
     663              11 :       calloc(ddescv_length, sizeof(*(header.ndescv))));
     664              11 :   if (NULL == header.ndescv) {
     665               0 :     goto cleanup;
     666                 :   }
     667              11 :   header.ndesc_length = ddescv_length;
     668                 :   // Receive the message.
     669              11 :   ret = NaClImcRecvTypedMessage(desc_, &header, flags, quota_interface);
     670              11 :   if (ret < 0) {
     671               0 :     goto cleanup;
     672                 :   }
     673              11 :   dgram->ndescv_length = header.ndesc_length;
     674              11 :   dgram->flags = header.flags;
     675                 :   // Copy the descriptors, creating new DescWrappers around them.
     676              22 :   for (i = 0; i < header.ndesc_length; ++i) {
     677                 :     dgram->ndescv[i] =
     678              11 :         new(std::nothrow) DescWrapper(common_data_, header.ndescv[i]);
     679              11 :     if (NULL == dgram->ndescv[i]) {
     680               0 :       goto cleanup;
     681                 :     }
     682                 :   }
     683              11 :   free(header.ndescv);
     684              11 :   free(header.iov);
     685              11 :   return ret;
     686                 : 
     687               0 :  cleanup:
     688               0 :   for (i = 0; i < ddescv_length; ++i) {
     689               0 :     delete dgram->ndescv[i];
     690                 :   }
     691               0 :   free(header.ndescv);
     692               0 :   free(header.iov);
     693               0 :   return ret;
     694                 : }
     695                 : 
     696              22 : DescWrapper* DescWrapper::Connect() {
     697                 :   struct NaClDesc* connected_desc;
     698                 :   int rv = reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     699                 :       ConnectAddr(desc_,
     700              22 :                   &connected_desc);
     701              22 :   if (0 != rv) {
     702                 :     // Connect failed.
     703               0 :     return NULL;
     704                 :   }
     705                 :   DescWrapper* wrapper =
     706              22 :       new(std::nothrow) DescWrapper(common_data_, connected_desc);
     707              22 :   if (NULL == wrapper) {
     708               0 :     NaClDescUnref(connected_desc);
     709                 :   }
     710              22 :   return wrapper;
     711                 : }
     712                 : 
     713               0 : DescWrapper* DescWrapper::Accept() {
     714                 :   struct NaClDesc* connected_desc;
     715                 :   int rv = reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     716               0 :       AcceptConn(desc_, &connected_desc);
     717               0 :   if (0 != rv) {
     718                 :     // Accept failed.
     719               0 :     return NULL;
     720                 :   }
     721                 :   DescWrapper* wrapper =
     722               0 :       new(std::nothrow) DescWrapper(common_data_, connected_desc);
     723               0 :   if (NULL == wrapper) {
     724               0 :     NaClDescUnref(connected_desc);
     725                 :   }
     726               0 :   return wrapper;
     727                 : }
     728                 : 
     729               0 : int DescWrapper::Post() {
     730                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     731               0 :       Post(desc_);
     732                 : }
     733                 : 
     734               0 : int DescWrapper::SemWait() {
     735                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     736               0 :       SemWait(desc_);
     737                 : }
     738                 : 
     739               0 : int DescWrapper::GetValue() {
     740                 :   return reinterpret_cast<struct NaClDescVtbl const *>(desc_->base.vtbl)->
     741               0 :       GetValue(desc_);
     742                 : }
     743                 : 
     744              26 : }  // namespace nacl

Generated by: LCOV version 1.7