LCOV - code coverage report
Current view: directory - src/trusted/desc - nacl_desc_quota.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 158 41 25.9 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <string.h>
       8                 : 
       9                 : #include "native_client/src/include/portability.h"
      10                 : #include "native_client/src/include/nacl_macros.h"
      11                 : 
      12                 : #include "native_client/src/shared/platform/nacl_check.h"
      13                 : #include "native_client/src/shared/platform/nacl_sync.h"
      14                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      15                 : 
      16                 : #include "native_client/src/trusted/desc/nacl_desc_quota.h"
      17                 : #include "native_client/src/trusted/desc/nacl_desc_quota_interface.h"
      18                 : 
      19                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      20                 : #include "native_client/src/trusted/desc/nrd_xfer_intern.h"
      21                 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
      22                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      23                 : 
      24                 : static struct NaClDescVtbl const kNaClDescQuotaVtbl;
      25                 : 
      26                 : int NaClDescQuotaCtor(struct NaClDescQuota           *self,
      27                 :                       struct NaClDesc                *desc,
      28                 :                       uint8_t const                  *file_id,
      29               1 :                       struct NaClDescQuotaInterface  *quota_interface) {
      30               1 :   if (!NaClDescCtor(&self->base)) {
      31               0 :     NACL_VTBL(NaClDescQuota, self) = NULL;
      32               0 :     return 0;
      33                 :   }
      34               1 :   if (!NaClMutexCtor(&self->mu)) {
      35                 :     /* do not NaClRefCountUnref, since we cannot free: caller must do that */
      36               0 :     (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
      37               0 :     return 0;
      38                 :   }
      39               1 :   self->desc = desc;  /* take ownership */
      40               1 :   memcpy(self->file_id, file_id, NACL_DESC_QUOTA_FILE_ID_LEN);
      41               1 :   if (NULL == quota_interface) {
      42               0 :     self->quota_interface = (struct NaClDescQuotaInterface *) NULL;
      43                 :   } else {
      44               1 :     self->quota_interface = NaClDescQuotaInterfaceRef(quota_interface);
      45                 :   }
      46               1 :   NACL_VTBL(NaClDesc, self) = &kNaClDescQuotaVtbl;
      47               1 :   return 1;
      48                 : }
      49                 : 
      50               1 : void NaClDescQuotaDtor(struct NaClRefCount *vself) {
      51               1 :   struct NaClDescQuota *self = (struct NaClDescQuota *) vself;
      52                 : 
      53               1 :   NaClRefCountSafeUnref((struct NaClRefCount *) self->quota_interface);
      54               1 :   NaClRefCountUnref((struct NaClRefCount *) self->desc);
      55               1 :   self->desc = NULL;
      56               1 :   NaClMutexDtor(&self->mu);
      57                 : 
      58               1 :   NACL_VTBL(NaClDesc, self) = &kNaClDescVtbl;
      59               1 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
      60               1 : }
      61                 : 
      62                 : uintptr_t NaClDescQuotaMap(struct NaClDesc          *vself,
      63                 :                            struct NaClDescEffector  *effp,
      64                 :                            void                     *start_addr,
      65                 :                            size_t                   len,
      66                 :                            int                      prot,
      67                 :                            int                      flags,
      68               0 :                            nacl_off64_t             offset) {
      69               0 :   struct NaClDescQuota *self = (struct NaClDescQuota *) vself;
      70                 : 
      71               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->
      72                 :           Map)(self->desc, effp, start_addr, len, prot, flags, offset);
      73                 : }
      74                 : 
      75                 : int NaClDescQuotaUnmapUnsafe(struct NaClDesc          *vself,
      76                 :                              struct NaClDescEffector  *effp,
      77                 :                              void                     *start_addr,
      78               0 :                              size_t                   len) {
      79               0 :   struct NaClDescQuota *self = (struct NaClDescQuota *) vself;
      80                 : 
      81               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->
      82                 :           UnmapUnsafe)(self->desc, effp, start_addr, len);
      83                 : }
      84                 : 
      85                 : int NaClDescQuotaUnmap(struct NaClDesc          *vself,
      86                 :                        struct NaClDescEffector  *effp,
      87                 :                        void                     *start_addr,
      88               0 :                        size_t                   len) {
      89               0 :   struct NaClDescQuota *self = (struct NaClDescQuota *) vself;
      90                 : 
      91               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->
      92                 :           Unmap)(self->desc, effp, start_addr, len);
      93                 : }
      94                 : 
      95                 : ssize_t NaClDescQuotaRead(struct NaClDesc *vself,
      96                 :                           void            *buf,
      97               0 :                           size_t          len) {
      98               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
      99                 : 
     100               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Read)(self->desc, buf, len);
     101                 : }
     102                 : 
     103                 : ssize_t NaClDescQuotaWrite(struct NaClDesc  *vself,
     104                 :                            void const       *buf,
     105            6554 :                            size_t           len) {
     106            6554 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     107                 :   nacl_off64_t          file_offset;
     108                 :   uint64_t              len_u64;
     109                 :   int64_t               allowed;
     110                 :   ssize_t               rv;
     111                 : 
     112            6554 :   NaClXMutexLock(&self->mu);
     113            6554 :   if (0 == len) {
     114               1 :     allowed = 0;
     115                 :   } else {
     116                 :     /*
     117                 :      * prevent another thread from doing a repositioning seek between the
     118                 :      * lseek(d,0,1) and the Write.
     119                 :      */
     120            6553 :     file_offset = (*NACL_VTBL(NaClDesc, self->desc)->Seek)(self->desc,
     121                 :                                                            0,
     122                 :                                                            SEEK_CUR);
     123            6553 :     if (file_offset < 0) {
     124               0 :       rv = (ssize_t) file_offset;
     125               0 :       goto abort;
     126                 :     }
     127                 : 
     128                 :     NACL_COMPILE_TIME_ASSERT(SIZE_T_MAX <= NACL_UMAX_VAL(uint64_t));
     129                 :     /*
     130                 :      * Write can always return a short, non-zero transfer count.
     131                 :      */
     132            6553 :     len_u64 = (uint64_t) len;
     133                 :     /* get rid of the always-true/always-false comparison warning */
     134            6553 :     if (len_u64 > NACL_MAX_VAL(int64_t)) {
     135               0 :       len = (size_t) NACL_MAX_VAL(int64_t);
     136                 :     }
     137                 : 
     138            6553 :     if (NULL == self->quota_interface) {
     139                 :       /* If there is no quota_interface, do not allow writes. */
     140               0 :       allowed = 0;
     141                 :     } else {
     142            6553 :       allowed = (*NACL_VTBL(NaClDescQuotaInterface, self->quota_interface)->
     143                 :                  WriteRequest)(self->quota_interface,
     144                 :                                self->file_id, file_offset, len);
     145                 :     }
     146            6553 :     if (allowed <= 0) {
     147               0 :       rv = -NACL_ABI_EDQUOT;
     148               0 :       goto abort;
     149                 :     }
     150                 :     /*
     151                 :      * allowed <= len should be a post-condition, but we check for
     152                 :      * it anyway.
     153                 :      */
     154            6553 :     if ((uint64_t) allowed > len) {
     155               0 :       NaClLog(LOG_WARNING,
     156                 :               ("NaClSrpcPepperWriteRequest returned an allowed quota that"
     157                 :                " is larger than that requested; reducing to original"
     158                 :                " request amount.\n"));
     159               0 :       allowed = len;
     160                 :     }
     161                 :   }
     162                 : 
     163                 :   /*
     164                 :    * It is possible for Write to write fewer than bytes than the quota
     165                 :    * that was granted, in which case quota will leak.
     166                 :    * TODO(sehr,bsy): eliminate quota leakage.
     167                 :    */
     168            6554 :   rv = (*NACL_VTBL(NaClDesc, self->desc)->Write)(self->desc,
     169                 :                                                  buf, (size_t) allowed);
     170            6554 : abort:
     171            6554 :   NaClXMutexUnlock(&self->mu);
     172            6554 :   return rv;
     173                 : }
     174                 : 
     175                 : nacl_off64_t NaClDescQuotaSeek(struct NaClDesc  *vself,
     176                 :                                nacl_off64_t     offset,
     177               1 :                                int              whence) {
     178               1 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     179                 :   nacl_off64_t          rv;
     180                 : 
     181               1 :   NaClXMutexLock(&self->mu);
     182               1 :   rv = (*NACL_VTBL(NaClDesc, self->desc)->Seek)(self->desc, offset, whence);
     183               1 :   NaClXMutexUnlock(&self->mu);
     184                 : 
     185               1 :   return rv;
     186                 : }
     187                 : 
     188                 : int NaClDescQuotaIoctl(struct NaClDesc  *vself,
     189                 :                        int              request,
     190               0 :                        void             *arg) {
     191               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     192                 : 
     193               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Ioctl)(self->desc, request, arg);
     194                 : }
     195                 : 
     196                 : int NaClDescQuotaFstat(struct NaClDesc      *vself,
     197               0 :                        struct nacl_abi_stat *statbuf) {
     198               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     199                 : 
     200               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Fstat)(self->desc, statbuf);
     201                 : }
     202                 : 
     203                 : ssize_t NaClDescQuotaGetdents(struct NaClDesc *vself,
     204                 :                               void            *dirp,
     205               0 :                               size_t          count) {
     206               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     207                 : 
     208               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Getdents)(self->desc, dirp, count);
     209                 : }
     210                 : 
     211                 : int NaClDescQuotaExternalizeSize(struct NaClDesc *vself,
     212                 :                                  size_t          *nbytes,
     213               0 :                                  size_t          *nhandles) {
     214               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     215                 :   int                   rv;
     216                 :   size_t                num_bytes;
     217                 :   size_t                num_handles;
     218                 : 
     219               0 :   if (NULL != self->quota_interface) {
     220                 :     /* Already quota-managed descriptors may not be transferred. */
     221               0 :     return -NACL_ABI_EINVAL;
     222                 :   }
     223               0 :   if (0 != (rv = (*NACL_VTBL(NaClDesc, self->desc)->
     224                 :                   ExternalizeSize)(self->desc, &num_bytes, &num_handles))) {
     225               0 :     return rv;
     226                 :   }
     227               0 :   *nbytes = num_bytes + sizeof self->file_id;
     228               0 :   *nhandles = num_handles;
     229               0 :   NaClNrdXferIncrTagOverhead(nbytes, nhandles);
     230               0 :   return 0;
     231                 : }
     232                 : 
     233                 : /*
     234                 :  * nrd_xfer tagging scheme details escapes into here.
     235                 :  */
     236                 : int NaClDescQuotaExternalize(struct NaClDesc          *vself,
     237               0 :                              struct NaClDescXferState *xfer) {
     238               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     239                 : 
     240               0 :   memcpy(xfer->next_byte, self->file_id, sizeof self->file_id);
     241               0 :   xfer->next_byte += sizeof self->file_id;
     242                 : 
     243               0 :   if (0 != NaClDescExternalizeToXferBuffer(xfer, self->desc)) {
     244               0 :     NaClLog(LOG_ERROR,
     245                 :             ("NaClDescQuotaExternalize: externalizing wrapped descriptor"
     246                 :              " type %d failed\n"),
     247                 :             NACL_VTBL(NaClDesc, self->desc)->typeTag);
     248               0 :     return -NACL_ABI_EINVAL;  /* invalid/non-transferable desc type */
     249                 :   }
     250               0 :   return 0;
     251                 : }
     252                 : 
     253                 : int NaClDescQuotaInternalize(struct NaClDesc               **out_desc,
     254                 :                              struct NaClDescXferState      *xfer,
     255               0 :                              struct NaClDescQuotaInterface *quota_interface) {
     256               0 :   int                   rv = -NACL_ABI_EIO;
     257                 :   uint8_t               file_id[NACL_DESC_QUOTA_FILE_ID_LEN];
     258               0 :   struct NaClDescQuota  *out = NULL;
     259                 :   struct NaClDesc       *wrapped_desc;
     260                 : 
     261               0 :   if (NULL == (out = malloc(sizeof *out))) {
     262               0 :     rv = -NACL_ABI_ENOMEM;
     263               0 :     goto cleanup;
     264                 :   }
     265               0 :   memcpy(file_id, xfer->next_byte, sizeof file_id);
     266               0 :   xfer->next_byte += sizeof file_id;
     267                 : 
     268               0 :   if (1 != NaClDescInternalizeFromXferBuffer(&wrapped_desc, xfer,
     269                 :                                              quota_interface)) {
     270               0 :     rv = -NACL_ABI_EIO;
     271               0 :     goto cleanup;
     272                 :   }
     273               0 :   if (!NaClDescQuotaCtor(out, wrapped_desc, file_id, quota_interface)) {
     274               0 :     rv = -NACL_ABI_ENOMEM;
     275               0 :     goto cleanup_wrapped;
     276                 : 
     277                 :   }
     278                 : 
     279               0 :   *out_desc = (struct NaClDesc *) out;
     280               0 :   rv = 0;
     281                 : 
     282               0 : cleanup_wrapped:
     283               0 :   if (0 != rv) {
     284               0 :     NaClDescUnref(wrapped_desc);
     285                 :   }
     286                 : 
     287               0 : cleanup:
     288               0 :   if (0 != rv) {
     289               0 :     free(out);
     290                 :   }
     291               0 :   return rv;
     292                 : }
     293                 : 
     294               0 : int NaClDescQuotaLock(struct NaClDesc *vself) {
     295               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     296                 : 
     297               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Lock)(self->desc);
     298                 : }
     299                 : 
     300               0 : int NaClDescQuotaTryLock(struct NaClDesc *vself) {
     301               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     302                 : 
     303               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->TryLock)(self->desc);
     304                 : }
     305                 : 
     306               0 : int NaClDescQuotaUnlock(struct NaClDesc *vself) {
     307               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     308                 : 
     309               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Unlock)(self->desc);
     310                 : }
     311                 : 
     312                 : int NaClDescQuotaWait(struct NaClDesc *vself,
     313               0 :                       struct NaClDesc *mutex) {
     314               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     315                 : 
     316               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Wait)(self->desc, mutex);
     317                 : }
     318                 : 
     319                 : int NaClDescQuotaTimedWaitAbs(struct NaClDesc                *vself,
     320                 :                               struct NaClDesc                *mutex,
     321               0 :                               struct nacl_abi_timespec const *ts) {
     322               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     323                 : 
     324               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->TimedWaitAbs)(self->desc, mutex,
     325                 :                                                           ts);
     326                 : }
     327                 : 
     328               0 : int NaClDescQuotaSignal(struct NaClDesc *vself) {
     329               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     330                 : 
     331               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Signal)(self->desc);
     332                 : }
     333                 : 
     334               0 : int NaClDescQuotaBroadcast(struct NaClDesc *vself) {
     335               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     336                 : 
     337               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Broadcast)(self->desc);
     338                 : }
     339                 : 
     340                 : ssize_t NaClDescQuotaSendMsg(struct NaClDesc                *vself,
     341                 :                              struct NaClMessageHeader const *dgram,
     342               0 :                              int                            flags) {
     343               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     344                 : 
     345               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->SendMsg)(self->desc, dgram, flags);
     346                 : }
     347                 : 
     348                 : ssize_t NaClDescQuotaRecvMsg(struct NaClDesc           *vself,
     349                 :                              struct NaClMessageHeader  *dgram,
     350               0 :                              int                       flags) {
     351               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     352                 : 
     353               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->RecvMsg)(self->desc, dgram, flags);
     354                 : }
     355                 : 
     356                 : int NaClDescQuotaConnectAddr(struct NaClDesc *vself,
     357               0 :                              struct NaClDesc **result) {
     358               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     359                 : 
     360               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->ConnectAddr)(self->desc, result);
     361                 : }
     362                 : 
     363                 : int NaClDescQuotaAcceptConn(struct NaClDesc *vself,
     364               0 :                             struct NaClDesc **result) {
     365               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     366                 : 
     367               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->AcceptConn)(self->desc, result);
     368                 : }
     369                 : 
     370               0 : int NaClDescQuotaPost(struct NaClDesc *vself) {
     371               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     372                 : 
     373               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->Post)(self->desc);
     374                 : }
     375                 : 
     376               0 : int NaClDescQuotaSemWait(struct NaClDesc *vself) {
     377               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     378                 : 
     379               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->SemWait)(self->desc);
     380                 : }
     381                 : 
     382               0 : int NaClDescQuotaGetValue(struct NaClDesc *vself) {
     383               0 :   struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
     384                 : 
     385               0 :   return (*NACL_VTBL(NaClDesc, self->desc)->GetValue)(self->desc);
     386                 : }
     387                 : 
     388                 : 
     389                 : static struct NaClDescVtbl const kNaClDescQuotaVtbl = {
     390                 :   {
     391                 :     NaClDescQuotaDtor,
     392                 :   },
     393                 :   NaClDescQuotaMap,
     394                 :   NaClDescQuotaUnmapUnsafe,
     395                 :   NaClDescQuotaUnmap,
     396                 :   NaClDescQuotaRead,
     397                 :   NaClDescQuotaWrite,
     398                 :   NaClDescQuotaSeek,
     399                 :   NaClDescQuotaIoctl,
     400                 :   NaClDescQuotaFstat,
     401                 :   NaClDescQuotaGetdents,
     402                 :   NACL_DESC_QUOTA,
     403                 :   NaClDescQuotaExternalizeSize,
     404                 :   NaClDescQuotaExternalize,
     405                 :   NaClDescQuotaLock,
     406                 :   NaClDescQuotaTryLock,
     407                 :   NaClDescQuotaUnlock,
     408                 :   NaClDescQuotaWait,
     409                 :   NaClDescQuotaTimedWaitAbs,
     410                 :   NaClDescQuotaSignal,
     411                 :   NaClDescQuotaBroadcast,
     412                 :   NaClDescQuotaSendMsg,
     413                 :   NaClDescQuotaRecvMsg,
     414                 :   NaClDescQuotaConnectAddr,
     415                 :   NaClDescQuotaAcceptConn,
     416                 :   NaClDescQuotaPost,
     417                 :   NaClDescQuotaSemWait,
     418                 :   NaClDescQuotaGetValue,
     419                 : };

Generated by: LCOV version 1.7