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

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

Powered by Google App Engine
This is Rietveld 408576698