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

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