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 <string.h>
10 :
11 : #include "native_client/src/public/secure_service.h"
12 :
13 : #include "native_client/src/shared/platform/nacl_exit.h"
14 : #include "native_client/src/shared/platform/nacl_log.h"
15 : #include "native_client/src/shared/platform/nacl_sync.h"
16 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
17 : #include "native_client/src/shared/srpc/nacl_srpc.h"
18 :
19 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
20 : #include "native_client/src/trusted/fault_injection/fault_injection.h"
21 : #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
22 : #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
23 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
24 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
25 : #include "native_client/src/trusted/service_runtime/nacl_app.h"
26 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
27 : #include "native_client/src/trusted/service_runtime/nacl_reverse_host_interface.h"
28 : #include "native_client/src/trusted/service_runtime/nacl_reverse_quota_interface.h"
29 : #include "native_client/src/trusted/service_runtime/nacl_signal.h"
30 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
31 :
32 : struct NaClSrpcHandlerDesc const kNaClSecureServiceHandlers[];
33 :
34 10 : int NaClSecureServiceCtor(struct NaClSecureService *self,
35 10 : struct NaClApp *nap,
36 10 : struct NaClDesc *service_port,
37 10 : struct NaClDesc *sock_addr) {
38 10 : NaClLog(4,
39 : "Entered NaClSecureServiceCtor: self 0x%"NACL_PRIxPTR"\n",
40 : (uintptr_t) self);
41 20 : if (NACL_FI_ERROR_COND(
42 : "NaClSecureServiceCtor__NaClSimpleServiceWithSocketCtor",
43 : !NaClSimpleServiceWithSocketCtor(
44 : &self->base,
45 : kNaClSecureServiceHandlers,
46 : NaClThreadInterfaceThreadFactory,
47 : (void *) self,
48 : service_port,
49 : sock_addr))) {
50 0 : goto done;
51 : }
52 10 : if (!NaClMutexCtor(&self->mu)) {
53 0 : NaClLog(4, "NaClMutexCtor failed\n");
54 0 : goto failure_mutex_ctor;
55 : }
56 10 : if (!NaClCondVarCtor(&self->cv)) {
57 0 : NaClLog(4, "NaClCondVar failed\n");
58 0 : goto failure_condvar_ctor;
59 : }
60 10 : NaClXMutexCtor(&self->mu);
61 10 : NaClXCondVarCtor(&self->cv);
62 10 : self->nap = nap;
63 10 : self->reverse_channel_initialization_state =
64 : NACL_REVERSE_CHANNEL_UNINITIALIZED;
65 10 : self->reverse_client = NULL;
66 10 : self->conn_count = 0;
67 10 : NACL_VTBL(NaClRefCount, self) =
68 : (struct NaClRefCountVtbl *) &kNaClSecureServiceVtbl;
69 10 : return 1;
70 :
71 : failure_condvar_ctor:
72 0 : NaClMutexDtor(&self->mu);
73 : failure_mutex_ctor:
74 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
75 : done:
76 0 : return 0;
77 10 : }
78 :
79 0 : void NaClSecureServiceDtor(struct NaClRefCount *vself) {
80 0 : struct NaClSecureService *self = (struct NaClSecureService *) vself;
81 :
82 0 : NaClXMutexLock(&self->mu);
83 0 : if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
84 : self->reverse_channel_initialization_state) {
85 0 : while (NACL_REVERSE_CHANNEL_INITIALIZED !=
86 : self->reverse_channel_initialization_state) {
87 0 : NaClXCondVarWait(&self->cv, &self->mu);
88 0 : }
89 0 : }
90 :
91 0 : if (0 != self->conn_count) {
92 0 : NaClLog(LOG_FATAL,
93 : "SecureService dtor when connection count is nonzero\n");
94 0 : }
95 0 : self->conn_count = 0;
96 :
97 0 : if (NACL_REVERSE_CHANNEL_INITIALIZED ==
98 : self->reverse_channel_initialization_state) {
99 0 : NaClSrpcDtor(&self->reverse_channel);
100 0 : }
101 0 : if (NULL != self->reverse_client) {
102 0 : NaClRefCountUnref((struct NaClRefCount *) self->reverse_client);
103 0 : }
104 0 : NaClXMutexUnlock(&self->mu);
105 :
106 0 : NaClCondVarDtor(&self->cv);
107 0 : NaClMutexDtor(&self->mu);
108 :
109 0 : NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
110 : &kNaClSimpleServiceVtbl;
111 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
112 0 : }
113 :
114 : int NaClSecureServiceConnectionFactory(
115 10 : struct NaClSimpleService *vself,
116 10 : struct NaClDesc *conn,
117 10 : struct NaClSimpleServiceConnection **out) {
118 : /* our instance_data is not connection specific */
119 10 : return NaClSimpleServiceConnectionFactoryWithInstanceData(
120 : vself, conn, (struct NaClSecureService *) vself, out);
121 : }
122 :
123 : static void NaClSecureServiceConnectionCountIncr(
124 10 : struct NaClSecureService *self) {
125 10 : NaClLog(5, "NaClSecureServiceThreadCountIncr\n");
126 10 : NaClXMutexLock(&self->mu);
127 10 : if (0 == ++self->conn_count) {
128 0 : NaClLog(LOG_FATAL,
129 : "NaClSecureServiceThreadCountIncr: "
130 : "thread count overflow!\n");
131 0 : }
132 10 : NaClXMutexUnlock(&self->mu);
133 10 : }
134 :
135 : static void NaClSecureServiceConnectionCountDecr(
136 3 : struct NaClSecureService *self) {
137 3 : uint32_t conn_count;
138 :
139 3 : NaClLog(5, "NaClSecureServiceThreadCountDecr\n");
140 3 : NaClXMutexLock(&self->mu);
141 3 : if (0 == self->conn_count) {
142 0 : NaClLog(LOG_FATAL,
143 : "NaClSecureServiceThreadCountDecr: "
144 : "decrementing thread count when count is zero\n");
145 0 : }
146 3 : conn_count = --self->conn_count;
147 3 : NaClXMutexUnlock(&self->mu);
148 :
149 3 : if (0 == conn_count) {
150 3 : NaClLog(4, "NaClSecureServiceThread: all channels closed, exiting.\n");
151 : /*
152 : * Set that we are killed by SIGKILL so that debug stub could report
153 : * this to debugger.
154 : */
155 3 : NaClAppShutdown(self->nap, NACL_ABI_W_EXITCODE(0, NACL_ABI_SIGKILL));
156 3 : }
157 0 : }
158 :
159 : int NaClSecureServiceAcceptConnection(
160 10 : struct NaClSimpleService *vself,
161 10 : struct NaClSimpleServiceConnection **vconn) {
162 10 : struct NaClSecureService *self =
163 : (struct NaClSecureService *) vself;
164 10 : int status;
165 :
166 10 : NaClLog(4, "NaClSecureServiceAcceptConnection\n");
167 10 : status = (*kNaClSimpleServiceVtbl.AcceptConnection)(vself, vconn);
168 10 : if (0 == status) {
169 10 : NaClSecureServiceConnectionCountIncr(self);
170 10 : }
171 10 : NaClLog(4, "Leaving NaClSecureServiceAcceptConnection, status %d.\n", status);
172 10 : return status;
173 : }
174 :
175 10 : void NaClSecureServiceRpcHandler(struct NaClSimpleService *vself,
176 10 : struct NaClSimpleServiceConnection *vconn) {
177 10 : struct NaClSecureService *self =
178 : (struct NaClSecureService *) vself;
179 :
180 10 : NaClLog(4, "NaClSecureChannelThread started\n");
181 10 : (*kNaClSimpleServiceVtbl.RpcHandler)(vself, vconn);
182 10 : NaClLog(4, "NaClSecureChannelThread closed.\n");
183 10 : NaClSecureServiceConnectionCountDecr(self);
184 10 : }
185 :
186 : static void NaClSecureServiceLoadModuleRpcCallback(
187 8 : void *instance_data,
188 8 : NaClErrorCode status) {
189 8 : struct NaClSrpcClosure *done_cls =
190 : (struct NaClSrpcClosure *) instance_data;
191 16 : UNREFERENCED_PARAMETER(status);
192 8 : NaClLog(4, "NaClSecureChannelLoadModuleRpcCallback: status %d\n", status);
193 8 : (*done_cls->Run)(done_cls);
194 8 : }
195 :
196 : /* TODO(teravest): Remove this once http://crbug.com/333950 is resolved. */
197 : static void NaClSecureServiceLoadModuleRpc(
198 8 : struct NaClSrpcRpc *rpc,
199 8 : struct NaClSrpcArg **in_args,
200 8 : struct NaClSrpcArg **out_args,
201 8 : struct NaClSrpcClosure *done_cls) {
202 8 : struct NaClSecureService *nssp =
203 : (struct NaClSecureService *) rpc->channel->server_instance_data;
204 8 : struct NaClDesc *nexe = in_args[0]->u.hval;
205 16 : UNREFERENCED_PARAMETER(out_args);
206 :
207 8 : NaClLog(4, "NaClSecureServiceLoadModuleRpc: loading module\n");
208 8 : rpc->result = NACL_SRPC_RESULT_OK;
209 8 : NaClAppLoadModule(nssp->nap,
210 : nexe,
211 : NaClSecureServiceLoadModuleRpcCallback,
212 : (void *) done_cls);
213 8 : NaClDescUnref(nexe);
214 8 : nexe = NULL;
215 :
216 8 : NaClLog(4, "NaClSecureServiceLoadModuleRpc: done\n");
217 8 : }
218 :
219 : /*
220 : * The first connection is performed by this callback handler. This
221 : * spawns a client thread that will bootstrap the other connections by
222 : * stashing the connection represented by |conn| to make reverse RPCs
223 : * to ask the peer to connect to us. No thread is spawned; we just
224 : * wrap access to the connection with a lock.
225 : *
226 : * Subsequent connection callbacks will pass the connection to the
227 : * actual thread that made the connection request using |conn|
228 : * received in the first connection.
229 : */
230 : static void NaClSecureReverseClientCallback(
231 3 : void *state,
232 3 : struct NaClThreadInterface *tif,
233 3 : struct NaClDesc *new_conn) {
234 3 : struct NaClSecureService *self =
235 : (struct NaClSecureService *) state;
236 3 : struct NaClApp *nap = self->nap;
237 3 : struct NaClManifestProxy *manifest_proxy;
238 3 : struct NaClReverseHostInterface *reverse_host_interface;
239 3 : struct NaClReverseQuotaInterface *reverse_quota_interface;
240 6 : UNREFERENCED_PARAMETER(tif);
241 :
242 3 : NaClLog(4,
243 : ("Entered NaClSecureReverseClientCallback: self 0x%"NACL_PRIxPTR","
244 : " nap 0x%"NACL_PRIxPTR", new_conn 0x%"NACL_PRIxPTR"\n"),
245 : (uintptr_t) self, (uintptr_t) nap, (uintptr_t) new_conn);
246 :
247 3 : NaClXMutexLock(&self->mu);
248 3 : if (NACL_REVERSE_CHANNEL_INITIALIZATING !=
249 : self->reverse_channel_initialization_state) {
250 : /*
251 : * The reverse channel connection capability is used to make the
252 : * RPC that invokes this callback (this callback is invoked on a
253 : * reverse channel connect), so the plugin wants to initialize the
254 : * reverse channel and in particular the state must be either be
255 : * in-progress or finished.
256 : */
257 0 : NaClLog(LOG_FATAL, "Reverse channel already initialized\n");
258 0 : }
259 3 : NaClXMutexUnlock(&self->mu);
260 3 : if (!NaClSrpcClientCtor(&self->reverse_channel, new_conn)) {
261 0 : NaClLog(LOG_FATAL, "Reverse channel SRPC Client Ctor failed\n");
262 0 : goto done;
263 : }
264 : reverse_host_interface = (struct NaClReverseHostInterface *)
265 3 : malloc(sizeof *reverse_host_interface);
266 3 : if (NULL == reverse_host_interface ||
267 6 : NACL_FI_ERROR_COND(
268 : ("NaClSecureReverseClientCallback"
269 : "__NaClReverseInterfaceCtor"),
270 : !NaClReverseHostInterfaceCtor(reverse_host_interface,
271 : self))) {
272 0 : NaClLog(LOG_FATAL, "Reverse interface ctor failed\n");
273 0 : goto cleanup_reverse_host_interface;
274 : }
275 3 : NaClAppRuntimeHostSetup(nap, (struct NaClRuntimeHostInterface *)
276 : reverse_host_interface);
277 :
278 : reverse_quota_interface = (struct NaClReverseQuotaInterface *)
279 3 : malloc(sizeof *reverse_quota_interface);
280 3 : if (NULL == reverse_quota_interface ||
281 6 : NACL_FI_ERROR_COND(
282 : ("NaClSecureReverseClientCallback"
283 : "__NaClReverseQuotaInterfaceCtor"),
284 : !NaClReverseQuotaInterfaceCtor(reverse_quota_interface,
285 : self))) {
286 0 : NaClLog(LOG_FATAL, "Reverse quota interface ctor failed\n");
287 0 : goto cleanup_reverse_quota_interface;
288 : }
289 3 : NaClAppDescQuotaSetup(nap, (struct NaClDescQuotaInterface *)
290 : reverse_quota_interface);
291 :
292 3 : NaClRefCountSafeUnref((struct NaClRefCount *) reverse_quota_interface);
293 3 : reverse_quota_interface = NULL;
294 :
295 : manifest_proxy = (struct NaClManifestProxy *)
296 3 : malloc(sizeof *manifest_proxy);
297 3 : if (NULL == manifest_proxy ||
298 3 : !NaClManifestProxyCtor(manifest_proxy,
299 : NaClAddrSpSquattingThreadIfFactoryFunction,
300 : (void *) nap,
301 : self)) {
302 0 : NaClLog(LOG_FATAL, "Manifest proxy ctor failed\n");
303 0 : goto cleanup_manifest_proxy;
304 : }
305 :
306 : /*
307 : * NaClSimpleServiceStartServiceThread requires the nap->mu lock.
308 : */
309 3 : if (!NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
310 : manifest_proxy)) {
311 0 : NaClLog(LOG_FATAL, "ManifestProxy start service failed\n");
312 0 : goto cleanup_manifest_proxy;
313 : }
314 :
315 3 : NaClXMutexLock(&nap->mu);
316 6 : (*NACL_VTBL(NaClNameService, nap->name_service)->
317 : CreateDescEntry)(nap->name_service,
318 : "ManifestNameService", NACL_ABI_O_RDWR,
319 3 : NaClDescRef(manifest_proxy->base.bound_and_cap[1]));
320 3 : NaClXMutexUnlock(&nap->mu);
321 :
322 3 : NaClXMutexLock(&self->mu);
323 3 : self->reverse_channel_initialization_state =
324 : NACL_REVERSE_CHANNEL_INITIALIZED;
325 3 : NaClXCondVarBroadcast(&self->cv);
326 3 : NaClXMutexUnlock(&self->mu);
327 :
328 : cleanup_manifest_proxy:
329 3 : NaClRefCountSafeUnref((struct NaClRefCount *) manifest_proxy);
330 : cleanup_reverse_quota_interface:
331 3 : NaClRefCountSafeUnref((struct NaClRefCount *) reverse_quota_interface);
332 : cleanup_reverse_host_interface:
333 3 : NaClRefCountSafeUnref((struct NaClRefCount *) reverse_host_interface);
334 : done:
335 3 : NaClLog(4, "Leaving NaClSecureReverseClientCallback\n");
336 3 : }
337 :
338 : static void NaClSecureServiceReverseSetupRpc(
339 3 : struct NaClSrpcRpc *rpc,
340 3 : struct NaClSrpcArg **in_args,
341 3 : struct NaClSrpcArg **out_args,
342 3 : struct NaClSrpcClosure *done_cls) {
343 3 : struct NaClSecureService *nssp =
344 : (struct NaClSecureService *) rpc->channel->server_instance_data;
345 3 : struct NaClDesc *rev_addr = NULL;
346 3 : struct NaClSecureReverseClient *rev;
347 6 : UNREFERENCED_PARAMETER(in_args);
348 :
349 3 : NaClLog(4, "NaClSecureServiceReverseSetupRpc: reverse setup\n");
350 :
351 3 : NaClXMutexLock(&nssp->mu);
352 3 : if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
353 : nssp->reverse_channel_initialization_state) {
354 0 : NaClLog(LOG_ERROR, "NaClSecureServiceReverseSetupRpc:"
355 : " reverse channel initialization state not uninitialized\n");
356 0 : rpc->result = NACL_SRPC_RESULT_APP_ERROR;
357 0 : goto cleanup;
358 : }
359 3 : nssp->reverse_channel_initialization_state =
360 : NACL_REVERSE_CHANNEL_INITIALIZATING;
361 3 : NaClXCondVarBroadcast(&nssp->cv);
362 :
363 : /* the reverse connection is still coming */
364 3 : rev = (struct NaClSecureReverseClient *) malloc(sizeof *rev);
365 3 : if (NULL == rev) {
366 0 : rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
367 0 : goto cleanup;
368 : }
369 3 : NaClLog(4, "NaClSecureServiceReverseSetupRpc:"
370 : " invoking NaClSecureReverseClientCtor\n");
371 3 : if (!NaClSecureReverseClientCtor(rev,
372 : NaClSecureReverseClientCallback,
373 : (void *) nssp)) {
374 0 : free(rev);
375 0 : rpc->result = NACL_SRPC_RESULT_APP_ERROR;
376 0 : goto cleanup;
377 : }
378 :
379 3 : if (!NaClSimpleRevClientStartServiceThread(&rev->base)) {
380 0 : rpc->result = NACL_SRPC_RESULT_APP_ERROR;
381 0 : goto cleanup;
382 : }
383 :
384 3 : nssp->reverse_client = (struct NaClSecureReverseClient *) NaClRefCountRef(
385 : (struct NaClRefCount *) rev);
386 :
387 3 : out_args[0]->u.hval = NaClDescRef(rev->base.bound_and_cap[1]);
388 3 : rpc->result = NACL_SRPC_RESULT_OK;
389 : cleanup:
390 3 : NaClXMutexUnlock(&nssp->mu);
391 3 : NaClLog(4, "NaClSecureServiceReverseSetupRpc: done, "
392 : " rev_addr 0x%08"NACL_PRIxPTR"\n",
393 : (uintptr_t) rev_addr);
394 3 : (*done_cls->Run)(done_cls);
395 3 : }
396 :
397 : struct StartModuleCallbackState {
398 : int *out_status;
399 : struct NaClSrpcClosure *cls;
400 : };
401 :
402 : static void NaClSecureServiceStartModuleRpcCallback(
403 10 : void *instance_data,
404 10 : NaClErrorCode status) {
405 10 : struct StartModuleCallbackState *state =
406 : (struct StartModuleCallbackState *) instance_data;
407 10 : NaClLog(4, "NaClSecureChannelStartModuleRpcCallback: status %d\n", status);
408 :
409 : /*
410 : * The RPC reply is now sent. This has to occur before we signal
411 : * the main thread to possibly start, since in the case of a failure
412 : * the main thread may quickly exit. If the main thread does this
413 : * before we sent the RPC reply, then the plugin will be left
414 : * without an answer.
415 : */
416 10 : *state->out_status = (int) status;
417 10 : (*state->cls->Run)(state->cls);
418 10 : free(state);
419 10 : }
420 :
421 : static void NaClSecureServiceStartModuleRpc(
422 10 : struct NaClSrpcRpc *rpc,
423 10 : struct NaClSrpcArg **in_args,
424 10 : struct NaClSrpcArg **out_args,
425 10 : struct NaClSrpcClosure *done_cls) {
426 10 : struct NaClSecureService *nssp =
427 : (struct NaClSecureService *) rpc->channel->server_instance_data;
428 10 : struct StartModuleCallbackState *state;
429 20 : UNREFERENCED_PARAMETER(in_args);
430 :
431 10 : NaClLog(4, "NaClSecureChannelStartModuleRpc: starting module\n");
432 :
433 : /*
434 : * When reverse setup is being used, we have to block and wait for reverse
435 : * channel to become initialized before we can proceed with start module.
436 : */
437 10 : NaClXMutexLock(&nssp->mu);
438 10 : if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
439 : nssp->reverse_channel_initialization_state) {
440 9 : while (NACL_REVERSE_CHANNEL_INITIALIZED !=
441 : nssp->reverse_channel_initialization_state) {
442 3 : NaClXCondVarWait(&nssp->cv, &nssp->mu);
443 3 : }
444 3 : }
445 10 : NaClXMutexUnlock(&nssp->mu);
446 :
447 10 : state = (struct StartModuleCallbackState *) malloc(sizeof *state);
448 10 : if (NULL == state) {
449 0 : rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
450 0 : (*done_cls->Run)(done_cls);
451 0 : return;
452 : }
453 10 : state->out_status = &out_args[0]->u.ival;
454 10 : state->cls = done_cls;
455 :
456 10 : rpc->result = NACL_SRPC_RESULT_OK;
457 10 : NaClAppStartModule(nssp->nap,
458 : NaClSecureServiceStartModuleRpcCallback,
459 : (void *) state);
460 :
461 10 : NaClLog(4, "NaClSecureChannelStartModuleRpc: done\n");
462 20 : }
463 :
464 : static void NaClSecureServiceLogRpc(
465 0 : struct NaClSrpcRpc *rpc,
466 0 : struct NaClSrpcArg **in_args,
467 0 : struct NaClSrpcArg **out_args,
468 0 : struct NaClSrpcClosure *done_cls) {
469 0 : int severity = in_args[0]->u.ival;
470 0 : char *msg = in_args[1]->arrays.str;
471 0 : UNREFERENCED_PARAMETER(out_args);
472 :
473 0 : NaClLog(5, "NaClSecureChannelLogRpc\n");
474 0 : NaClLog(severity, "%s\n", msg);
475 0 : NaClLog(5, "NaClSecureChannelLogRpc\n");
476 0 : rpc->result = NACL_SRPC_RESULT_OK;
477 0 : (*done_cls->Run)(done_cls);
478 0 : }
479 :
480 : static void NaClSecureServiceShutdownRpc(
481 2 : struct NaClSrpcRpc *rpc,
482 2 : struct NaClSrpcArg **in_args,
483 2 : struct NaClSrpcArg **out_args,
484 2 : struct NaClSrpcClosure *done) {
485 2 : struct NaClSecureService *nssp =
486 : (struct NaClSecureService *) rpc->channel->server_instance_data;
487 4 : UNREFERENCED_PARAMETER(rpc);
488 4 : UNREFERENCED_PARAMETER(in_args);
489 4 : UNREFERENCED_PARAMETER(out_args);
490 4 : UNREFERENCED_PARAMETER(done);
491 :
492 2 : NaClAppShutdown(nssp->nap, 0);
493 2 : }
494 :
495 : struct NaClSrpcHandlerDesc const kNaClSecureServiceHandlers[] = {
496 : { NACL_SECURE_SERVICE_LOAD_MODULE, NaClSecureServiceLoadModuleRpc, },
497 : { NACL_SECURE_SERVICE_REVERSE_SETUP, NaClSecureServiceReverseSetupRpc, },
498 : { NACL_SECURE_SERVICE_START_MODULE, NaClSecureServiceStartModuleRpc, },
499 : { NACL_SECURE_SERVICE_LOG, NaClSecureServiceLogRpc, },
500 : { NACL_SECURE_SERVICE_HARD_SHUTDOWN, NaClSecureServiceShutdownRpc, },
501 : { (char const *) NULL, (NaClSrpcMethod) NULL, },
502 : };
503 :
504 : struct NaClSimpleServiceVtbl const kNaClSecureServiceVtbl = {
505 : {
506 : NaClSecureServiceDtor,
507 : },
508 : NaClSecureServiceConnectionFactory,
509 : NaClSecureServiceAcceptConnection,
510 : NaClSimpleServiceAcceptAndSpawnHandler,
511 : NaClSecureServiceRpcHandler,
512 : };
513 :
514 : struct NaClSecureRevClientConnHandler {
515 : struct NaClSecureRevClientConnHandler *next;
516 :
517 : /* used by NaClSimpleRevServiceClient's ClientCallback fn */
518 : void (*handler)(
519 : void *state,
520 : struct NaClThreadInterface *tif,
521 : struct NaClDesc *conn);
522 : void *state;
523 : };
524 :
525 : static void NaClSecureReverseClientInternalCallback(
526 4 : void *state,
527 4 : struct NaClThreadInterface *tif,
528 4 : struct NaClDesc *conn) {
529 4 : struct NaClSecureReverseClient *self =
530 : (struct NaClSecureReverseClient *) state;
531 4 : struct NaClSecureRevClientConnHandler *hand_ptr;
532 :
533 4 : NaClLog(4, "Entered NaClSecureReverseClientInternalCallback\n");
534 4 : hand_ptr = (*NACL_VTBL(NaClSecureReverseClient, self)->RemoveHandler)(self);
535 4 : NaClLog(4, " got callback object %"NACL_PRIxPTR"\n", (uintptr_t) hand_ptr);
536 4 : NaClLog(4,
537 : " callback:0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n",
538 : (uintptr_t) hand_ptr->handler,
539 : (uintptr_t) hand_ptr->state,
540 : (uintptr_t) conn);
541 4 : (*hand_ptr->handler)(hand_ptr->state, tif, conn);
542 4 : NaClLog(4, "NaClSecureReverseClientInternalCallback: freeing memory\n");
543 4 : free(hand_ptr);
544 4 : NaClLog(4, "Leaving NaClSecureReverseClientInternalCallback\n");
545 4 : }
546 :
547 : /*
548 : * Require an initial connection handler in the Ctor, so that it's
549 : * obvious that a reverse client needs to accept an IMC connection
550 : * from the server to get things bootstrapped.
551 : */
552 : int NaClSecureReverseClientCtor(
553 3 : struct NaClSecureReverseClient *self,
554 3 : void (*client_callback)(
555 : void *, struct NaClThreadInterface*, struct NaClDesc *),
556 3 : void *state) {
557 3 : NaClLog(4,
558 : "Entered NaClSecureReverseClientCtor, self 0x%"NACL_PRIxPTR"\n",
559 : (uintptr_t) self);
560 3 : if (!NaClSimpleRevClientCtor(&self->base,
561 : NaClSecureReverseClientInternalCallback,
562 : (void *) self,
563 : NaClThreadInterfaceThreadFactory,
564 : (void *) NULL)) {
565 0 : goto failure_simple_ctor;
566 : }
567 3 : NaClLog(4, "NaClSecureReverseClientCtor: Mutex\n");
568 3 : if (!NaClMutexCtor(&self->mu)) {
569 0 : goto failure_mutex_ctor;
570 : }
571 3 : self->queue_head = (struct NaClSecureRevClientConnHandler *) NULL;
572 3 : self->queue_insert = &self->queue_head;
573 :
574 3 : NACL_VTBL(NaClRefCount, self) =
575 : (struct NaClRefCountVtbl *) &kNaClSecureReverseClientVtbl;
576 :
577 3 : NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler\n");
578 3 : if (!(*NACL_VTBL(NaClSecureReverseClient, self)->
579 : InsertHandler)(self, client_callback, state)) {
580 0 : goto failure_handler_insert;
581 : }
582 :
583 3 : NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
584 3 : return 1;
585 :
586 : failure_handler_insert:
587 0 : NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler failed\n");
588 0 : NACL_VTBL(NaClRefCount, self) =
589 : (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
590 :
591 0 : self->queue_insert = (struct NaClSecureRevClientConnHandler **) NULL;
592 0 : NaClMutexDtor(&self->mu);
593 :
594 : failure_mutex_ctor:
595 0 : NaClLog(4, "NaClSecureReverseClientCtor: Mutex failed\n");
596 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
597 : failure_simple_ctor:
598 0 : NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
599 0 : return 0;
600 3 : }
601 :
602 0 : void NaClSecureReverseClientDtor(struct NaClRefCount *vself) {
603 0 : struct NaClSecureReverseClient *self =
604 : (struct NaClSecureReverseClient *) vself;
605 :
606 0 : struct NaClSecureRevClientConnHandler *entry;
607 0 : struct NaClSecureRevClientConnHandler *next;
608 :
609 0 : for (entry = self->queue_head; NULL != entry; entry = next) {
610 0 : next = entry->next;
611 0 : free(entry);
612 0 : }
613 0 : NaClMutexDtor(&self->mu);
614 :
615 0 : NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
616 : &kNaClSimpleRevClientVtbl;
617 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
618 0 : }
619 :
620 : /*
621 : * Caller must set up handler before issuing connection request RPC on
622 : * nap->reverse_channel, since otherwise the connection handler queue
623 : * may be empty and the connect code would abort. Because the connect
624 : * doesn't wait for a handler, we don't need a condvar.
625 : *
626 : * We do not need to serialize on the handlers, since the
627 : * RPC-server/IMC-client implementation should not distinguish one
628 : * connection from another: it is okay for two handlers to be
629 : * inserted, and two connection request RPCs to be preformed
630 : * (sequentially, since they are over a single channel), and have the
631 : * server side spawn threads that asynchronously connect twice, in the
632 : * "incorrect" order, etc.
633 : */
634 : int NaClSecureReverseClientInsertHandler(
635 4 : struct NaClSecureReverseClient *self,
636 4 : void (*handler)(
637 : void *handler_state,
638 : struct NaClThreadInterface *thread_if,
639 : struct NaClDesc *new_conn),
640 4 : void *state) {
641 4 : struct NaClSecureRevClientConnHandler *entry;
642 4 : int retval = 0; /* fail */
643 :
644 4 : NaClLog(4,
645 : ("NaClSecureReverseClientInsertHandler: "
646 : "handler 0x%"NACL_PRIxPTR", state 0x%"NACL_PRIxPTR"\n"),
647 : (uintptr_t) handler, (uintptr_t) state);
648 :
649 4 : NaClXMutexLock(&self->mu);
650 :
651 4 : entry = (struct NaClSecureRevClientConnHandler *) malloc(sizeof *entry);
652 4 : if (NULL == entry) {
653 0 : goto cleanup;
654 : }
655 4 : entry->handler = handler;
656 4 : entry->state = state;
657 4 : entry->next = (struct NaClSecureRevClientConnHandler *) NULL;
658 4 : *self->queue_insert = entry;
659 4 : self->queue_insert = &entry->next;
660 4 : retval = 1;
661 :
662 : cleanup:
663 4 : NaClXMutexUnlock(&self->mu);
664 4 : return retval;
665 : }
666 :
667 : struct NaClSecureRevClientConnHandler *NaClSecureReverseClientRemoveHandler(
668 4 : struct NaClSecureReverseClient *self) {
669 4 : struct NaClSecureRevClientConnHandler *head;
670 :
671 4 : NaClLog(4, "Entered NaClSecureReverseClientRemoveHandler, acquiring lock\n");
672 4 : NaClXMutexLock(&self->mu);
673 4 : NaClLog(4, "NaClSecureReverseClientRemoveHandler, got lock\n");
674 4 : head = self->queue_head;
675 4 : if (NULL == head) {
676 0 : NaClLog(LOG_FATAL,
677 : "NaClSecureReverseClientRemoveHandler: empty handler queue\n");
678 0 : }
679 4 : if (NULL == (self->queue_head = head->next)) {
680 4 : NaClLog(4, "NaClSecureReverseClientRemoveHandler, last elt patch up\n");
681 4 : self->queue_insert = &self->queue_head;
682 4 : }
683 4 : NaClLog(4, "NaClSecureReverseClientRemoveHandler, unlocking\n");
684 4 : NaClXMutexUnlock(&self->mu);
685 :
686 4 : head->next = NULL;
687 4 : NaClLog(4,
688 : ("Leaving NaClSecureReverseClientRemoveHandler:"
689 : " returning %"NACL_PRIxPTR"\n"),
690 : (uintptr_t) head);
691 4 : return head;
692 : }
693 :
694 : struct NaClSecureReverseClientVtbl const kNaClSecureReverseClientVtbl = {
695 : {
696 : {
697 : NaClSecureReverseClientDtor,
698 : },
699 : },
700 : NaClSecureReverseClientInsertHandler,
701 : NaClSecureReverseClientRemoveHandler,
702 : };
|