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 : #define NACL_LOG_MODULE_NAME "reverse_service_c"
7 :
8 : #include "native_client/src/trusted/reverse_service/reverse_service_c.h"
9 :
10 : #include <limits.h>
11 : #include <string.h>
12 :
13 : #include "native_client/src/include/nacl_compiler_annotations.h"
14 : #include "native_client/src/include/portability_io.h"
15 :
16 : #include "native_client/src/public/nacl_file_info.h"
17 :
18 : #include "native_client/src/shared/platform/nacl_check.h"
19 : #include "native_client/src/shared/platform/nacl_host_desc.h"
20 : #include "native_client/src/shared/platform/nacl_log.h"
21 : #include "native_client/src/shared/platform/nacl_sync.h"
22 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
23 : #include "native_client/src/shared/platform/nacl_threads.h"
24 :
25 : #include "native_client/src/shared/srpc/nacl_srpc.h"
26 :
27 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
28 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
29 :
30 : #include "native_client/src/trusted/reverse_service/manifest_rpc.h"
31 : #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h"
32 :
33 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
34 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
35 :
36 : struct NaClSrpcHandlerDesc const kNaClReverseServiceHandlers[]; /* fwd */
37 :
38 : int NaClReverseThreadIfFactoryFn(
39 : void *factory_data,
40 : NaClThreadIfStartFunction fn_ptr,
41 : void *thread_data,
42 : size_t thread_stack_size,
43 : struct NaClThreadInterface **out_new_thread); /* fwd */
44 :
45 5 : int NaClReverseServiceCtor(struct NaClReverseService *self,
46 5 : struct NaClReverseInterface *iface,
47 5 : struct NaClDesc *conn_cap) {
48 5 : int retval = 0; /* fail */
49 :
50 15 : CHECK(iface != NULL);
51 :
52 10 : NaClLog(4, "Entered NaClReverseServiceCtor\n");
53 5 : if (!NaClSimpleRevServiceCtor(&self->base,
54 : conn_cap,
55 : kNaClReverseServiceHandlers,
56 : NaClReverseThreadIfFactoryFn,
57 : (void *) self)) {
58 0 : NaClLog(4, "NaClReverseServiceCtor: NaClSimpleRevServiceCtor failed\n");
59 0 : goto done;
60 : }
61 5 : NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl *)
62 : &kNaClReverseServiceVtbl;
63 5 : if (!NaClMutexCtor(&self->mu)) {
64 0 : NaClLog(4, "NaClMutexCtor failed\n");
65 0 : goto mutex_ctor_fail;
66 : }
67 5 : if (!NaClCondVarCtor(&self->cv)) {
68 0 : NaClLog(4, "NaClCondVar failed\n");
69 0 : goto condvar_ctor_fail;
70 : }
71 : /* success return path */
72 5 : self->iface = (struct NaClReverseInterface *) NaClRefCountRef(
73 : (struct NaClRefCount *) iface);
74 5 : self->thread_count = 0;
75 :
76 5 : retval = 1;
77 5 : goto done;
78 :
79 : /* cleanup unwind */
80 : condvar_ctor_fail:
81 0 : NaClMutexDtor(&self->mu);
82 : mutex_ctor_fail:
83 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
84 : done:
85 5 : return retval;
86 : }
87 :
88 5 : void NaClReverseServiceDtor(struct NaClRefCount *vself) {
89 5 : struct NaClReverseService *self = (struct NaClReverseService *) vself;
90 :
91 5 : if (0 != self->thread_count) {
92 0 : NaClLog(LOG_FATAL,
93 : "ReverseService dtor when thread count is nonzero\n");
94 0 : }
95 5 : self->thread_count = 0;
96 5 : NaClRefCountUnref((struct NaClRefCount *) self->iface);
97 5 : NaClCondVarDtor(&self->cv);
98 5 : NaClMutexDtor(&self->mu);
99 :
100 5 : NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl *)
101 : &kNaClSimpleRevServiceVtbl;
102 5 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
103 5 : }
104 :
105 : static void NaClReverseServiceAddChannelRpc(
106 3 : struct NaClSrpcRpc *rpc,
107 3 : struct NaClSrpcArg **in_args,
108 3 : struct NaClSrpcArg **out_args,
109 3 : struct NaClSrpcClosure *done_cls) {
110 3 : struct NaClReverseService *nrsp =
111 : (struct NaClReverseService *) rpc->channel->server_instance_data;
112 6 : UNREFERENCED_PARAMETER(in_args);
113 :
114 6 : NaClLog(4, "Entered AddChannel\n");
115 3 : out_args[0]->u.ival = (uint32_t)(*NACL_VTBL(NaClSimpleRevService, nrsp)->
116 : ConnectAndSpawnHandlerCb)(&nrsp->base, NULL, (void *) nrsp);
117 6 : NaClLog(4, "Leaving AddChannel\n");
118 3 : rpc->result = NACL_SRPC_RESULT_OK;
119 3 : (*done_cls->Run)(done_cls);
120 3 : }
121 :
122 : static void NaClReverseServiceModuleInitDoneRpc(
123 1 : struct NaClSrpcRpc *rpc,
124 1 : struct NaClSrpcArg **in_args,
125 1 : struct NaClSrpcArg **out_args,
126 1 : struct NaClSrpcClosure *done_cls) {
127 1 : struct NaClReverseService *nrsp =
128 : (struct NaClReverseService *) rpc->channel->server_instance_data;
129 2 : UNREFERENCED_PARAMETER(in_args);
130 2 : UNREFERENCED_PARAMETER(out_args);
131 :
132 2 : NaClLog(4, "Entered ModuleInitDone: service 0x%08"NACL_PRIxPTR"\n",
133 : (uintptr_t) nrsp);
134 2 : NaClLog(4, "ModuleInitDone: invoking StartupInitializationComplete\n");
135 1 : (*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
136 : StartupInitializationComplete)(nrsp->iface);
137 2 : NaClLog(4, "Leaving ModuleInitDoneRpc\n");
138 1 : rpc->result = NACL_SRPC_RESULT_OK;
139 1 : (*done_cls->Run)(done_cls);
140 1 : }
141 :
142 : static void NaClReverseServiceModuleExitRpc(
143 2 : struct NaClSrpcRpc *rpc,
144 2 : struct NaClSrpcArg **in_args,
145 2 : struct NaClSrpcArg **out_args,
146 2 : struct NaClSrpcClosure *done_cls) {
147 2 : struct NaClReverseService *nrsp =
148 : (struct NaClReverseService *) rpc->channel->server_instance_data;
149 2 : int exit_status = in_args[0]->u.ival;
150 4 : UNREFERENCED_PARAMETER(out_args);
151 :
152 4 : NaClLog(4,
153 : ("Entered ModuleExitRpc: service 0x%08"NACL_PRIxPTR
154 : ", exit_status 0x%d\n"),
155 : (uintptr_t) nrsp, exit_status);
156 4 : NaClLog(4, "ModuleExitRpc: invoking ReportExitStatus\n");
157 2 : (*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
158 : ReportExitStatus)(nrsp->iface, exit_status);
159 4 : NaClLog(4, "Leaving ModuleExitRpc\n");
160 2 : rpc->result = NACL_SRPC_RESULT_OK;
161 2 : (*done_cls->Run)(done_cls);
162 2 : }
163 :
164 : static void NaClReverseServicePostMessageRpc(
165 0 : struct NaClSrpcRpc *rpc,
166 0 : struct NaClSrpcArg **in_args,
167 0 : struct NaClSrpcArg **out_args,
168 0 : struct NaClSrpcClosure *done_cls) {
169 0 : struct NaClReverseService *nrsp =
170 : (struct NaClReverseService *) rpc->channel->server_instance_data;
171 0 : char *msg = in_args[0]->arrays.carr;
172 0 : nacl_abi_size_t nbytes = in_args[0]->u.count;
173 :
174 0 : NaClLog(4, "Entered PostMessageRpc: service 0x%08"NACL_PRIxPTR"\n",
175 : (uintptr_t) nrsp);
176 0 : (*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
177 : DoPostMessage)(nrsp->iface, msg, nbytes);
178 0 : out_args[0]->u.ival = nbytes;
179 0 : NaClLog(4, "Leaving PostMessageRpc\n");
180 0 : rpc->result = NACL_SRPC_RESULT_OK;
181 0 : (*done_cls->Run)(done_cls);
182 0 : }
183 :
184 : static void NaClReverseServiceCreateProcessRpc(
185 0 : struct NaClSrpcRpc *rpc,
186 0 : struct NaClSrpcArg **in_args,
187 0 : struct NaClSrpcArg **out_args,
188 0 : struct NaClSrpcClosure *done_cls) {
189 0 : struct NaClReverseService *nrsp =
190 : (struct NaClReverseService *) rpc->channel->server_instance_data;
191 0 : struct NaClDesc *sock_addr;
192 0 : struct NaClDesc *app_addr;
193 0 : int status;
194 0 : UNREFERENCED_PARAMETER(in_args);
195 :
196 0 : NaClLog(4,
197 : "Entered NaClReverseServiceCreateProcessRpc: 0x%08"NACL_PRIxPTR"\n",
198 : (uintptr_t) nrsp);
199 0 : status = (*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
200 : CreateProcess)(nrsp->iface, &sock_addr, &app_addr);
201 0 : out_args[0]->u.ival = status;
202 0 : out_args[1]->u.hval = (0 == status)
203 : ? sock_addr
204 0 : : (struct NaClDesc *) NaClDescInvalidMake();
205 0 : out_args[2]->u.hval = (0 == status)
206 : ? app_addr
207 0 : : (struct NaClDesc *) NaClDescInvalidMake();
208 0 : NaClLog(4, "Leaving NaClReverseServiceCreateProcessRpc\n");
209 0 : rpc->result = NACL_SRPC_RESULT_OK;
210 0 : (*done_cls->Run)(done_cls);
211 0 : }
212 :
213 : struct CreateProcessFunctorState {
214 : struct NaClDesc **out_sock_addr;
215 : struct NaClDesc **out_app_addr;
216 : int32_t *out_pid;
217 : struct NaClSrpcClosure *cls;
218 : };
219 :
220 2 : static void CreateProcessFunctor(void *functor_state,
221 2 : struct NaClDesc *sock_addr,
222 2 : struct NaClDesc *app_addr,
223 2 : int32_t pid) {
224 2 : struct CreateProcessFunctorState *state =
225 : (struct CreateProcessFunctorState *) functor_state;
226 2 : if (NULL == sock_addr) {
227 0 : sock_addr = (struct NaClDesc *) NaClDescInvalidMake();
228 0 : }
229 2 : if (NULL == app_addr) {
230 0 : app_addr = (struct NaClDesc *) NaClDescInvalidMake();
231 0 : }
232 2 : *state->out_sock_addr = sock_addr;
233 2 : *state->out_app_addr = app_addr;
234 2 : *state->out_pid = pid;
235 2 : (*state->cls->Run)(state->cls);
236 2 : }
237 :
238 : static void NaClReverseServiceCreateProcessFunctorResultRpc(
239 2 : struct NaClSrpcRpc *rpc,
240 2 : struct NaClSrpcArg **in_args,
241 2 : struct NaClSrpcArg **out_args,
242 2 : struct NaClSrpcClosure *done_cls) {
243 2 : struct NaClReverseService *nrsp =
244 : (struct NaClReverseService *) rpc->channel->server_instance_data;
245 2 : struct CreateProcessFunctorState functor_state;
246 :
247 4 : UNREFERENCED_PARAMETER(in_args);
248 :
249 4 : NaClLog(4,
250 : "Entered NaClReverseServiceCreateProcessFunctorResultRpc: 0x%08"
251 : NACL_PRIxPTR"\n",
252 : (uintptr_t) nrsp);
253 2 : functor_state.out_sock_addr = &out_args[0]->u.hval;
254 2 : functor_state.out_app_addr = &out_args[1]->u.hval;
255 2 : functor_state.out_pid = &out_args[2]->u.ival;
256 2 : functor_state.cls = done_cls;
257 :
258 2 : rpc->result = NACL_SRPC_RESULT_OK;
259 2 : (*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
260 : CreateProcessFunctorResult)(nrsp->iface,
261 : CreateProcessFunctor, &functor_state);
262 4 : NaClLog(4, "Leaving NaClReverseServiceCreateProcessFunctorResultRpc\n");
263 2 : }
264 :
265 : /*
266 : * Manifest name service, internal APIs.
267 : *
268 : * Manifest file lookups result in read-only file descriptors with a
269 : * handle. When the descriptor is closed, the service runtime must
270 : * inform the plugin of this using the handle, so that the File object
271 : * reference can be closed (thereby allowing the browser to delete or
272 : * otherwise garbage collect the file). Files, being from the
273 : * manifest, cannot be deleted. The manifest is also a read-only
274 : * object, so no new entries can be made to it.
275 : *
276 : * Read-only proxies do not require quota support per se, since we do
277 : * not limit read bandwidth. Quota support is needed for storage
278 : * limits, though could also be used to limit write bandwidth (prevent
279 : * disk output saturation, limit malicious code's ability to cause
280 : * disk failures, especially with flash disks with limited write
281 : * cycles).
282 : */
283 :
284 : /*
285 : * Look up by string name, resulting in a handle (if name is in the
286 : * preimage), a object proxy handle, and an error code.
287 : */
288 : static void NaClReverseServiceManifestLookupRpc(
289 2 : struct NaClSrpcRpc *rpc,
290 2 : struct NaClSrpcArg **in_args,
291 2 : struct NaClSrpcArg **out_args,
292 2 : struct NaClSrpcClosure *done_cls) {
293 2 : struct NaClReverseService *nrsp =
294 : (struct NaClReverseService *) rpc->channel->server_instance_data;
295 2 : char *url_key = in_args[0]->arrays.str;
296 2 : int flags = in_args[0]->u.ival;
297 2 : struct NaClFileInfo info;
298 2 : struct NaClHostDesc *host_desc;
299 2 : struct NaClDescIoDesc *io_desc = NULL;
300 2 : struct NaClDesc *nacl_desc = NULL;
301 :
302 2 : memset(&info, 0, sizeof(info));
303 :
304 4 : NaClLog(4, "Entered ManifestLookupRpc: 0x%08"NACL_PRIxPTR", %s, %d\n",
305 : (uintptr_t) nrsp, url_key, flags);
306 :
307 4 : NaClLog(4, "ManifestLookupRpc: invoking OpenManifestEntry\n");
308 4 : if (!(*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
309 : OpenManifestEntry)(nrsp->iface, url_key, &info)
310 : || -1 == info.desc) {
311 0 : NaClLog(1, "ManifestLookupRpc: OpenManifestEntry failed.\n");
312 0 : out_args[0]->u.ival = NACL_ABI_ENOENT; /* failed */
313 0 : out_args[1]->u.hval = (struct NaClDesc *) NaClDescInvalidMake();
314 0 : out_args[2]->u.lval = 0;
315 0 : out_args[3]->u.lval = 0;
316 0 : out_args[4]->u.count = 0;
317 0 : goto done;
318 : }
319 4 : NaClLog(4, "ManifestLookupRpc: OpenManifestEntry returned desc %d.\n",
320 : info.desc);
321 2 : host_desc = (struct NaClHostDesc *) malloc(sizeof *host_desc);
322 6 : CHECK(host_desc != NULL);
323 6 : CHECK(NaClHostDescPosixTake(host_desc, info.desc, NACL_ABI_O_RDONLY) == 0);
324 2 : io_desc = NaClDescIoDescMake(host_desc);
325 6 : CHECK(io_desc != NULL);
326 2 : nacl_desc = (struct NaClDesc *) io_desc;
327 :
328 2 : out_args[0]->u.ival = 0; /* OK */
329 2 : out_args[1]->u.hval = nacl_desc;
330 2 : out_args[2]->u.lval = (int64_t) info.file_token.lo;
331 2 : out_args[3]->u.lval = (int64_t) info.file_token.hi;
332 2 : out_args[4]->u.count = 10;
333 6 : strncpy(out_args[4]->arrays.carr, "123456789", 10);
334 : /*
335 : * TODO(phosek): the array should be an object reference (issue 3035).
336 : */
337 :
338 : done:
339 2 : rpc->result = NACL_SRPC_RESULT_OK;
340 2 : (*done_cls->Run)(done_cls);
341 2 : NaClDescSafeUnref((struct NaClDesc *) io_desc);
342 2 : }
343 :
344 : static void NaClReverseServiceRequestQuotaForWriteRpc(
345 0 : struct NaClSrpcRpc *rpc,
346 0 : struct NaClSrpcArg **in_args,
347 0 : struct NaClSrpcArg **out_args,
348 0 : struct NaClSrpcClosure *done_cls) {
349 0 : struct NaClReverseService *nrsp =
350 : (struct NaClReverseService *) rpc->channel->server_instance_data;
351 0 : char *file_id = in_args[0]->arrays.carr;
352 0 : int64_t offset = in_args[1]->u.lval;
353 0 : int64_t length = in_args[2]->u.lval;
354 :
355 0 : NaClLog(4, "Entered RequestQuotaForWriteRpc: 0x%08"NACL_PRIxPTR"\n",
356 : (uintptr_t) nrsp);
357 0 : out_args[0]->u.lval = (*NACL_VTBL(NaClReverseInterface, nrsp->iface)->
358 : RequestQuotaForWrite)(nrsp->iface, file_id, offset, length);
359 0 : NaClLog(4, "Leaving RequestQuotaForWriteRpc\n");
360 0 : rpc->result = NACL_SRPC_RESULT_OK;
361 0 : (*done_cls->Run)(done_cls);
362 0 : }
363 :
364 : struct NaClReverseCountingThreadInterface {
365 : struct NaClThreadInterface base NACL_IS_REFCOUNT_SUBCLASS;
366 : struct NaClReverseService *reverse_service;
367 : };
368 :
369 : extern struct NaClThreadInterfaceVtbl
370 : const kNaClReverseThreadInterfaceVtbl; /* fwd */
371 :
372 : int NaClReverseThreadIfCtor_protected(
373 8 : struct NaClReverseCountingThreadInterface *self,
374 8 : void *factory_data,
375 8 : NaClThreadIfStartFunction fn_ptr,
376 8 : void *thread_data,
377 8 : size_t thread_stack_size) {
378 8 : struct NaClReverseService *nrsp = (struct NaClReverseService *) factory_data;
379 :
380 16 : NaClLog(3, "Entered NaClReverseThreadIfCtor_protected\n");
381 16 : if (!NaClThreadInterfaceCtor_protected(
382 : (struct NaClThreadInterface *) self,
383 : NaClReverseThreadIfFactoryFn,
384 8 : NaClRefCountRef((struct NaClRefCount *) nrsp),
385 : fn_ptr,
386 : thread_data,
387 : thread_stack_size)) {
388 0 : NaClLog(4, "NaClThreadInterfaceCtor_protected failed\n");
389 0 : NaClRefCountUnref((struct NaClRefCount *) nrsp);
390 0 : return 0;
391 : }
392 :
393 8 : self->reverse_service = nrsp;
394 8 : (*NACL_VTBL(NaClReverseService, nrsp)->ThreadCountIncr)(nrsp);
395 :
396 8 : NACL_VTBL(NaClRefCount, self) =
397 : (struct NaClRefCountVtbl *) &kNaClReverseThreadInterfaceVtbl;
398 :
399 16 : NaClLog(3, "Leaving NaClAddrSpSquattingThreadIfCtor_protected\n");
400 8 : return 1;
401 8 : }
402 :
403 : /*
404 : * Takes ownership of rev reference. Caller should Ref() the argument
405 : * and Unref on failure if caller does not wish to pass ownership.
406 : */
407 : int NaClReverseThreadIfFactoryFn(
408 8 : void *factory_data,
409 8 : NaClThreadIfStartFunction fn_ptr,
410 8 : void *thread_data,
411 8 : size_t thread_stack_size,
412 8 : struct NaClThreadInterface **out_new_thread) {
413 8 : struct NaClReverseCountingThreadInterface *new_thread;
414 8 : int rv = 1;
415 :
416 16 : NaClLog(3, "Entered NaClReverseThreadIfFactoryFn\n");
417 : new_thread = (struct NaClReverseCountingThreadInterface *)
418 8 : malloc(sizeof *new_thread);
419 8 : if (NULL == new_thread) {
420 0 : rv = 0;
421 0 : goto cleanup;
422 : }
423 :
424 : if (!(rv =
425 8 : NaClReverseThreadIfCtor_protected(new_thread,
426 : factory_data,
427 : fn_ptr,
428 : thread_data,
429 : thread_stack_size))) {
430 0 : goto cleanup;
431 : }
432 :
433 8 : *out_new_thread = (struct NaClThreadInterface *) new_thread;
434 8 : new_thread = NULL;
435 :
436 : cleanup:
437 8 : free(new_thread);
438 16 : NaClLog(3,
439 : "Leaving NaClReverseThreadIfFactoryFn, rv %d\n",
440 : rv);
441 8 : return rv;
442 : }
443 :
444 8 : void NaClReverseThreadIfDtor(struct NaClRefCount *vself) {
445 8 : struct NaClReverseCountingThreadInterface *self =
446 : (struct NaClReverseCountingThreadInterface *) vself;
447 :
448 8 : NaClRefCountUnref((struct NaClRefCount *) self->reverse_service);
449 8 : self->reverse_service = NULL;
450 8 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
451 8 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
452 8 : }
453 :
454 8 : void NaClReverseThreadIfLaunchCallback(struct NaClThreadInterface *self) {
455 16 : NaClLog(4,
456 : ("NaClReverseThreadIfLaunchCallback: thread 0x%"NACL_PRIxPTR
457 : " is launching\n"),
458 : (uintptr_t) self);
459 8 : }
460 :
461 8 : void NaClReverseThreadIfExit(struct NaClThreadInterface *vself,
462 8 : void *exit_code) {
463 8 : struct NaClReverseCountingThreadInterface *self =
464 : (struct NaClReverseCountingThreadInterface *) vself;
465 16 : UNREFERENCED_PARAMETER(exit_code);
466 16 : NaClLog(4,
467 : ("NaClReverseThreadIfExit: thread 0x%"NACL_PRIxPTR
468 : " is exiting\n"),
469 : (uintptr_t) vself);
470 :
471 8 : (*NACL_VTBL(NaClReverseService, self->reverse_service)->ThreadCountDecr)(
472 : self->reverse_service);
473 :
474 8 : NaClRefCountUnref((struct NaClRefCount *) self);
475 8 : NaClThreadExit();
476 8 : }
477 :
478 : struct NaClSrpcHandlerDesc const kNaClReverseServiceHandlers[] = {
479 : { NACL_REVERSE_CONTROL_ADD_CHANNEL, NaClReverseServiceAddChannelRpc, },
480 : { NACL_REVERSE_CONTROL_INIT_DONE, NaClReverseServiceModuleInitDoneRpc, },
481 : { NACL_REVERSE_CONTROL_REPORT_STATUS, NaClReverseServiceModuleExitRpc, },
482 : { NACL_REVERSE_CONTROL_POST_MESSAGE, NaClReverseServicePostMessageRpc, },
483 : { NACL_REVERSE_CONTROL_CREATE_PROCESS, NaClReverseServiceCreateProcessRpc, },
484 : { NACL_REVERSE_CONTROL_CREATE_PROCESS_INTERLOCKED,
485 : NaClReverseServiceCreateProcessFunctorResultRpc, },
486 : { NACL_MANIFEST_LOOKUP, NaClReverseServiceManifestLookupRpc, },
487 : { NACL_REVERSE_REQUEST_QUOTA_FOR_WRITE, NaClReverseServiceRequestQuotaForWriteRpc, },
488 : { (char const *) NULL, (NaClSrpcMethod) NULL, },
489 : };
490 :
491 : struct NaClThreadInterfaceVtbl const kNaClReverseThreadInterfaceVtbl = {
492 : {
493 : NaClReverseThreadIfDtor,
494 : },
495 : NaClThreadInterfaceStartThread,
496 : NaClReverseThreadIfLaunchCallback,
497 : NaClReverseThreadIfExit,
498 : };
499 :
500 5 : static void NaClReverseServiceCbBinder(void *state,
501 5 : int server_loop_ret) {
502 5 : struct NaClReverseService *self = (struct NaClReverseService *) state;
503 10 : UNREFERENCED_PARAMETER(server_loop_ret);
504 :
505 5 : (*NACL_VTBL(NaClReverseInterface, self->iface)->ReportCrash)(
506 : self->iface);
507 5 : }
508 :
509 5 : int NaClStartServiceCb(struct NaClReverseService *self,
510 5 : void (*exit_cb)(void *server_instance_data,
511 : int server_loop_ret),
512 5 : void *instance_data) {
513 5 : int retval = 0; /* fail */
514 :
515 10 : NaClLog(4, "Entered ReverseSocket::StartService\n");
516 :
517 10 : NaClLog(4, "StartService: invoking ConnectAndSpawnHandler\n");
518 5 : if (0 != (*NACL_VTBL(NaClSimpleRevService, self)->
519 : ConnectAndSpawnHandlerCb)((struct NaClSimpleRevService *) self,
520 : exit_cb,
521 : instance_data)) {
522 0 : NaClLog(LOG_ERROR, "StartServiceCb: ConnectAndSpawnHandlerCb failed\n.");
523 0 : goto done;
524 : }
525 5 : retval = 1;
526 :
527 : done:
528 10 : NaClLog(4, "Leaving ReverseSocket::StartService\n");
529 5 : return retval;
530 : }
531 :
532 5 : int NaClReverseServiceStart(struct NaClReverseService *self,
533 5 : int crash_report) {
534 10 : NaClLog(4, "NaClReverseServiceStart: starting service\n");
535 5 : if (0 != crash_report) {
536 5 : return NaClStartServiceCb(self, NaClReverseServiceCbBinder, (void *) self);
537 : } else {
538 0 : return NaClStartServiceCb(self, NULL, (void *) self);
539 : }
540 : return 0;
541 5 : }
542 :
543 : void NaClReverseServiceWaitForServiceThreadsToExit(
544 5 : struct NaClReverseService *self) {
545 10 : NaClLog(4, "NaClReverseServiceWaitForServiceThreadsToExit\n");
546 5 : NaClXMutexLock(&self->mu);
547 13 : while (0 != self->thread_count) {
548 6 : NaClLog(4, "NaClReverseServiceWaitForServiceThreadsToExit: %d left\n",
549 : self->thread_count);
550 3 : NaClXCondVarWait(&self->cv, &self->mu);
551 6 : NaClLog(5, "NaClReverseServiceWaitForServiceThreadsToExit: woke up\n");
552 3 : }
553 5 : NaClXMutexUnlock(&self->mu);
554 10 : NaClLog(4, "NaClReverseServiceWaitForServiceThreadsToExit: all done\n");
555 5 : }
556 :
557 : void NaClReverseServiceThreadCountIncr(
558 8 : struct NaClReverseService *self) {
559 16 : NaClLog(5, "NaClReverseServiceThreadCountIncr\n");
560 8 : NaClXMutexLock(&self->mu);
561 8 : if (0 == ++self->thread_count) {
562 0 : NaClLog(LOG_FATAL,
563 : "NaClReverseServiceThreadCountIncr: "
564 : "thread count overflow!\n");
565 0 : }
566 8 : NaClXMutexUnlock(&self->mu);
567 8 : }
568 :
569 : void NaClReverseServiceThreadCountDecr(
570 8 : struct NaClReverseService *self) {
571 16 : NaClLog(5, "NaClReverseServiceThreadCountDecr\n");
572 8 : NaClXMutexLock(&self->mu);
573 8 : if (0 == self->thread_count) {
574 0 : NaClLog(LOG_FATAL,
575 : "NaClReverseServiceThreadCountDecr: "
576 : "decrementing thread count when count is zero\n");
577 0 : }
578 8 : if (0 == --self->thread_count) {
579 5 : NaClXCondVarBroadcast(&self->cv);
580 5 : }
581 8 : NaClXMutexUnlock(&self->mu);
582 8 : }
583 :
584 : struct NaClReverseServiceVtbl const kNaClReverseServiceVtbl = {
585 : {
586 : {
587 : NaClReverseServiceDtor,
588 : },
589 : NaClSimpleRevServiceConnectAndSpawnHandler,
590 : NaClSimpleRevServiceConnectAndSpawnHandlerCb,
591 : NaClSimpleRevServiceConnectionFactory,
592 : NaClSimpleRevServiceRpcHandler,
593 : },
594 : NaClReverseServiceStart,
595 : NaClReverseServiceWaitForServiceThreadsToExit,
596 : NaClReverseServiceThreadCountIncr,
597 : NaClReverseServiceThreadCountDecr,
598 : };
599 :
600 : int NaClReverseInterfaceCtor_protected(
601 5 : struct NaClReverseInterface *self) {
602 10 : NaClLog(4, "Entered NaClReverseInterfaceCtor_protected\n");
603 5 : if (!NaClRefCountCtor((struct NaClRefCount *) self)) {
604 0 : NaClLog(4,
605 : "NaClReverseInterfaceCtor_protected: "
606 : "NaClRefCountCtor base class ctor failed\n");
607 0 : return 0;
608 : }
609 5 : NACL_VTBL(NaClRefCount, self) =
610 : (struct NaClRefCountVtbl const *) &kNaClReverseInterfaceVtbl;
611 10 : NaClLog(4,
612 : "Leaving NaClReverseInterfaceCtor_protected, returning 1\n");
613 5 : return 1;
614 5 : }
615 :
616 0 : void NaClReverseInterfaceDtor(struct NaClRefCount *vself) {
617 0 : struct NaClReverseInterface *self =
618 : (struct NaClReverseInterface *) vself;
619 :
620 0 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
621 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
622 0 : }
623 :
624 : void NaClReverseInterfaceStartupInitializationComplete(
625 0 : struct NaClReverseInterface *self) {
626 0 : NaClLog(3,
627 : ("NaClReverseInterfaceStartupInitializationComplete(0x%08"
628 : NACL_PRIxPTR")\n"),
629 : (uintptr_t) self);
630 0 : }
631 :
632 : int NaClReverseInterfaceOpenManifestEntry(
633 0 : struct NaClReverseInterface *self,
634 0 : char const *url_key,
635 0 : struct NaClFileInfo *info) {
636 0 : NaClLog(3,
637 : ("NaClReverseInterfaceOpenManifestEntry(0x%08"NACL_PRIxPTR", %s"
638 : ", 0x%08"NACL_PRIxPTR")\n"),
639 : (uintptr_t) self, url_key, (uintptr_t) info);
640 0 : return 0;
641 : }
642 :
643 : void NaClReverseInterfaceReportCrash(
644 0 : struct NaClReverseInterface *self) {
645 0 : NaClLog(3,
646 : "NaClReverseInterfaceReportCrash(0x%08"NACL_PRIxPTR")\n",
647 : (uintptr_t) self);
648 0 : }
649 :
650 : void NaClReverseInterfaceReportExitStatus(
651 0 : struct NaClReverseInterface *self,
652 0 : int exit_status) {
653 0 : NaClLog(3,
654 : "NaClReverseInterfaceReportExitStatus(0x%08"NACL_PRIxPTR", 0x%x)\n",
655 : (uintptr_t) self, exit_status);
656 0 : }
657 :
658 : void NaClReverseInterfaceDoPostMessage(
659 0 : struct NaClReverseInterface *self,
660 0 : char const *message,
661 0 : size_t message_bytes) {
662 0 : NaClLog(3,
663 : ("NaClReverseInterfaceDoPostMessage(0x%08"NACL_PRIxPTR", %s"
664 : ", %08"NACL_PRIuS")\n"),
665 : (uintptr_t) self, message, message_bytes);
666 0 : }
667 :
668 : int NaClReverseInterfaceCreateProcess(
669 0 : struct NaClReverseInterface *self,
670 0 : struct NaClDesc **out_sock_addr,
671 0 : struct NaClDesc **out_app_addr) {
672 0 : NaClLog(3,
673 : ("NaClReverseInterfaceCreateProcess(0x%08"NACL_PRIxPTR
674 : ", 0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxPTR")\n"),
675 : (uintptr_t) self,
676 : (uintptr_t) out_sock_addr,
677 : (uintptr_t) out_app_addr);
678 0 : return -NACL_ABI_EAGAIN;
679 : }
680 :
681 : int64_t NaClReverseInterfaceRequestQuotaForWrite(
682 0 : struct NaClReverseInterface *self,
683 0 : char const *file_id,
684 0 : int64_t offset,
685 0 : int64_t length) {
686 0 : NaClLog(3,
687 : ("NaClReverseInterfaceRequestQuotaForWrite(0x%08"NACL_PRIxPTR", %s"
688 : ", %08"NACL_PRId64", %08"NACL_PRId64")\n"),
689 : (uintptr_t) self, file_id, offset, length);
690 0 : return 0;
691 : }
692 :
693 : void NaClReverseInterfaceCreateProcessFunctorResult(
694 0 : struct NaClReverseInterface *self,
695 0 : void (*result_functor)(void *functor_state,
696 : struct NaClDesc *out_sock_addr,
697 : struct NaClDesc *out_app_addr,
698 : int32_t out_pid_or_errno),
699 0 : void *functor_state) {
700 0 : NaClLog(3,
701 : ("NaClReverseInterfaceCreateProcessFunctorResult(0x%08"NACL_PRIxPTR
702 : ", 0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxPTR")\n"),
703 : (uintptr_t) self,
704 : (uintptr_t) result_functor,
705 : (uintptr_t) functor_state);
706 0 : }
707 :
708 0 : void NaClReverseInterfaceFinalizeProcess(struct NaClReverseInterface *self,
709 0 : int32_t pid) {
710 0 : NaClLog(3,
711 : ("NaClReverseInterfaceFinalizeProcess(0x%08"NACL_PRIxPTR", %d)\n"),
712 : (uintptr_t) self, pid);
713 0 : }
714 :
715 : struct NaClReverseInterfaceVtbl const kNaClReverseInterfaceVtbl = {
716 : {
717 : NaClReverseInterfaceDtor,
718 : },
719 : NaClReverseInterfaceStartupInitializationComplete,
720 : NaClReverseInterfaceOpenManifestEntry,
721 : NaClReverseInterfaceReportCrash,
722 : NaClReverseInterfaceReportExitStatus,
723 : NaClReverseInterfaceDoPostMessage,
724 : NaClReverseInterfaceCreateProcess,
725 : NaClReverseInterfaceCreateProcessFunctorResult,
726 : NaClReverseInterfaceFinalizeProcess,
727 : NaClReverseInterfaceRequestQuotaForWrite,
728 : };
|