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

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

Issue 10914138: Split secure command channel and untrusted application channel (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Minor fixes. Created 8 years, 2 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 | Annotate | Revision Log
OLDNEW
(Empty)
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 "native_client/src/trusted/service_runtime/nacl_secure_service.h"
8
9 #include "native_client/src/shared/platform/nacl_exit.h"
10 #include "native_client/src/shared/platform/nacl_log.h"
11 #include "native_client/src/shared/platform/nacl_sync.h"
12 #include "native_client/src/shared/platform/nacl_sync_checked.h"
13 #include "native_client/src/shared/srpc/nacl_srpc.h"
14
15 #include "native_client/src/trusted/fault_injection/fault_injection.h"
16 #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
17 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
18
19
20 int NaClSecureThreadIfFactoryFn(
21 void *factory_data,
22 NaClThreadIfStartFunction fn_ptr,
23 void *thread_data,
24 size_t thread_stack_size,
25 struct NaClThreadInterface **out_new_thread);
26
27 int NaClSecureServiceCtor(struct NaClSecureService *self,
28 struct NaClSrpcHandlerDesc const *srpc_handlers,
29 struct NaClApp *nap,
30 struct NaClDesc *service_port,
31 struct NaClDesc *sock_addr) {
32 int retval = 0; /* fail */
33
34 NaClLog(4,
35 "Entered NaClSecureServiceCtor: self 0x%"NACL_PRIxPTR"\n",
36 (uintptr_t) self);
37 if (NACL_FI_ERROR_COND(
38 "NaClSecureServiceCtor__NaClSimpleServiceWithSocketCtor",
39 !NaClSimpleServiceWithSocketCtor(
40 &self->base,
41 srpc_handlers,
42 NaClSecureThreadIfFactoryFn,
43 (void *) self,
44 service_port,
45 sock_addr))) {
46 goto done;
47 }
48 if (!NaClMutexCtor(&self->mu)) {
49 NaClLog(4, "NaClMutexCtor failed\n");
50 goto failure_simple_ctor;
bsy 2012/09/26 03:50:55 goto failure_no_mutex;
Petr Hosek 2012/09/26 04:22:21 Changed.
51 }
52 if (!NaClCondVarCtor(&self->cv)) {
53 NaClLog(4, "NaClCondVar failed\n");
54 goto failure_simple_ctor;
55 }
56 self->nap = nap;
57 self->thread_count = 0;
58
59 NACL_VTBL(NaClRefCount, self) =
60 (struct NaClRefCountVtbl *) &kNaClSecureServiceVtbl;
61
62 retval = 1;
63 goto done;
64
65 /* cleanup unwind */
66 failure_simple_ctor: /* ctor failed */
67 NaClCondVarDtor(&self->cv);
bsy 2012/09/26 03:35:33 you cannot safely dtor what has not been successfu
Petr Hosek 2012/09/26 04:22:21 Reworked.
68 NaClMutexDtor(&self->mu);
bsy 2012/09/26 03:50:55 failure_no_mutex: (*NACL_VTBL(NaClRefCount, self
Petr Hosek 2012/09/26 04:22:21 Yep, already added ;)
69 done:
70 return retval;
71 }
72
73 void NaClSecureServiceDtor(struct NaClRefCount *vself) {
74 struct NaClSecureService *self = (struct NaClSecureService *) vself;
75
76 if (0 != self->thread_count) {
77 NaClLog(LOG_FATAL,
78 "SecureService dtor when thread count is nonzero\n");
79 }
80 self->thread_count = 0;
bsy 2012/09/26 03:35:33 not needed, post-condition implies this.
Petr Hosek 2012/09/26 04:22:21 Removed, as well as condvar.
81 NaClCondVarDtor(&self->cv);
82 NaClMutexDtor(&self->mu);
83
84 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
85 &kNaClSimpleServiceVtbl;
86 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
87 }
88
89 int NaClSecureServiceConnectionFactory(
90 struct NaClSimpleService *vself,
91 struct NaClDesc *conn,
92 struct NaClSimpleServiceConnection **out) {
93 struct NaClSecureService *self =
94 (struct NaClSecureService *) vself;
95
96 /* our instance_data is not connection specific */
97 return NaClSimpleServiceConnectionFactoryWithInstanceData(
98 vself, conn, (void *) self->nap, out);
99 }
100
101 struct NaClSecureThreadInterface {
102 struct NaClThreadInterface base NACL_IS_REFCOUNT_SUBCLASS;
103 struct NaClSecureService *secure_service;
104 };
105
106 extern struct NaClThreadInterfaceVtbl
107 const kNaClSecureThreadInterfaceVtbl; /* fwd */
108
109 int NaClReverseThreadIfCtor_protected(
110 struct NaClSecureThreadInterface *self,
111 void *factory_data,
112 NaClThreadIfStartFunction fn_ptr,
113 void *thread_data,
114 size_t thread_stack_size) {
115 struct NaClSecureService *service = (struct NaClSecureService *) factory_data;
116
117 NaClLog(3, "Entered NaClSecureThreadIfCtor_protected\n");
118 if (!NaClThreadInterfaceCtor_protected(
119 (struct NaClThreadInterface *) self,
120 NaClSecureThreadIfFactoryFn,
121 NaClRefCountRef((struct NaClRefCount *) service),
122 fn_ptr,
123 thread_data,
124 thread_stack_size)) {
125 NaClLog(4, "NaClThreadInterfaceCtor_protected failed\n");
126 NaClRefCountUnref((struct NaClRefCount *) service);
127 return 0;
128 }
129
130 self->secure_service = service;
131 (*NACL_VTBL(NaClSecureService, service)->ThreadCountIncr)(service);
132
133 NACL_VTBL(NaClRefCount, self) =
134 (struct NaClRefCountVtbl *) &kNaClSecureThreadInterfaceVtbl;
135
136 NaClLog(3, "Leaving NaClSecureThreadIfCtor_protected\n");
137 return 1;
138 }
139
140 /*
141 * Takes ownership of rev reference. Caller should Ref() the argument
142 * and Unref on failure if caller does not wish to pass ownership.
143 */
144 int NaClSecureThreadIfFactoryFn(
145 void *factory_data,
146 NaClThreadIfStartFunction fn_ptr,
147 void *thread_data,
148 size_t thread_stack_size,
149 struct NaClThreadInterface **out_new_thread) {
150 struct NaClSecureThreadInterface *new_thread;
151 int rv = 1;
152
153 NaClLog(3, "Entered NaClSecureThreadIfFactoryFn\n");
154 new_thread = (struct NaClSecureThreadInterface *)
155 malloc(sizeof *new_thread);
156 if (NULL == new_thread) {
157 rv = 0;
158 goto cleanup;
159 }
160
161 if (!(rv =
162 NaClReverseThreadIfCtor_protected(new_thread,
163 factory_data,
164 fn_ptr,
165 thread_data,
166 thread_stack_size))) {
167 goto cleanup;
168 }
169
170 *out_new_thread = (struct NaClThreadInterface *) new_thread;
171 new_thread = NULL;
172
173 cleanup:
174 free(new_thread);
175 NaClLog(3,
176 "Leaving NaClSecureThreadIfFactoryFn, rv %d\n",
177 rv);
178 return rv;
179 }
180
181 void NaClSecureThreadIfDtor(struct NaClRefCount *vself) {
182 struct NaClSecureThreadInterface *self =
183 (struct NaClSecureThreadInterface *) vself;
184
185 NaClRefCountUnref((struct NaClRefCount *) self->secure_service);
186 self->secure_service = NULL;
187 NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
188 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
189 }
190
191 void NaClSecureThreadIfLaunchCallback(struct NaClThreadInterface *self) {
192 NaClLog(4,
193 ("NaClSecureThreadIfLaunchCallback: thread 0x%"NACL_PRIxPTR
194 " is launching\n"),
195 (uintptr_t) self);
196 }
197
198 void NaClSecureThreadIfExit(struct NaClThreadInterface *vself,
199 void *exit_code) {
200 struct NaClSecureThreadInterface *self =
201 (struct NaClSecureThreadInterface *) vself;
202 NaClLog(4,
203 ("NaClSecureThreadIfExit: thread 0x%"NACL_PRIxPTR
204 " is exiting\n"),
205 (uintptr_t) vself);
206
207 (*NACL_VTBL(NaClSecureService, self->secure_service)->ThreadCountDecr)(
208 self->secure_service);
209
210 NaClRefCountUnref((struct NaClRefCount *) self);
211 NaClThreadExit((int)(uintptr_t) exit_code);
212 }
213
214 struct NaClThreadInterfaceVtbl const kNaClSecureThreadInterfaceVtbl = {
215 {
216 NaClSecureThreadIfDtor,
217 },
218 NaClThreadInterfaceStartThread,
219 NaClSecureThreadIfLaunchCallback,
220 NaClSecureThreadIfExit,
221 };
222
223 void NaClSecureServiceWaitForServiceThreadsToExit(
bsy 2012/09/26 03:35:33 remove method
Petr Hosek 2012/09/26 04:22:21 Gone.
224 struct NaClSecureService *self) {
225 NaClLog(4, "NaClSecureServiceWaitForServiceThreadsToExit\n");
226 NaClXMutexLock(&self->mu);
227 while (0 != self->thread_count) {
228 NaClXCondVarWait(&self->cv, &self->mu);
229 NaClLog(5, "NaClSecureServiceWaitForServiceThreadsToExit: woke up\n");
230 }
231 NaClXMutexUnlock(&self->mu);
232 NaClLog(4, "NaClSecureServiceWaitForServiceThreadsToExit: all done\n");
233 }
234
235 void NaClSecureServiceThreadCountIncr(
236 struct NaClSecureService *self) {
237 NaClLog(5, "NaClSecureServiceThreadCountIncr\n");
238 NaClXMutexLock(&self->mu);
239 if (0 == ++self->thread_count) {
240 NaClLog(LOG_FATAL,
241 "NaClSecureServiceThreadCountIncr: "
242 "thread count overflow!\n");
243 }
244 NaClXMutexUnlock(&self->mu);
245 }
246
247 void NaClSecureServiceThreadCountDecr(
248 struct NaClSecureService *self) {
249 NaClLog(5, "NaClSecureServiceThreadCountDecr\n");
250 NaClXMutexLock(&self->mu);
251 if (0 == self->thread_count) {
252 NaClLog(LOG_FATAL,
253 "NaClSecureServiceThreadCountDecr: "
254 "decrementing thread count when count is zero\n");
255 }
256 if (0 == --self->thread_count) {
257 NaClXCondVarBroadcast(&self->cv);
258 NaClLog(4, "NaClSecureServiceThread: channel closed, exiting.\n");
259 NaClExit(0);
260 }
261 NaClXMutexUnlock(&self->mu);
262 }
263
264 struct NaClSecureServiceVtbl const kNaClSecureServiceVtbl = {
265 {
266 {
267 NaClSecureServiceDtor,
268 },
269 NaClSecureServiceConnectionFactory,
270 NaClSimpleServiceAcceptConnection,
271 NaClSimpleServiceAcceptAndSpawnHandler,
272 NaClSimpleServiceRpcHandler,
273 },
274 NaClSecureServiceWaitForServiceThreadsToExit,
bsy 2012/09/26 03:35:33 remove method
Petr Hosek 2012/09/26 04:22:21 Gone.
275 NaClSecureServiceThreadCountIncr,
276 NaClSecureServiceThreadCountDecr,
277 };
278
279 struct NaClSecureRevClientConnHandler {
280 struct NaClSecureRevClientConnHandler *next;
281
282 /* used by NaClSimpleRevServiceClient's ClientCallback fn */
283 void (*handler)(
284 void *state,
285 struct NaClThreadInterface *tif,
286 struct NaClDesc *conn);
287 void *state;
288 };
289
290 static void NaClSecureReverseClientInternalCallback(
291 void *state,
292 struct NaClThreadInterface *tif,
293 struct NaClDesc *conn) {
294 struct NaClSecureReverseClient *self =
295 (struct NaClSecureReverseClient *) state;
296 struct NaClSecureRevClientConnHandler *hand_ptr;
297
298 UNREFERENCED_PARAMETER(tif);
299 NaClLog(4, "Entered NaClSecureReverseClientInternalCallback\n");
300 hand_ptr = (*NACL_VTBL(NaClSecureReverseClient, self)->RemoveHandler)(self);
301 NaClLog(4, " got callback object %"NACL_PRIxPTR"\n", (uintptr_t) hand_ptr);
302 NaClLog(4,
303 " callback:0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n",
304 (uintptr_t) hand_ptr->handler,
305 (uintptr_t) hand_ptr->state,
306 (uintptr_t) conn);
307 (*hand_ptr->handler)(hand_ptr->state, tif, conn);
308 NaClLog(4, "NaClSecureReverseClientInternalCallback: freeing memory\n");
309 free(hand_ptr);
310 NaClLog(4, "Leaving NaClSecureReverseClientInternalCallback\n");
311 }
312
313 /*
314 * Require an initial connection handler in the Ctor, so that it's
315 * obvious that a reverse client needs to accept an IMC connection
316 * from the server to get things bootstrapped.
317 */
318 int NaClSecureReverseClientCtor(
319 struct NaClSecureReverseClient *self,
320 void (*client_callback)(
321 void *, struct NaClThreadInterface*, struct NaClDesc *),
322 void *state,
323 struct NaClApp *nap) {
324 NaClLog(4,
325 ("Entered NaClSecureReverseClientCtor, self 0x%"NACL_PRIxPTR","
326 " nap 0x%"NACL_PRIxPTR"\n"),
327 (uintptr_t) self,
328 (uintptr_t) nap);
329 if (!NaClSimpleRevClientCtor(&self->base,
330 NaClSecureReverseClientInternalCallback,
331 (void *) self,
332 NaClThreadInterfaceThreadFactory,
333 (void *) NULL)) {
334 goto failure_simple_ctor;
335 }
336 NaClLog(4, "NaClSecureReverseClientCtor: Mutex\n");
337 if (!NaClMutexCtor(&self->mu)) {
338 goto failure_mutex_ctor;
339 }
340 self->nap = nap;
341 self->queue_head = (struct NaClSecureRevClientConnHandler *) NULL;
342 self->queue_insert = &self->queue_head;
343
344 NACL_VTBL(NaClRefCount, self) =
345 (struct NaClRefCountVtbl *) &kNaClSecureReverseClientVtbl;
346
347 NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler\n");
348 if (!(*NACL_VTBL(NaClSecureReverseClient, self)->
349 InsertHandler)(self, client_callback, state)) {
350 goto failure_handler_insert;
351 }
352
353 NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
354 return 1;
355
356 failure_handler_insert:
357 NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler failed\n");
358 NACL_VTBL(NaClRefCount, self) =
359 (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
360
361 self->nap = NULL;
362 self->queue_insert = (struct NaClSecureRevClientConnHandler **) NULL;
363 NaClMutexDtor(&self->mu);
364
365 failure_mutex_ctor:
366 NaClLog(4, "NaClSecureReverseClientCtor: Mutex failed\n");
367 (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
368 failure_simple_ctor:
369 NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
370 return 0;
371 }
372
373 void NaClSecureReverseClientDtor(struct NaClRefCount *vself) {
374 struct NaClSecureReverseClient *self =
375 (struct NaClSecureReverseClient *) vself;
376
377 struct NaClSecureRevClientConnHandler *entry;
378 struct NaClSecureRevClientConnHandler *next;
379
380 for (entry = self->queue_head; NULL != entry; entry = next) {
381 next = entry->next;
382 free(entry);
383 }
384 NaClMutexDtor(&self->mu);
385
386 NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
387 &kNaClSimpleRevClientVtbl;
388 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
389 }
390
391 /*
392 * Caller must set up handler before issuing connection request RPC on
393 * nap->reverse_channel, since otherwise the connection handler queue
394 * may be empty and the connect code would abort. Because the connect
395 * doesn't wait for a handler, we don't need a condvar.
396 *
397 * We do not need to serialize on the handlers, since the
398 * RPC-server/IMC-client implementation should not distinguish one
399 * connection from another: it is okay for two handlers to be
400 * inserted, and two connection request RPCs to be preformed
401 * (sequentially, since they are over a single channel), and have the
402 * server side spawn threads that asynchronously connect twice, in the
403 * "incorrect" order, etc.
404 */
405 int NaClSecureReverseClientInsertHandler(
406 struct NaClSecureReverseClient *self,
407 void (*handler)(
408 void *handler_state,
409 struct NaClThreadInterface *thread_if,
410 struct NaClDesc *new_conn),
411 void *state) {
412 struct NaClSecureRevClientConnHandler *entry;
413 int retval = 0; /* fail */
414
415 NaClLog(4,
416 ("NaClSecureReverseClientInsertHandler: "
417 "handler 0x%"NACL_PRIxPTR", state 0x%"NACL_PRIxPTR"\n"),
418 (uintptr_t) handler, (uintptr_t) state);
419
420 NaClXMutexLock(&self->mu);
421
422 entry = (struct NaClSecureRevClientConnHandler *) malloc(sizeof *entry);
423 if (NULL == entry) {
424 goto cleanup;
425 }
426 entry->handler = handler;
427 entry->state = state;
428 entry->next = (struct NaClSecureRevClientConnHandler *) NULL;
429 *self->queue_insert = entry;
430 self->queue_insert = &entry->next;
431 retval = 1;
432
433 cleanup:
434 NaClXMutexUnlock(&self->mu);
435 return retval;
436 }
437
438 struct NaClSecureRevClientConnHandler *NaClSecureReverseClientRemoveHandler(
439 struct NaClSecureReverseClient *self) {
440 struct NaClSecureRevClientConnHandler *head;
441
442 NaClLog(4, "Entered NaClSecureReverseClientRemoveHandler, acquiring lock\n");
443 NaClXMutexLock(&self->mu);
444 NaClLog(4, "NaClSecureReverseClientRemoveHandler, got lock\n");
445 head = self->queue_head;
446 if (NULL == head) {
447 NaClLog(LOG_FATAL,
448 "NaClSecureReverseClientRemoveHandler: empty handler queue\n");
449 }
450 if (NULL == (self->queue_head = head->next)) {
451 NaClLog(4, "NaClSecureReverseClientRemoveHandler, last elt patch up\n");
452 self->queue_insert = &self->queue_head;
453 }
454 NaClLog(4, "NaClSecureReverseClientRemoveHandler, unlocking\n");
455 NaClXMutexUnlock(&self->mu);
456
457 head->next = NULL;
458 NaClLog(4,
459 ("Leaving NaClSecureReverseClientRemoveHandler:"
460 " returning %"NACL_PRIxPTR"\n"),
461 (uintptr_t) head);
462 return head;
463 }
464
465 struct NaClSecureReverseClientVtbl const kNaClSecureReverseClientVtbl = {
466 {
467 {
468 NaClSecureReverseClientDtor,
469 },
470 },
471 NaClSecureReverseClientInsertHandler,
472 NaClSecureReverseClientRemoveHandler,
473 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698