LCOV - code coverage report
Current view: directory - src/trusted/service_runtime/fs - obj_proxy.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 166 119 71.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 Object Proxy.  Used for the NaCl file system
       9                 :  * and as a generic object proxy mechanism.
      10                 :  */
      11                 : 
      12                 : #include "native_client/src/include/portability.h"
      13                 : 
      14                 : #include <string.h>
      15                 : 
      16                 : #include "native_client/src/shared/platform/nacl_log.h"
      17                 : #include "native_client/src/trusted/service_runtime/fs/obj_proxy.h"
      18                 : 
      19                 : #define PARANOID  1
      20                 : /* #define DEBUG  1 */
      21                 : 
      22                 : /* private */
      23                 : struct NaClObjProxyEntry {
      24                 :   void    *obj;
      25                 :   uint8_t name[1];  /* NB: actual allocated size is larger */
      26                 : };
      27                 : 
      28                 : 
      29                 : /*
      30                 :  * The hash functor class for object->name mapping is the trivial
      31                 :  * subclass of NaClHashFunctor: the virtual functions do not need
      32                 :  * access to any instance data.
      33                 :  */
      34                 : 
      35              48 : static void NaClObjProxyFunctorDtor(struct NaClCmpFunctor *vself) {
      36                 :   UNREFERENCED_PARAMETER(vself);
      37                 :   return;
      38                 : }
      39                 : 
      40                 : 
      41                 : static int NaClObjProxyObjCmp(struct NaClCmpFunctor *vself,
      42                 :                               void                  *vlhs,
      43           98280 :                               void                  *vrhs) {
      44           98280 :   struct NaClObjProxyEntry *lhs = (struct NaClObjProxyEntry *) vlhs;
      45           98280 :   struct NaClObjProxyEntry *rhs = (struct NaClObjProxyEntry *) vrhs;
      46                 : 
      47                 :   UNREFERENCED_PARAMETER(vself);
      48           98280 :   return lhs->obj != rhs->obj;
      49                 : }
      50                 : 
      51                 : 
      52                 : static uintptr_t NaClObjProxyObjHash(struct NaClHashFunctor *vself,
      53          267432 :                                      void                   *ventry) {
      54          267432 :   struct NaClObjProxyEntry *entry = (struct NaClObjProxyEntry *) ventry;
      55                 : 
      56                 :   UNREFERENCED_PARAMETER(vself);
      57          267432 :   return (uintptr_t) entry->obj;
      58                 : }
      59                 : 
      60                 : 
      61                 : static struct NaClHashFunctorVtbl const kNaClObjProxyObjHashFunctorVtbl = {
      62                 :   {
      63                 :     NaClObjProxyFunctorDtor,  /* .base.Dtor */
      64                 :     NaClObjProxyObjCmp,       /* .base.OrderCmp */
      65                 :   },
      66                 :   NaClObjProxyObjHash,        /* .Hash */
      67                 : };
      68                 : 
      69                 : 
      70              24 : static int NaClObjProxyObjFunctorCtor(struct NaClHashFunctor  *self) {
      71              24 :   self->vtbl = &kNaClObjProxyObjHashFunctorVtbl;
      72              24 :   return 1;
      73                 : }
      74                 : 
      75                 : /*
      76                 :  * The hash functor for the name->object mapping requires instance
      77                 :  * data: the virtual functions need to know the name length.
      78                 :  */
      79                 : 
      80                 : struct NaClObjProxyNameFunctor {
      81                 :   struct NaClHashFunctor  base;
      82                 :   struct NaClObjProxy     *info;
      83                 : };
      84                 : 
      85                 : 
      86                 : static int NaClObjProxyNameCmp(struct NaClCmpFunctor *vself,
      87          220497 :                                void *vlhs, void *vrhs) {
      88                 :   struct NaClObjProxyNameFunctor *self
      89          220497 :       = (struct NaClObjProxyNameFunctor *) vself;
      90                 : 
      91          220497 :   struct NaClObjProxyEntry *lhs = (struct NaClObjProxyEntry *) vlhs;
      92          220497 :   struct NaClObjProxyEntry *rhs = (struct NaClObjProxyEntry *) vrhs;
      93                 : 
      94          220497 :   return memcmp(lhs->name, rhs->name, self->info->name_bytes);
      95                 : }
      96                 : 
      97                 : static uintptr_t NaClObjProxyNameHash(struct NaClHashFunctor *vself,
      98          267432 :                                       void *ventry) {
      99                 :   struct NaClObjProxyNameFunctor *self
     100          267432 :       = (struct NaClObjProxyNameFunctor *) vself;
     101          267432 :   struct NaClObjProxyEntry *entry = (struct NaClObjProxyEntry *) ventry;
     102                 : 
     103                 :   uintptr_t h;
     104                 :   int       i;
     105                 : 
     106         5749788 :   for (i = self->info->name_bytes, h = 0; --i >= 0; ) {
     107         5214924 :     h = 17 * h + 3 * entry->name[i];  /* need better mixing? */
     108                 :   }
     109          267432 :   return h;
     110                 : }
     111                 : 
     112                 : 
     113                 : struct NaClHashFunctorVtbl const kNaClObjProxyNameHashFunctorVtbl = {
     114                 :   {
     115                 :     NaClObjProxyFunctorDtor,  /* .base.Dtor */
     116                 :     NaClObjProxyNameCmp,      /* .base.OrderCmp */
     117                 :   },
     118                 :   NaClObjProxyNameHash,       /* .Hash */
     119                 : };
     120                 : 
     121                 : 
     122                 : static int NaClObjProxyNameFunctorCtor(struct NaClObjProxyNameFunctor  *self,
     123              24 :                                        struct NaClObjProxy             *info) {
     124              24 :   self->base.vtbl = &kNaClObjProxyNameHashFunctorVtbl;
     125              24 :   self->info = info;
     126              24 :   return 1;
     127                 : }
     128                 : 
     129                 : 
     130                 : int NaClObjProxyCtor(struct NaClObjProxy    *self,
     131                 :                      struct NaClSecureRngIf *rng,
     132              24 :                      int                    name_bytes) {
     133              24 :   int                             rv = 0;
     134              24 :   struct NaClHashFunctor          *obj2name_functor = NULL;
     135              24 :   struct NaClObjProxyNameFunctor  *name2obj_functor = NULL;
     136              24 :   struct NaClContainerHashTbl     *o2n = NULL;
     137              24 :   struct NaClContainerHashTbl     *n2o = NULL;
     138              24 :   struct NaClObjProxyEntry        *key = NULL;
     139                 : 
     140              24 :   self->obj_to_name = NULL;
     141              24 :   self->name_to_obj = NULL;
     142              24 :   self->obj_to_name_functor = NULL;
     143              24 :   self->name_to_obj_functor = NULL;
     144                 : 
     145              24 :   if (!NaClMutexCtor(&self->mu)) {
     146               0 :     goto cleanup;
     147                 :   }
     148                 : 
     149              24 :   obj2name_functor = malloc(sizeof *obj2name_functor);
     150              24 :   if (NULL == obj2name_functor) {
     151               0 :     goto cleanup;
     152                 :   }
     153              24 :   if (!NaClObjProxyObjFunctorCtor(obj2name_functor)) {
     154               0 :     goto cleanup;
     155                 :   }
     156              24 :   self->obj_to_name_functor = (struct NaClHashFunctor *) obj2name_functor;
     157              24 :   obj2name_functor = NULL;
     158                 : 
     159              24 :   name2obj_functor = malloc(sizeof *name2obj_functor);
     160              24 :   if (NULL == name2obj_functor) {
     161               0 :     goto cleanup;
     162                 :   }
     163              24 :   if (!NaClObjProxyNameFunctorCtor(name2obj_functor, self)) {
     164               0 :     goto cleanup;
     165                 :   }
     166              24 :   self->name_to_obj_functor = (struct NaClHashFunctor *) name2obj_functor;
     167              24 :   name2obj_functor = NULL;
     168                 : 
     169              24 :   o2n = malloc(sizeof *o2n);
     170              24 :   if (NULL == o2n) {
     171               0 :     goto cleanup;
     172                 :   }
     173              24 :   n2o = malloc(sizeof *n2o);
     174              24 :   if (NULL == n2o) {
     175               0 :     goto cleanup;
     176                 :   }
     177              24 :   key = malloc(sizeof *key + name_bytes);
     178              24 :   if (!NaClContainerHashTblCtor(o2n, self->obj_to_name_functor, 257)) {
     179               0 :     goto cleanup;
     180                 :   }
     181              24 :   self->obj_to_name = (struct NaClContainer *) o2n;
     182              24 :   o2n = NULL;
     183              24 :   if (!NaClContainerHashTblCtor(n2o, self->name_to_obj_functor, 257)) {
     184               0 :     goto cleanup;
     185                 :   }
     186              24 :   self->name_to_obj = (struct NaClContainer *) n2o;
     187              24 :   n2o = NULL;
     188              24 :   self->name_bytes = name_bytes;
     189              24 :   self->key = key;
     190              24 :   self->rng = rng;
     191              24 :   rv = 1;
     192              24 : cleanup:
     193              24 :   if (!rv) {
     194               0 :     free(obj2name_functor);
     195               0 :     if (NULL != self->obj_to_name_functor) {
     196               0 :       ((*self->obj_to_name_functor->vtbl->base.Dtor)
     197                 :        ((struct NaClCmpFunctor *) self->obj_to_name_functor));
     198               0 :       free(self->obj_to_name_functor);
     199               0 :       self->obj_to_name_functor = NULL;
     200                 :     }
     201               0 :     free(name2obj_functor);
     202               0 :     if (NULL != self->name_to_obj_functor) {
     203               0 :       ((*self->name_to_obj_functor->vtbl->base.Dtor)
     204                 :        ((struct NaClCmpFunctor *) self->name_to_obj_functor));
     205               0 :       self->name_to_obj_functor = NULL;
     206                 :     }
     207               0 :     free(o2n);
     208               0 :     if (NULL != self->obj_to_name) {
     209               0 :       (*self->obj_to_name->vtbl->Dtor)(self->obj_to_name);
     210               0 :       free(self->obj_to_name);
     211               0 :       self->obj_to_name = NULL;
     212                 :     }
     213               0 :     free(n2o);
     214               0 :     if (NULL != self->name_to_obj) {
     215               0 :       (*self->name_to_obj->vtbl->Dtor)(self->name_to_obj);
     216               0 :       free(self->name_to_obj);
     217               0 :       self->name_to_obj = NULL;
     218                 :     }
     219               0 :     free(key);
     220               0 :     NaClMutexDtor(&self->mu);
     221                 :   }
     222              24 :   return rv;
     223                 : }
     224                 : 
     225                 : 
     226              24 : void NaClObjProxyDtor(struct NaClObjProxy *self) {
     227              24 :   ((*self->obj_to_name_functor->vtbl->base.Dtor)
     228                 :    ((struct NaClCmpFunctor *) self->obj_to_name_functor));
     229              24 :   ((*self->name_to_obj_functor->vtbl->base.Dtor)
     230                 :    ((struct NaClCmpFunctor *) self->name_to_obj_functor));
     231              24 :   (*self->name_to_obj->vtbl->Dtor)(self->name_to_obj);
     232              24 :   free(self->name_to_obj);
     233              24 :   (*self->obj_to_name->vtbl->Dtor)(self->obj_to_name);
     234              24 :   free(self->obj_to_name);
     235              24 :   free(self->key);
     236              24 :   NaClMutexDtor(&self->mu);
     237              24 : }
     238                 : 
     239                 : 
     240                 : uint8_t const *NaClObjProxyFindNameByObj(struct NaClObjProxy *self,
     241          172008 :                                          void                *obj) {
     242          172008 :   struct NaClObjProxyEntry        *found = NULL;
     243                 :   struct NaClContainerHashTblIter iter;
     244          172008 :   uint8_t const                   *rv = NULL;
     245                 : 
     246          172008 :   NaClXMutexLock(&self->mu);
     247          172008 :   self->key->obj = obj;
     248          172008 :   (*self->obj_to_name->vtbl->Find)(self->obj_to_name,
     249                 :                                    self->key,
     250                 :                                    (struct NaClContainerIter *) &iter);
     251          172008 :   if (!(*iter.base.vtbl->AtEnd)((struct NaClContainerIter *) &iter)) {
     252           98280 :     found = ((struct NaClObjProxyEntry *)
     253                 :              (*iter.base.vtbl->Star)((struct NaClContainerIter *) &iter));
     254           98280 :     rv = found->name;
     255                 :   }
     256          172008 :   NaClXMutexUnlock(&self->mu);
     257                 : 
     258          172008 :   return rv;
     259                 : }
     260                 : 
     261                 : 
     262                 : int NaClObjProxyFindObjByName(struct NaClObjProxy *self,
     263                 :                               uint8_t const       *name,
     264          172008 :                               void                **out) {
     265          172008 :   struct NaClObjProxyEntry        *found = NULL;
     266                 :   struct NaClContainerHashTblIter iter;
     267          172008 :   int                             rv = 0;
     268                 : 
     269          172008 :   NaClXMutexLock(&self->mu);
     270          172008 :   memcpy(self->key->name, name, self->name_bytes);
     271          172008 :   (*self->name_to_obj->vtbl->Find)(self->name_to_obj,
     272                 :                                    self->key,
     273                 :                                    (struct NaClContainerIter *) &iter);
     274          172008 :   if (!(*iter.base.vtbl->AtEnd)((struct NaClContainerIter *) &iter)) {
     275           98280 :     found = ((struct NaClObjProxyEntry *)
     276                 :              (*iter.base.vtbl->Star)((struct NaClContainerIter *) &iter));
     277           98280 :     *out = found->obj;
     278                 : #if DEBUG
     279                 :     printf("ObjByName %d: %02x%02x%02x...\n", (int) found->obj,
     280                 :            self->key->name[0], self->key->name[1], self->key->name[2]);
     281                 : #endif
     282           98280 :     rv = 1;
     283                 :   }
     284          172008 :   NaClXMutexUnlock(&self->mu);
     285          172008 :   return rv;
     286                 : }
     287                 : 
     288                 : 
     289           49152 : uint8_t const *NaClObjProxyInsert(struct NaClObjProxy *self, void *obj) {
     290           49152 :   struct NaClObjProxyEntry  *entry = NULL;
     291           49152 :   struct NaClObjProxyEntry  *entry2 = NULL;
     292           49152 :   uint8_t const             *rv = NULL;
     293                 : #if PARANOID
     294                 :   void                      *out;
     295                 : 
     296           49152 :   if (NULL != NaClObjProxyFindNameByObj(self, obj)) {
     297               0 :     return rv;
     298                 :   }
     299                 : #endif
     300                 : 
     301           49152 :   entry = malloc(sizeof *entry + self->name_bytes);
     302           49152 :   if (NULL == entry) {
     303               0 :     goto cleanup;
     304                 :   }
     305           49152 :   entry2 = malloc(sizeof *entry2 + self->name_bytes);
     306           49152 :   if (NULL == entry2) {
     307               0 :     free(entry);
     308               0 :     goto cleanup;
     309                 :   }
     310           49152 :   entry->obj = obj;
     311                 : #if PARANOID
     312                 :   do {
     313                 : #endif
     314           49152 :     (*self->rng->vtbl->GenBytes)(self->rng,
     315                 :                                  entry->name, self->name_bytes);
     316                 : #if PARANOID
     317           49152 :   } while (NaClObjProxyFindObjByName(self, entry->name, &out));
     318                 : #endif
     319           49152 :   memcpy(entry2, entry, (sizeof *entry) + self->name_bytes);
     320                 : #if DEBUG
     321                 :     printf("entry: %d: %02x%02x%02x...\n", (int) entry->obj,
     322                 :            entry->name[0], entry->name[1], entry->name[2]);
     323                 :     printf("entry2: %d: %02x%02x%02x...\n", (int) entry2->obj,
     324                 :            entry2->name[0], entry2->name[1], entry2->name[2]);
     325                 : #endif
     326                 : 
     327           49152 :   NaClXMutexLock(&self->mu);
     328           49152 :   (*self->obj_to_name->vtbl->Insert)(self->obj_to_name, entry);
     329           49152 :   (*self->name_to_obj->vtbl->Insert)(self->name_to_obj, entry2);
     330           49152 :   NaClXMutexUnlock(&self->mu);
     331                 : 
     332           49152 :   rv = entry->name;
     333           49152 : cleanup:
     334           49152 :   return rv;
     335                 : }
     336                 : 
     337                 : 
     338               0 : int NaClObjProxyRemove(struct NaClObjProxy *self, void *obj) {
     339                 :   /*
     340                 :    * must first find the entry so we know its randomly assigned name,
     341                 :    * then delete from name_to_obj before deleting from obj_to_name.
     342                 :    */
     343                 :   struct NaClContainerHashTblIter o2niter;
     344                 :   struct NaClObjProxyEntry        *entry;
     345                 :   struct NaClContainerHashTblIter n2oiter;
     346                 : 
     347               0 :   self->key->obj = obj;
     348                 : 
     349               0 :   (*self->obj_to_name->vtbl->Find)(self->obj_to_name,
     350                 :                                    self->key,
     351                 :                                    (struct NaClContainerIter *) &o2niter);
     352               0 :   if ((*o2niter.base.vtbl->AtEnd)((struct NaClContainerIter *) &o2niter)) {
     353               0 :     return 0;  /* not found */
     354                 :   }
     355               0 :   entry = ((struct NaClObjProxyEntry *)
     356                 :            (*o2niter.base.vtbl->Star)((struct NaClContainerIter *) &o2niter));
     357               0 :   (*self->name_to_obj->vtbl->Find)(self->name_to_obj,
     358                 :                                    entry,
     359                 :                                    (struct NaClContainerIter *) &n2oiter);
     360               0 :   if ((*n2oiter.base.vtbl->AtEnd)((struct NaClContainerIter *) &n2oiter)) {
     361               0 :     NaClLog(LOG_FATAL, "object %08"NACL_PRIxPTR
     362                 :             " found in o2n tbl, but not in n2o\n",
     363                 :             (uintptr_t) obj);
     364               0 :     return 0;  /* internal error! */
     365                 :   }
     366               0 :   (*o2niter.base.vtbl->Erase)((struct NaClContainerIter *) &o2niter);
     367               0 :   (*n2oiter.base.vtbl->Erase)((struct NaClContainerIter *) &n2oiter);
     368                 : 
     369               0 :   return 1;
     370                 : }

Generated by: LCOV version 1.7