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.
7 #define NACL_LOG_MODULE_NAME "manifest_proxy"
11 #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
13 #include "native_client/src/public/name_service.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 #include "native_client/src/trusted/desc/nacl_desc_io.h"
19 #include "native_client/src/trusted/desc_cacheability/desc_cacheability.h"
20 #include "native_client/src/trusted/reverse_service/manifest_rpc.h"
21 #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h"
22 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
23 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
24 #include "native_client/src/trusted/service_runtime/nacl_secure_service.h"
25 #include "native_client/src/trusted/validator/nacl_file_info.h"
26 #include "native_client/src/trusted/validator/rich_file_info.h"
27 #include "native_client/src/trusted/validator/validation_cache.h"
29 static void NaClManifestWaitForChannel_yield_mu(
30 struct NaClManifestProxyConnection *self) {
31 NaClLog(4, "Entered NaClManifestWaitForChannel_yield_mu\n");
32 NaClXMutexLock(&self->mu);
33 NaClLog(4, "NaClManifestWaitForChannel_yield_mu: checking channel\n");
34 while (!self->channel_initialized) {
35 NaClLog(4, "NaClManifestWaitForChannel_yield_mu: waiting\n");
36 NaClXCondVarWait(&self->cv, &self->mu);
38 NaClLog(4, "Leaving NaClManifestWaitForChannel_yield_mu\n");
41 static void NaClManifestReleaseChannel_release_mu(
42 struct NaClManifestProxyConnection *self) {
43 NaClLog(4, "NaClManifestReleaseChannel_release_mu\n");
44 NaClXMutexUnlock(&self->mu);
47 static void NaClManifestNameServiceInsertRpc(
48 struct NaClSrpcRpc *rpc,
49 struct NaClSrpcArg **in_args,
50 struct NaClSrpcArg **out_args,
51 struct NaClSrpcClosure *done_cls) {
53 UNREFERENCED_PARAMETER(in_args);
54 NaClLog(4, "NaClManifestNameServiceInsertRpc\n");
55 out_args[0]->u.ival = NACL_NAME_SERVICE_PERMISSION_DENIED;
56 /* cannot add names to the manifest! */
57 rpc->result = NACL_SRPC_RESULT_OK;
58 (*done_cls->Run)(done_cls);
61 static void NaClManifestNameServiceLookupRpc(
62 struct NaClSrpcRpc *rpc,
63 struct NaClSrpcArg **in_args,
64 struct NaClSrpcArg **out_args,
65 struct NaClSrpcClosure *done_cls) {
66 struct NaClManifestProxyConnection *proxy_conn =
67 (struct NaClManifestProxyConnection *) rpc->channel->server_instance_data;
68 char *name = in_args[0]->arrays.str;
69 int flags = in_args[1]->u.ival;
71 uint32_t cookie_size = sizeof cookie;
73 struct NaClDesc *desc;
74 struct NaClFileToken file_token;
75 NaClSrpcError srpc_error;
77 NaClLog(4, "NaClManifestNameServiceLookupRpc\n");
79 NaClManifestWaitForChannel_yield_mu(proxy_conn);
82 "NaClManifestNameServiceLookupRpc: name %s, flags %d\n",
85 "NaClManifestNameServiceLookupRpc: invoking %s\n",
86 NACL_MANIFEST_LOOKUP);
88 if (NACL_SRPC_RESULT_OK !=
90 NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
101 ("Manifest lookup via channel 0x%"NACL_PRIxPTR" with RPC "
102 NACL_MANIFEST_LOOKUP" failed: %d\n"),
103 (uintptr_t) &proxy_conn->client_channel,
105 rpc->result = srpc_error;
107 struct NaClManifestProxy *proxy =
108 (struct NaClManifestProxy *) proxy_conn->base.server;
109 struct NaClValidationCache *validation_cache =
110 proxy->server->nap->validation_cache;
111 struct NaClDesc *replacement_desc;
114 * The cookie is used to release renderer-side pepper file handle.
115 * For now, we leak. We need on-close callbacks on NaClDesc
116 * objects to do this properly, but even that is insufficient
117 * since the manifest NaClDesc could, in principle, be transferred
118 * to another process -- we would need distributed garbage
119 * protection. If Pepper could take advantage of host-OS-side
120 * reference counting that is already done, this wouldn't be a
124 "NaClManifestNameServiceLookupRpc: got cookie %.*s\n",
125 cookie_size, cookie);
126 replacement_desc = NaClExchangeFileTokenForMappableDesc(&file_token,
128 if (NULL != replacement_desc) {
130 desc = replacement_desc;
133 out_args[0]->u.ival = status;
134 out_args[1]->u.hval = desc;
135 rpc->result = NACL_SRPC_RESULT_OK;
137 (*done_cls->Run)(done_cls);
139 NaClManifestReleaseChannel_release_mu(proxy_conn);
142 static void NaClManifestNameServiceDeleteRpc(
143 struct NaClSrpcRpc *rpc,
144 struct NaClSrpcArg **in_args,
145 struct NaClSrpcArg **out_args,
146 struct NaClSrpcClosure *done_cls) {
148 UNREFERENCED_PARAMETER(in_args);
149 NaClLog(4, "NaClManifestNameServiceDeleteRpc\n");
150 out_args[0]->u.ival = NACL_NAME_SERVICE_PERMISSION_DENIED;
151 rpc->result = NACL_SRPC_RESULT_OK;
152 (*done_cls->Run)(done_cls);
155 struct NaClSrpcHandlerDesc const kNaClManifestProxyHandlers[] = {
156 { NACL_NAME_SERVICE_INSERT, NaClManifestNameServiceInsertRpc, },
157 { NACL_NAME_SERVICE_LOOKUP, NaClManifestNameServiceLookupRpc, },
158 { NACL_NAME_SERVICE_DELETE, NaClManifestNameServiceDeleteRpc, },
159 { (char const *) NULL, (NaClSrpcMethod) NULL, },
163 int NaClManifestProxyCtor(struct NaClManifestProxy *self,
164 NaClThreadIfFactoryFunction thread_factory_fn,
165 void *thread_factory_data,
166 struct NaClSecureService *server) {
168 ("Entered NaClManifestProxyCtor: self 0x%"NACL_PRIxPTR
169 ", client 0x%"NACL_PRIxPTR"\n"),
172 if (!NaClSimpleServiceCtor(&self->base,
173 kNaClManifestProxyHandlers,
175 thread_factory_data)) {
178 self->server = (struct NaClSecureService *)
179 NaClRefCountRef((struct NaClRefCount *) server);
180 NACL_VTBL(NaClRefCount, self) =
181 (struct NaClRefCountVtbl *) &kNaClManifestProxyVtbl;
185 static void NaClManifestProxyDtor(struct NaClRefCount *vself) {
186 struct NaClManifestProxy *self =
187 (struct NaClManifestProxy *) vself;
189 NaClRefCountUnref((struct NaClRefCount *) self->server);
191 NACL_VTBL(NaClRefCount, self) =
192 (struct NaClRefCountVtbl *) &kNaClSimpleServiceVtbl;
193 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
196 int NaClManifestProxyConnectionCtor(struct NaClManifestProxyConnection *self,
197 struct NaClManifestProxy *server,
198 struct NaClDesc *conn) {
200 "Entered NaClManifestProxyConnectionCtor, self 0x%"NACL_PRIxPTR"\n",
202 if (!NaClSimpleServiceConnectionCtor(
204 (struct NaClSimpleService *) server,
208 ("NaClManifestProxyConnectionCtor: base class ctor"
209 " NaClSimpleServiceConnectionCtor failed\n"));
212 NaClXMutexCtor(&self->mu);
213 NaClXCondVarCtor(&self->cv);
214 self->channel_initialized = 0;
215 NACL_VTBL(NaClRefCount, self) =
216 (struct NaClRefCountVtbl *) &kNaClManifestProxyConnectionVtbl;
220 void NaClManifestProxyConnectionRevHandleConnect(
221 struct NaClManifestProxyConnection *self,
222 struct NaClDesc *rev) {
223 NaClLog(4, "Entered NaClManifestProxyConnectionRevHandleConnect\n");
224 NaClXMutexLock(&self->mu);
225 if (self->channel_initialized) {
227 "NaClManifestProxyConnectionRevHandleConnect: double connect?\n");
230 * If NaClSrpcClientCtor proves to take too long, we should spin off
231 * another thread to do the initialization so that the reverse
232 * client can accept additional reverse channels.
235 "NaClManifestProxyConnectionRevHandleConnect: Creating SrpcClient\n");
236 if (NaClSrpcClientCtor(&self->client_channel, rev)) {
238 ("NaClManifestProxyConnectionRevHandleConnect: SrpcClientCtor"
239 " succeded, announcing.\n"));
240 self->channel_initialized = 1;
241 NaClXCondVarBroadcast(&self->cv);
242 /* ownership of rev taken */
245 ("NaClManifestProxyConnectionRevHandleConnect: NaClSrpcClientCtor"
248 NaClXMutexUnlock(&self->mu);
249 NaClLog(4, "Leaving NaClManifestProxyConnectionRevHandleConnect\n");
252 static void NaClManifestProxyConnectionDtor(struct NaClRefCount *vself) {
253 struct NaClManifestProxyConnection *self =
254 (struct NaClManifestProxyConnection *) vself;
256 "Entered NaClManifestProxyConnectionDtor: self 0x%"NACL_PRIxPTR"\n",
258 NaClXMutexLock(&self->mu);
259 while (!self->channel_initialized) {
261 "NaClManifestProxyConnectionDtor:"
262 " waiting for connection initialization\n");
263 NaClXCondVarWait(&self->cv, &self->mu);
265 NaClXMutexUnlock(&self->mu);
267 NaClLog(4, "NaClManifestProxyConnectionDtor: dtoring\n");
269 NaClCondVarDtor(&self->cv);
270 NaClMutexDtor(&self->mu);
272 NaClSrpcDtor(&self->client_channel);
273 NACL_VTBL(NaClSimpleServiceConnection, self) =
274 &kNaClSimpleServiceConnectionVtbl;
275 (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
279 * NaClManifestProxyConnection is a NaClSimpleServiceConnection
281 struct NaClSimpleServiceConnectionVtbl
282 const kNaClManifestProxyConnectionVtbl = {
284 NaClManifestProxyConnectionDtor,
286 NaClSimpleServiceConnectionServerLoop,
289 static void NaClManifestReverseClientCallback(
291 struct NaClThreadInterface *tif,
292 struct NaClDesc *new_conn) {
293 struct NaClManifestProxyConnection *mconn =
294 (struct NaClManifestProxyConnection *) state;
296 UNREFERENCED_PARAMETER(tif);
297 NaClLog(4, "Entered NaClManifestReverseClientCallback\n");
298 NaClManifestProxyConnectionRevHandleConnect(mconn, new_conn);
301 int NaClManifestProxyConnectionFactory(
302 struct NaClSimpleService *vself,
303 struct NaClDesc *conn,
304 struct NaClSimpleServiceConnection **out) {
305 struct NaClManifestProxy *self =
306 (struct NaClManifestProxy *) vself;
307 struct NaClManifestProxyConnection *mconn;
308 NaClSrpcError rpc_result;
312 ("Entered NaClManifestProxyConnectionFactory, self 0x%"NACL_PRIxPTR
315 mconn = (struct NaClManifestProxyConnection *) malloc(sizeof *mconn);
317 NaClLog(4, "NaClManifestProxyConnectionFactory: no memory\n");
318 return -NACL_ABI_ENOMEM;
320 NaClLog(4, "NaClManifestProxyConnectionFactory: creating connection obj\n");
321 if (!NaClManifestProxyConnectionCtor(mconn, self, conn)) {
323 return -NACL_ABI_EIO;
327 * Construct via NaClSecureReverseClientCtor with a callback to
328 * process the new reverse connection -- which should be stored in
331 * Make reverse RPC to obtain a new reverse RPC connection.
333 NaClLog(4, "NaClManifestProxyConnectionFactory: locking reverse channel\n");
334 NaClLog(4, "NaClManifestProxyConnectionFactory: client 0x%"NACL_PRIxPTR"\n",
335 (uintptr_t) self->server);
336 NaClXMutexLock(&self->server->mu);
337 if (NACL_REVERSE_CHANNEL_INITIALIZED !=
338 self->server->reverse_channel_initialization_state) {
340 "NaClManifestProxyConnectionFactory invoked w/o reverse channel\n");
342 NaClLog(4, "NaClManifestProxyConnectionFactory: inserting handler\n");
343 if (!(*NACL_VTBL(NaClSecureReverseClient, self->server->reverse_client)->
344 InsertHandler)(self->server->reverse_client,
345 NaClManifestReverseClientCallback,
348 ("NaClManifestProxyConnectionFactory:"
349 " NaClSecureReverseClientInsertHandler failed\n"));
352 * NaClSrpcInvokeBySignature(""); tell plugin to connect and create
356 ("NaClManifestProxyConnectionFactory: making RPC"
357 " to set up connection\n"));
358 rpc_result = NaClSrpcInvokeBySignature(&self->server->reverse_channel,
359 NACL_REVERSE_CONTROL_ADD_CHANNEL,
361 if (NACL_SRPC_RESULT_OK != rpc_result) {
363 "NaClManifestProxyConnectionFactory: add channel RPC failed: %d",
367 "NaClManifestProxyConnectionFactory: Start status %d\n", bool_status);
369 NaClXMutexUnlock(&self->server->mu);
371 *out = (struct NaClSimpleServiceConnection *) mconn;
375 struct NaClSimpleServiceVtbl const kNaClManifestProxyVtbl = {
377 NaClManifestProxyDtor,
379 NaClManifestProxyConnectionFactory,
380 /* see name_service.c vtbl for connection factory and ownership */
382 * The NaClManifestProxyConnectionFactory creates a subclass of a
383 * NaClSimpleServiceConnectionFactory object that uses the reverse
384 * connection object self->server to obtain a new RPC channel
385 * with each manifest connection.
387 NaClSimpleServiceAcceptConnection,
388 NaClSimpleServiceAcceptAndSpawnHandler,
389 NaClSimpleServiceRpcHandler,