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.
9 #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
11 #include "native_client/src/public/name_service.h"
12 #include "native_client/src/shared/platform/nacl_log.h"
13 #include "native_client/src/shared/platform/nacl_sync.h"
14 #include "native_client/src/shared/platform/nacl_sync_checked.h"
15 #include "native_client/src/shared/srpc/nacl_srpc.h"
16 #include "native_client/src/trusted/desc/nacl_desc_io.h"
17 #include "native_client/src/trusted/desc_cacheability/desc_cacheability.h"
18 #include "native_client/src/trusted/reverse_service/manifest_rpc.h"
19 #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h"
20 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
21 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
22 #include "native_client/src/trusted/service_runtime/nacl_secure_service.h"
23 #include "native_client/src/trusted/validator/nacl_file_info.h"
24 #include "native_client/src/trusted/validator/rich_file_info.h"
25 #include "native_client/src/trusted/validator/validation_cache.h"
27 static void NaClManifestWaitForChannel_yield_mu(
28 struct NaClManifestProxyConnection *self) {
29 NaClLog(4, "Entered NaClManifestWaitForChannel_yield_mu\n");
30 NaClXMutexLock(&self->mu);
31 NaClLog(4, "NaClManifestWaitForChannel_yield_mu: checking channel\n");
32 while (!self->channel_initialized) {
33 NaClLog(4, "NaClManifestWaitForChannel_yield_mu: waiting\n");
34 NaClXCondVarWait(&self->cv, &self->mu);
36 NaClLog(4, "Leaving NaClManifestWaitForChannel_yield_mu\n");
39 static void NaClManifestReleaseChannel_release_mu(
40 struct NaClManifestProxyConnection *self) {
41 NaClLog(4, "NaClManifestReleaseChannel_release_mu\n");
42 NaClXMutexUnlock(&self->mu);
45 static void NaClManifestNameServiceListRpc(
46 struct NaClSrpcRpc *rpc,
47 struct NaClSrpcArg **in_args,
48 struct NaClSrpcArg **out_args,
49 struct NaClSrpcClosure *done_cls) {
50 struct NaClManifestProxyConnection *proxy_conn =
51 (struct NaClManifestProxyConnection *) rpc->channel->server_instance_data;
52 uint32_t nbytes = out_args[0]->u.count;
53 char *dest = out_args[0]->arrays.carr;
54 NaClSrpcError srpc_error;
56 UNREFERENCED_PARAMETER(in_args);
58 "NaClManifestNameServiceListRpc, proxy_conn 0x%"NACL_PRIxPTR"\n",
59 (uintptr_t) proxy_conn);
61 NaClManifestWaitForChannel_yield_mu(proxy_conn);
64 ("NaClManifestNameServiceListRpc: nbytes %"NACL_PRIu32", dest"
65 " 0x%"NACL_PRIxPTR"\n"),
66 nbytes, (uintptr_t) dest);
67 if (NACL_SRPC_RESULT_OK !=
69 NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
73 ("Manifest list via channel 0x%"NACL_PRIxPTR" with RPC "
74 NACL_MANIFEST_LIST" failed: %d\n"),
75 (uintptr_t) &proxy_conn->client_channel,
77 rpc->result = srpc_error;
80 "NaClManifestNameServiceListRpc, proxy returned %"NACL_PRId32
83 out_args[0]->u.count = nbytes;
84 rpc->result = NACL_SRPC_RESULT_OK;
86 (*done_cls->Run)(done_cls);
87 NaClManifestReleaseChannel_release_mu(proxy_conn);
90 static void NaClManifestNameServiceInsertRpc(
91 struct NaClSrpcRpc *rpc,
92 struct NaClSrpcArg **in_args,
93 struct NaClSrpcArg **out_args,
94 struct NaClSrpcClosure *done_cls) {
96 UNREFERENCED_PARAMETER(in_args);
97 NaClLog(4, "NaClManifestNameServiceInsertRpc\n");
98 out_args[0]->u.ival = NACL_NAME_SERVICE_PERMISSION_DENIED;
99 /* cannot add names to the manifest! */
100 rpc->result = NACL_SRPC_RESULT_OK;
101 (*done_cls->Run)(done_cls);
104 static void NaClManifestNameServiceLookupRpc(
105 struct NaClSrpcRpc *rpc,
106 struct NaClSrpcArg **in_args,
107 struct NaClSrpcArg **out_args,
108 struct NaClSrpcClosure *done_cls) {
109 struct NaClManifestProxyConnection *proxy_conn =
110 (struct NaClManifestProxyConnection *) rpc->channel->server_instance_data;
111 char *name = in_args[0]->arrays.str;
112 int flags = in_args[1]->u.ival;
114 uint32_t cookie_size = sizeof cookie;
116 struct NaClDesc *desc;
117 struct NaClFileToken file_token;
118 NaClSrpcError srpc_error;
120 NaClLog(4, "NaClManifestNameServiceLookupRpc\n");
122 NaClManifestWaitForChannel_yield_mu(proxy_conn);
125 "NaClManifestNameServiceLookupRpc: name %s, flags %d\n",
128 "NaClManifestNameServiceLookupRpc: invoking %s\n",
129 NACL_MANIFEST_LOOKUP);
131 if (NACL_SRPC_RESULT_OK !=
133 NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
134 NACL_MANIFEST_LOOKUP,
144 ("Manifest lookup via channel 0x%"NACL_PRIxPTR" with RPC "
145 NACL_MANIFEST_LOOKUP" failed: %d\n"),
146 (uintptr_t) &proxy_conn->client_channel,
148 rpc->result = srpc_error;
150 struct NaClManifestProxy *proxy =
151 (struct NaClManifestProxy *) proxy_conn->base.server;
152 struct NaClValidationCache *validation_cache =
153 proxy->server->nap->validation_cache;
154 struct NaClDesc *replacement_desc;
157 * The cookie is used to release renderer-side pepper file handle.
158 * For now, we leak. We need on-close callbacks on NaClDesc
159 * objects to do this properly, but even that is insufficient
160 * since the manifest NaClDesc could, in principle, be transferred
161 * to another process -- we would need distributed garbage
162 * protection. If Pepper could take advantage of host-OS-side
163 * reference counting that is already done, this wouldn't be a
167 "NaClManifestNameServiceLookupRpc: got cookie %.*s\n",
168 cookie_size, cookie);
169 replacement_desc = NaClExchangeFileTokenForMappableDesc(&file_token,
171 if (NULL != replacement_desc) {
173 desc = replacement_desc;
176 out_args[0]->u.ival = status;
177 out_args[1]->u.hval = desc;
178 rpc->result = NACL_SRPC_RESULT_OK;
180 (*done_cls->Run)(done_cls);
182 NaClManifestReleaseChannel_release_mu(proxy_conn);
185 static void NaClManifestNameServiceDeleteRpc(
186 struct NaClSrpcRpc *rpc,
187 struct NaClSrpcArg **in_args,
188 struct NaClSrpcArg **out_args,
189 struct NaClSrpcClosure *done_cls) {
191 UNREFERENCED_PARAMETER(in_args);
192 NaClLog(4, "NaClManifestNameServiceDeleteRpc\n");
193 out_args[0]->u.ival = NACL_NAME_SERVICE_PERMISSION_DENIED;
194 rpc->result = NACL_SRPC_RESULT_OK;
195 (*done_cls->Run)(done_cls);
198 struct NaClSrpcHandlerDesc const kNaClManifestProxyHandlers[] = {
199 { NACL_NAME_SERVICE_LIST, NaClManifestNameServiceListRpc, },
200 { NACL_NAME_SERVICE_INSERT, NaClManifestNameServiceInsertRpc, },
201 { NACL_NAME_SERVICE_LOOKUP, NaClManifestNameServiceLookupRpc, },
202 { NACL_NAME_SERVICE_DELETE, NaClManifestNameServiceDeleteRpc, },
203 { (char const *) NULL, (NaClSrpcMethod) NULL, },
207 int NaClManifestProxyCtor(struct NaClManifestProxy *self,
208 NaClThreadIfFactoryFunction thread_factory_fn,
209 void *thread_factory_data,
210 struct NaClSecureService *server) {
212 ("Entered NaClManifestProxyCtor: self 0x%"NACL_PRIxPTR
213 ", client 0x%"NACL_PRIxPTR"\n"),
216 if (!NaClSimpleServiceCtor(&self->base,
217 kNaClManifestProxyHandlers,
219 thread_factory_data)) {
222 self->server = (struct NaClSecureService *)
223 NaClRefCountRef((struct NaClRefCount *) server);
224 NACL_VTBL(NaClRefCount, self) =
225 (struct NaClRefCountVtbl *) &kNaClManifestProxyVtbl;
229 static void NaClManifestProxyDtor(struct NaClRefCount *vself) {
230 struct NaClManifestProxy *self =
231 (struct NaClManifestProxy *) vself;
233 NaClRefCountUnref((struct NaClRefCount *) self->server);
235 NACL_VTBL(NaClRefCount, self) =
236 (struct NaClRefCountVtbl *) &kNaClSimpleServiceVtbl;
237 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
240 int NaClManifestProxyConnectionCtor(struct NaClManifestProxyConnection *self,
241 struct NaClManifestProxy *server,
242 struct NaClDesc *conn) {
244 "Entered NaClManifestProxyConnectionCtor, self 0x%"NACL_PRIxPTR"\n",
246 if (!NaClSimpleServiceConnectionCtor(
248 (struct NaClSimpleService *) server,
252 ("NaClManifestProxyConnectionCtor: base class ctor"
253 " NaClSimpleServiceConnectionCtor failed\n"));
256 NaClXMutexCtor(&self->mu);
257 NaClXCondVarCtor(&self->cv);
258 self->channel_initialized = 0;
259 NACL_VTBL(NaClRefCount, self) =
260 (struct NaClRefCountVtbl *) &kNaClManifestProxyConnectionVtbl;
264 void NaClManifestProxyConnectionRevHandleConnect(
265 struct NaClManifestProxyConnection *self,
266 struct NaClDesc *rev) {
267 NaClLog(4, "Entered NaClManifestProxyConnectionRevHandleConnect\n");
268 NaClXMutexLock(&self->mu);
269 if (self->channel_initialized) {
271 "NaClManifestProxyConnectionRevHandleConnect: double connect?\n");
274 * If NaClSrpcClientCtor proves to take too long, we should spin off
275 * another thread to do the initialization so that the reverse
276 * client can accept additional reverse channels.
279 "NaClManifestProxyConnectionRevHandleConnect: Creating SrpcClient\n");
280 if (NaClSrpcClientCtor(&self->client_channel, rev)) {
282 ("NaClManifestProxyConnectionRevHandleConnect: SrpcClientCtor"
283 " succeded, announcing.\n"));
284 self->channel_initialized = 1;
285 NaClXCondVarBroadcast(&self->cv);
286 /* ownership of rev taken */
289 ("NaClManifestProxyConnectionRevHandleConnect: NaClSrpcClientCtor"
292 NaClXMutexUnlock(&self->mu);
293 NaClLog(4, "Leaving NaClManifestProxyConnectionRevHandleConnect\n");
296 static void NaClManifestProxyConnectionDtor(struct NaClRefCount *vself) {
297 struct NaClManifestProxyConnection *self =
298 (struct NaClManifestProxyConnection *) vself;
300 "Entered NaClManifestProxyConnectionDtor: self 0x%"NACL_PRIxPTR"\n",
302 NaClXMutexLock(&self->mu);
303 while (!self->channel_initialized) {
305 "NaClManifestProxyConnectionDtor:"
306 " waiting for connection initialization\n");
307 NaClXCondVarWait(&self->cv, &self->mu);
309 NaClXMutexUnlock(&self->mu);
311 NaClLog(4, "NaClManifestProxyConnectionDtor: dtoring\n");
313 NaClCondVarDtor(&self->cv);
314 NaClMutexDtor(&self->mu);
316 NaClSrpcDtor(&self->client_channel);
317 NACL_VTBL(NaClSimpleServiceConnection, self) =
318 &kNaClSimpleServiceConnectionVtbl;
319 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
323 * NaClManifestProxyConnection is a NaClSimpleServiceConnection
325 struct NaClSimpleServiceConnectionVtbl
326 const kNaClManifestProxyConnectionVtbl = {
328 NaClManifestProxyConnectionDtor,
330 NaClSimpleServiceConnectionServerLoop,
333 static void NaClManifestReverseClientCallback(
335 struct NaClThreadInterface *tif,
336 struct NaClDesc *new_conn) {
337 struct NaClManifestProxyConnection *mconn =
338 (struct NaClManifestProxyConnection *) state;
340 UNREFERENCED_PARAMETER(tif);
341 NaClLog(4, "Entered NaClManifestReverseClientCallback\n");
342 NaClManifestProxyConnectionRevHandleConnect(mconn, new_conn);
345 int NaClManifestProxyConnectionFactory(
346 struct NaClSimpleService *vself,
347 struct NaClDesc *conn,
348 struct NaClSimpleServiceConnection **out) {
349 struct NaClManifestProxy *self =
350 (struct NaClManifestProxy *) vself;
351 struct NaClManifestProxyConnection *mconn;
352 NaClSrpcError rpc_result;
356 ("Entered NaClManifestProxyConnectionFactory, self 0x%"NACL_PRIxPTR
359 mconn = (struct NaClManifestProxyConnection *) malloc(sizeof *mconn);
361 NaClLog(4, "NaClManifestProxyConnectionFactory: no memory\n");
362 return -NACL_ABI_ENOMEM;
364 NaClLog(4, "NaClManifestProxyConnectionFactory: creating connection obj\n");
365 if (!NaClManifestProxyConnectionCtor(mconn, self, conn)) {
367 return -NACL_ABI_EIO;
371 * Construct via NaClSecureReverseClientCtor with a callback to
372 * process the new reverse connection -- which should be stored in
375 * Make reverse RPC to obtain a new reverse RPC connection.
377 NaClLog(4, "NaClManifestProxyConnectionFactory: locking reverse channel\n");
378 NaClLog(4, "NaClManifestProxyConnectionFactory: client 0x%"NACL_PRIxPTR"\n",
379 (uintptr_t) self->server);
380 NaClXMutexLock(&self->server->mu);
381 if (NACL_REVERSE_CHANNEL_INITIALIZED !=
382 self->server->reverse_channel_initialization_state) {
384 "NaClManifestProxyConnectionFactory invoked w/o reverse channel\n");
386 NaClLog(4, "NaClManifestProxyConnectionFactory: inserting handler\n");
387 if (!(*NACL_VTBL(NaClSecureReverseClient, self->server->reverse_client)->
388 InsertHandler)(self->server->reverse_client,
389 NaClManifestReverseClientCallback,
392 ("NaClManifestProxyConnectionFactory:"
393 " NaClSecureReverseClientInsertHandler failed\n"));
396 * NaClSrpcInvokeBySignature(""); tell plugin to connect and create
400 ("NaClManifestProxyConnectionFactory: making RPC"
401 " to set up connection\n"));
402 rpc_result = NaClSrpcInvokeBySignature(&self->server->reverse_channel,
403 NACL_REVERSE_CONTROL_ADD_CHANNEL,
405 if (NACL_SRPC_RESULT_OK != rpc_result) {
407 "NaClManifestProxyConnectionFactory: add channel RPC failed: %d",
411 "NaClManifestProxyConnectionFactory: Start status %d\n", bool_status);
413 NaClXMutexUnlock(&self->server->mu);
415 *out = (struct NaClSimpleServiceConnection *) mconn;
419 struct NaClSimpleServiceVtbl const kNaClManifestProxyVtbl = {
421 NaClManifestProxyDtor,
423 NaClManifestProxyConnectionFactory,
424 /* see name_service.c vtbl for connection factory and ownership */
426 * The NaClManifestProxyConnectionFactory creates a subclass of a
427 * NaClSimpleServiceConnectionFactory object that uses the reverse
428 * connection object self->server to obtain a new RPC channel
429 * with each manifest connection.
431 NaClSimpleServiceAcceptConnection,
432 NaClSimpleServiceAcceptAndSpawnHandler,
433 NaClSimpleServiceRpcHandler,