Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: src/trusted/service_runtime/name_service/name_service.c

Issue 891603002: Removes the name service from the service runtime (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Fixes code review comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include <string.h>
8
9 #include "native_client/src/include/portability.h"
10 #include "native_client/src/include/portability_string.h"
11
12 #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
13
14 #include "native_client/src/public/name_service.h"
15
16 #include "native_client/src/shared/platform/nacl_log.h"
17 #include "native_client/src/shared/platform/nacl_sync.h"
18 #include "native_client/src/shared/platform/nacl_sync_checked.h"
19
20 #include "native_client/src/shared/srpc/nacl_srpc.h"
21
22 #include "native_client/src/trusted/desc/nacl_desc_base.h"
23 #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
24 #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
25 #include "native_client/src/trusted/desc/nrd_xfer.h"
26
27 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
28 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
29
30 #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
31 #include "native_client/src/trusted/simple_service/nacl_simple_ltd_service.h"
32 #include "native_client/src/trusted/threading/nacl_thread_interface.h"
33
34
35 /*
36 * Name service is a linear linked list. We could use a hash
37 * container eventually, but performance is not a goal for this simple
38 * bootstrap name service. Static entry and factory-based generation
39 * are mutually exclusive; the |factory| function is used iff |entry|
40 * is NULL. Client code is expected to cache lookup results.
41 */
42 struct NaClNameServiceEntry {
43 struct NaClNameServiceEntry *next;
44 char const *name;
45 int mode;
46 struct NaClDesc *entry; /* static entry, or, ... */
47
48 NaClNameServiceFactoryFn_t factory;
49 void *state;
50 };
51
52 struct NaClSrpcHandlerDesc const kNaClNameServiceHandlers[];
53 /* fwd */
54
55 int NaClNameServiceCtor(struct NaClNameService *self,
56 NaClThreadIfFactoryFunction thread_factory_fn,
57 void *thread_factory_data) {
58 int retval = 0; /* fail */
59
60 NaClLog(4, "Entered NaClNameServiceCtor\n");
61 if (!NaClSimpleLtdServiceCtor(&self->base,
62 kNaClNameServiceHandlers,
63 NACL_NAME_SERVICE_CONNECTION_MAX,
64 thread_factory_fn,
65 thread_factory_data)) {
66 NaClLog(4, "NaClSimpleLtdServiceCtor failed\n");
67 goto done;
68 }
69 if (!NaClMutexCtor(&self->mu)) {
70 NaClLog(4, "NaClMutexCtor failed\n");
71 goto abort_mu;
72 }
73 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl *)
74 &kNaClNameServiceVtbl;
75 /* success return path */
76 self->head = (struct NaClNameServiceEntry *) NULL;
77 retval = 1;
78 goto done;
79
80 /* cleanup unwind */
81 abort_mu: /* mutex ctor failed */
82 (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
83 done:
84 return retval;
85 }
86
87 void NaClNameServiceDtor(struct NaClRefCount *vself) {
88 struct NaClNameService *self = (struct NaClNameService *) vself;
89
90 struct NaClNameServiceEntry *p;
91 struct NaClNameServiceEntry *next;
92
93 for (p = self->head; NULL != p; p = next) {
94 next = p->next;
95 if (NULL != p->entry) {
96 NaClRefCountUnref((struct NaClRefCount *) p->entry);
97 } else {
98 /*
99 * Tell the factory fn that this particular use can be GC'd.
100 */
101 (void) (*p->factory)(p->state, p->name, 0, (struct NaClDesc **) NULL);
102 }
103 free(p);
104 }
105 NaClMutexDtor(&self->mu);
106 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl *)
107 &kNaClSimpleLtdServiceVtbl;
108 (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
109 }
110
111 static struct NaClNameServiceEntry **NameServiceSearch(
112 struct NaClNameServiceEntry **hd,
113 char const *name) {
114 while (NULL != *hd && 0 != strcmp((*hd)->name, name)) {
115 hd = &(*hd)->next;
116 }
117 return hd;
118 }
119
120
121 int NaClNameServiceCreateDescEntry(
122 struct NaClNameService *nnsp,
123 char const *name,
124 int mode,
125 struct NaClDesc *new_desc) {
126 int retval = NACL_NAME_SERVICE_INSUFFICIENT_RESOURCES;
127 struct NaClNameServiceEntry *name_entry = NULL;
128 struct NaClNameServiceEntry *found = NULL;
129 char *dup_name = STRDUP(name);
130
131 NaClLog(3,
132 "NaClNameServiceCreateDescEntry: entering %s, %d (0x%x)\n",
133 name,
134 mode, mode);
135 /*
136 * common case is insertion success, so we pre-allocate memory
137 * (strdup, malloc) to avoid doing memory allocations while holding
138 * the name service lock.
139 */
140 if (NULL == dup_name) {
141 goto dup_failed;
142 }
143 name_entry = (struct NaClNameServiceEntry *) malloc(sizeof *name_entry);
144 if (NULL == name_entry) {
145 goto entry_alloc_failed;
146 }
147
148 NaClXMutexLock(&nnsp->mu);
149 found = *NameServiceSearch(&nnsp->head, name);
150 if (NULL != found) {
151 retval = NACL_NAME_SERVICE_DUPLICATE_NAME;
152 goto unlock_and_cleanup;
153 }
154 name_entry->next = nnsp->head;
155 name_entry->name = dup_name;
156 dup_name = (char *) NULL;
157 name_entry->mode = mode;
158 name_entry->entry = new_desc;
159 name_entry->factory = (NaClNameServiceFactoryFn_t) NULL;
160 name_entry->state = (void *) NULL;
161 nnsp->head = name_entry;
162 name_entry = NULL;
163 retval = NACL_NAME_SERVICE_SUCCESS;
164
165 unlock_and_cleanup:
166 NaClXMutexUnlock(&nnsp->mu);
167 free(name_entry);
168 entry_alloc_failed:
169 free(dup_name);
170 dup_failed:
171 return retval;
172 }
173
174 int NaClNameServiceCreateFactoryEntry(
175 struct NaClNameService *nnsp,
176 char const *name,
177 NaClNameServiceFactoryFn_t factory_fn,
178 void *factory_state) {
179 int retval = NACL_NAME_SERVICE_INSUFFICIENT_RESOURCES;
180 struct NaClNameServiceEntry *name_entry = NULL;
181 struct NaClNameServiceEntry *found = NULL;
182 char *dup_name = STRDUP(name);
183
184 NaClLog(3,
185 ("NaClNameServiceCreateFactoryEntry: entering %s,"
186 " 0x%"NACL_PRIxPTR", 0x%"NACL_PRIxPTR"\n"),
187 name,
188 (uintptr_t) factory_fn,
189 (uintptr_t) factory_state);
190 /*
191 * common case is insertion success, so we pre-allocate memory
192 * (strdup, malloc) to avoid doing memory allocation while holding
193 * the name service lock.
194 */
195 if (NULL == dup_name) {
196 goto dup_failed;
197 }
198 name_entry = (struct NaClNameServiceEntry *) malloc(sizeof *name_entry);
199 if (NULL == name_entry) {
200 goto entry_alloc_failed;
201 }
202
203 NaClXMutexLock(&nnsp->mu);
204 found = *NameServiceSearch(&nnsp->head, name);
205 if (NULL != found) {
206 retval = NACL_NAME_SERVICE_DUPLICATE_NAME;
207 goto unlock_and_cleanup;
208 }
209 name_entry->next = nnsp->head;
210 name_entry->name = dup_name;
211 dup_name = (char *) NULL;
212 name_entry->entry = (struct NaClDesc *) NULL;
213 name_entry->factory = factory_fn;
214 name_entry->state = factory_state;
215 nnsp->head = name_entry;
216 name_entry = NULL;
217 retval = NACL_NAME_SERVICE_SUCCESS;
218
219 unlock_and_cleanup:
220 NaClXMutexUnlock(&nnsp->mu);
221 free(name_entry);
222 entry_alloc_failed:
223 free(dup_name);
224 dup_failed:
225 return retval;
226 }
227
228 int NaClNameServiceResolveName(struct NaClNameService *nnsp,
229 char const *name,
230 int flags,
231 struct NaClDesc **out) {
232 struct NaClNameServiceEntry *nnsep;
233 int status = NACL_NAME_SERVICE_NAME_NOT_FOUND;
234
235 NaClLog(3,
236 "NaClNameServiceResolveName: looking up %s, flags %d (0x%x)\n",
237 name,
238 flags, flags);
239 if (0 != (flags & ~NACL_ABI_O_ACCMODE)) {
240 NaClLog(2, "NaClNameServiceResolveName: bad flags!\n");
241 status = NACL_NAME_SERVICE_PERMISSION_DENIED;
242 goto quit;
243 }
244
245 NaClXMutexLock(&nnsp->mu);
246 nnsep = *NameServiceSearch(&nnsp->head, name);
247 if (NULL != nnsep) {
248 if (NULL != nnsep->entry) {
249 NaClLog(3,
250 "NaClNameServiceResolveName: found %s, mode %d (0x%x)\n",
251 name,
252 nnsep->mode, nnsep->mode);
253 /* check flags against nnsep->mode */
254 NaClLog(4,
255 ("NaClNameServiceResolveName: checking mode/flags"
256 " compatibility\n"));
257 switch (flags) {
258 case NACL_ABI_O_RDONLY:
259 if (NACL_ABI_O_WRONLY == nnsep->mode) {
260 status = NACL_NAME_SERVICE_PERMISSION_DENIED;
261 NaClLog(4,
262 "NaClNameServiceResolveName: incompatible,"
263 " not readable\n");
264 goto unlock_and_quit;
265 }
266 break;
267 case NACL_ABI_O_WRONLY:
268 if (NACL_ABI_O_RDONLY == nnsep->mode) {
269 status = NACL_NAME_SERVICE_PERMISSION_DENIED;
270 NaClLog(4,
271 "NaClNameServiceResolveName: incompatible,"
272 " not writeable\n");
273 goto unlock_and_quit;
274 }
275 break;
276 case NACL_ABI_O_RDWR:
277 if (NACL_ABI_O_RDWR != nnsep->mode) {
278 status = NACL_NAME_SERVICE_PERMISSION_DENIED;
279 NaClLog(4, "NaClNameServiceResolveName: incompatible,"
280 " not for both read and write\n");
281 goto unlock_and_quit;
282 }
283 break;
284 default:
285 status = NACL_NAME_SERVICE_INVALID_ARGUMENT;
286 NaClLog(4, "NaClNameServiceResolveName: invalid flag\n");
287 goto unlock_and_quit;
288 }
289 NaClLog(4, "NaClNameServiceResolveName: mode and flags are compatible\n");
290 *out = NaClDescRef(nnsep->entry);
291 status = NACL_NAME_SERVICE_SUCCESS;
292 } else {
293 status = (*nnsep->factory)(nnsep->state, name, flags, out);
294 }
295 }
296 unlock_and_quit:
297 nnsep = NULL;
298 NaClXMutexUnlock(&nnsp->mu);
299 quit:
300 return status;
301 }
302
303 int NaClNameServiceDeleteName(struct NaClNameService *nnsp,
304 char const *name) {
305 struct NaClNameServiceEntry **nnsepp;
306 struct NaClNameServiceEntry *to_free = NULL;
307 int status = NACL_NAME_SERVICE_NAME_NOT_FOUND;
308
309 NaClXMutexLock(&nnsp->mu);
310 nnsepp = NameServiceSearch(&nnsp->head, name);
311 if (NULL != *nnsepp) {
312 to_free = *nnsepp;
313 *nnsepp = to_free->next;
314 status = NACL_NAME_SERVICE_SUCCESS;
315 }
316 NaClXMutexUnlock(&nnsp->mu);
317
318 /* do the free operations w/o holding the lock */
319 if (NULL != to_free) {
320 NaClDescSafeUnref(to_free->entry);
321 if (NULL != to_free->factory) {
322 (void) (*to_free->factory)(to_free->state,
323 to_free->name,
324 0,
325 (struct NaClDesc **) NULL);
326 }
327 free((void *) to_free->name);
328 free(to_free);
329 }
330 return status;
331 }
332
333 static void NaClNameServiceNameInsertRpc(
334 struct NaClSrpcRpc *rpc,
335 struct NaClSrpcArg **in_args,
336 struct NaClSrpcArg **out_args,
337 struct NaClSrpcClosure *done_cls) {
338 struct NaClNameService *nnsp =
339 (struct NaClNameService *) rpc->channel->server_instance_data;
340 char *name = in_args[0]->arrays.str;
341 int mode = in_args[1]->u.ival;
342 struct NaClDesc *desc = in_args[2]->u.hval;
343
344 NaClLog(3,
345 "NaClNameServiceNameInsertRpc: inserting %s, %d (0x%x)\n",
346 name,
347 mode, mode);
348 out_args[0]->u.ival = (*NACL_VTBL(NaClNameService, nnsp)->CreateDescEntry)(
349 nnsp, name, mode, desc);
350 rpc->result = NACL_SRPC_RESULT_OK;
351 (*done_cls->Run)(done_cls);
352 }
353
354 static void NaClNameServiceNameLookupOldRpc(
355 struct NaClSrpcRpc *rpc,
356 struct NaClSrpcArg **in_args,
357 struct NaClSrpcArg **out_args,
358 struct NaClSrpcClosure *done_cls) {
359 struct NaClNameService *nnsp =
360 (struct NaClNameService *) rpc->channel->server_instance_data;
361 char *name = in_args[0]->arrays.str;
362 int status;
363 struct NaClDesc *desc;
364
365 NaClLog(LOG_WARNING,
366 "NaClNameServiceNameLookupOldRpc: DEPRECATED interface used.\n");
367 NaClLog(3, "NaClNameServiceNameLookupOldRpc: looking up %s\n", name);
368 status = (*NACL_VTBL(NaClNameService, nnsp)->ResolveName)(
369 nnsp, name, NACL_ABI_O_RDONLY, &desc);
370 out_args[0]->u.ival = status;
371 out_args[1]->u.hval = (NACL_NAME_SERVICE_SUCCESS == status)
372 ? desc
373 : (struct NaClDesc *) NaClDescInvalidMake();
374 rpc->result = NACL_SRPC_RESULT_OK;
375 (*done_cls->Run)(done_cls);
376 }
377
378 static void NaClNameServiceNameLookupRpc(
379 struct NaClSrpcRpc *rpc,
380 struct NaClSrpcArg **in_args,
381 struct NaClSrpcArg **out_args,
382 struct NaClSrpcClosure *done_cls) {
383 struct NaClNameService *nnsp =
384 (struct NaClNameService *) rpc->channel->server_instance_data;
385 char *name = in_args[0]->arrays.str;
386 int flags = in_args[1]->u.ival;
387 int status;
388 struct NaClDesc *desc;
389
390 NaClLog(3, "NaClNameServiceNameLookupRpc: looking up %s\n", name);
391 NaClLog(3, "NaClNameServiceNameLookupRpc: flags %d (0x%x)\n", flags, flags);
392 status = (*NACL_VTBL(NaClNameService, nnsp)->ResolveName)(
393 nnsp, name, flags, &desc);
394 out_args[0]->u.ival = status;
395 out_args[1]->u.hval = (NACL_NAME_SERVICE_SUCCESS == status)
396 ? desc
397 : (struct NaClDesc *) NaClDescInvalidMake();
398 NaClLog(3, "NaClNameServiceNameLookupRpc: status %d\n", status);
399 NaClLog(3, "NaClNameServiceNameLookupRpc: desc 0x%"NACL_PRIxPTR"\n",
400 (uintptr_t) desc);
401 rpc->result = NACL_SRPC_RESULT_OK;
402 (*done_cls->Run)(done_cls);
403 }
404
405 static void NaClNameServiceNameDeleteRpc(
406 struct NaClSrpcRpc *rpc,
407 struct NaClSrpcArg **in_args,
408 struct NaClSrpcArg **out_args,
409 struct NaClSrpcClosure *done_cls) {
410 struct NaClNameService *nnsp =
411 (struct NaClNameService *) rpc->channel->server_instance_data;
412 char *name = in_args[0]->arrays.str;
413
414 out_args[0]->u.ival = (*NACL_VTBL(NaClNameService, nnsp)->DeleteName)(
415 nnsp, name);
416 rpc->result = NACL_SRPC_RESULT_OK;
417 (*done_cls->Run)(done_cls);
418 }
419
420 struct NaClSrpcHandlerDesc const kNaClNameServiceHandlers[] = {
421 { NACL_NAME_SERVICE_INSERT, NaClNameServiceNameInsertRpc, },
422 { NACL_NAME_SERVICE_LOOKUP_DEPRECATED, NaClNameServiceNameLookupOldRpc, },
423 { NACL_NAME_SERVICE_LOOKUP, NaClNameServiceNameLookupRpc, },
424 { NACL_NAME_SERVICE_DELETE, NaClNameServiceNameDeleteRpc, },
425 { (char const *) NULL, (NaClSrpcMethod) NULL, },
426 };
427
428 void NaClNameServiceLaunch(struct NaClNameService *self) {
429
430 NaClLog(4, "NaClNameServiceThread: starting service\n");
431 NaClSimpleServiceStartServiceThread((struct NaClSimpleService *) self);
432 }
433
434 struct NaClNameServiceVtbl kNaClNameServiceVtbl = {
435 {
436 /* really NaClSimpleLtdServiceVtbl contents */
437 {
438 NaClNameServiceDtor,
439 },
440 NaClSimpleServiceConnectionFactory,
441 /*
442 * To implement name service ownership, the ConnectionFactory will
443 * need to build a subclass of a NaClSimpleServiceConnection where
444 * the connection can be marked as an owner, and the NameService
445 * would contain a mutex protected flag specifying whether it is
446 * owned that blocks mutations by all but the owning connection.
447 * The Connection object's Dtor can release ownership.
448 */
449 NaClSimpleLtdServiceAcceptConnection,
450 NaClSimpleServiceAcceptAndSpawnHandler,
451 NaClSimpleLtdServiceRpcHandler,
452 },
453 NaClNameServiceCreateDescEntry,
454 NaClNameServiceCreateFactoryEntry,
455 NaClNameServiceResolveName,
456 NaClNameServiceDeleteName,
457 };
OLDNEW
« no previous file with comments | « src/trusted/service_runtime/name_service/name_service.h ('k') | src/trusted/service_runtime/sel_ldr.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698