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 : }
|