Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / manifest_name_service_proxy / manifest_proxy.c
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 #define NACL_LOG_MODULE_NAME "manifest_proxy"
8
9 #include <string.h>
10
11 #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
12
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"
28
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);
37   }
38   NaClLog(4, "Leaving NaClManifestWaitForChannel_yield_mu\n");
39 }
40
41 static void NaClManifestReleaseChannel_release_mu(
42     struct NaClManifestProxyConnection *self) {
43   NaClLog(4, "NaClManifestReleaseChannel_release_mu\n");
44   NaClXMutexUnlock(&self->mu);
45 }
46
47 static void NaClManifestNameServiceInsertRpc(
48     struct NaClSrpcRpc      *rpc,
49     struct NaClSrpcArg      **in_args,
50     struct NaClSrpcArg      **out_args,
51     struct NaClSrpcClosure  *done_cls) {
52
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);
59 }
60
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;
70   char                                cookie[20];
71   uint32_t                            cookie_size = sizeof cookie;
72   int                                 status;
73   struct NaClDesc                     *desc;
74   struct NaClFileToken                file_token;
75   NaClSrpcError                       srpc_error;
76
77   NaClLog(4, "NaClManifestNameServiceLookupRpc\n");
78
79   NaClManifestWaitForChannel_yield_mu(proxy_conn);
80
81   NaClLog(4,
82           "NaClManifestNameServiceLookupRpc: name %s, flags %d\n",
83           name, flags);
84   NaClLog(4,
85           "NaClManifestNameServiceLookupRpc: invoking %s\n",
86           NACL_MANIFEST_LOOKUP);
87
88   if (NACL_SRPC_RESULT_OK !=
89       (srpc_error =
90        NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
91                                  NACL_MANIFEST_LOOKUP,
92                                  name,
93                                  flags,
94                                  &status,
95                                  &desc,
96                                  &file_token.lo,
97                                  &file_token.hi,
98                                  &cookie_size,
99                                  cookie))) {
100     NaClLog(LOG_ERROR,
101             ("Manifest lookup via channel 0x%"NACL_PRIxPTR" with RPC "
102              NACL_MANIFEST_LOOKUP" failed: %d\n"),
103             (uintptr_t) &proxy_conn->client_channel,
104             srpc_error);
105     rpc->result = srpc_error;
106   } else {
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;
112
113     /*
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
121      * problem.
122      */
123     NaClLog(4,
124             "NaClManifestNameServiceLookupRpc: got cookie %.*s\n",
125             cookie_size, cookie);
126     replacement_desc = NaClExchangeFileTokenForMappableDesc(&file_token,
127                                                             validation_cache);
128     if (NULL != replacement_desc) {
129       NaClDescUnref(desc);
130       desc = replacement_desc;
131     }
132
133     out_args[0]->u.ival = status;
134     out_args[1]->u.hval = desc;
135     rpc->result = NACL_SRPC_RESULT_OK;
136   }
137   (*done_cls->Run)(done_cls);
138   NaClDescUnref(desc);
139   NaClManifestReleaseChannel_release_mu(proxy_conn);
140 }
141
142 static void NaClManifestNameServiceDeleteRpc(
143     struct NaClSrpcRpc      *rpc,
144     struct NaClSrpcArg      **in_args,
145     struct NaClSrpcArg      **out_args,
146     struct NaClSrpcClosure  *done_cls) {
147
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);
153 }
154
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, },
160 };
161
162
163 int NaClManifestProxyCtor(struct NaClManifestProxy        *self,
164                           NaClThreadIfFactoryFunction     thread_factory_fn,
165                           void                            *thread_factory_data,
166                           struct NaClSecureService        *server) {
167   NaClLog(4,
168           ("Entered NaClManifestProxyCtor: self 0x%"NACL_PRIxPTR
169            ", client 0x%"NACL_PRIxPTR"\n"),
170           (uintptr_t) self,
171           (uintptr_t) server);
172   if (!NaClSimpleServiceCtor(&self->base,
173                              kNaClManifestProxyHandlers,
174                              thread_factory_fn,
175                              thread_factory_data)) {
176     return 0;
177   }
178   self->server = (struct NaClSecureService *)
179       NaClRefCountRef((struct NaClRefCount *) server);
180   NACL_VTBL(NaClRefCount, self) =
181       (struct NaClRefCountVtbl *) &kNaClManifestProxyVtbl;
182   return 1;
183 }
184
185 static void NaClManifestProxyDtor(struct NaClRefCount *vself) {
186   struct NaClManifestProxy *self =
187       (struct NaClManifestProxy *) vself;
188
189   NaClRefCountUnref((struct NaClRefCount *) self->server);
190
191   NACL_VTBL(NaClRefCount, self) =
192       (struct NaClRefCountVtbl *) &kNaClSimpleServiceVtbl;
193   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
194 }
195
196 int NaClManifestProxyConnectionCtor(struct NaClManifestProxyConnection  *self,
197                                     struct NaClManifestProxy            *server,
198                                     struct NaClDesc                     *conn) {
199   NaClLog(4,
200           "Entered NaClManifestProxyConnectionCtor, self 0x%"NACL_PRIxPTR"\n",
201           (uintptr_t) self);
202   if (!NaClSimpleServiceConnectionCtor(
203           &self->base,
204           (struct NaClSimpleService *) server,
205           conn,
206           (void *) self)) {
207     NaClLog(4,
208             ("NaClManifestProxyConnectionCtor: base class ctor"
209              " NaClSimpleServiceConnectionCtor failed\n"));
210     return 0;
211   }
212   NaClXMutexCtor(&self->mu);
213   NaClXCondVarCtor(&self->cv);
214   self->channel_initialized = 0;
215   NACL_VTBL(NaClRefCount, self) =
216       (struct NaClRefCountVtbl *) &kNaClManifestProxyConnectionVtbl;
217   return 1;
218 }
219
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) {
226     NaClLog(LOG_FATAL,
227             "NaClManifestProxyConnectionRevHandleConnect: double connect?\n");
228   }
229   /*
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.
233    */
234   NaClLog(4,
235           "NaClManifestProxyConnectionRevHandleConnect: Creating SrpcClient\n");
236   if (NaClSrpcClientCtor(&self->client_channel, rev)) {
237     NaClLog(4,
238             ("NaClManifestProxyConnectionRevHandleConnect: SrpcClientCtor"
239              " succeded, announcing.\n"));
240     self->channel_initialized = 1;
241     NaClXCondVarBroadcast(&self->cv);
242     /* ownership of rev taken */
243   } else {
244     NaClLog(4,
245             ("NaClManifestProxyConnectionRevHandleConnect: NaClSrpcClientCtor"
246              " failed\n"));
247   }
248   NaClXMutexUnlock(&self->mu);
249   NaClLog(4, "Leaving NaClManifestProxyConnectionRevHandleConnect\n");
250 }
251
252 static void NaClManifestProxyConnectionDtor(struct NaClRefCount *vself) {
253   struct NaClManifestProxyConnection *self =
254       (struct NaClManifestProxyConnection *) vself;
255   NaClLog(4,
256           "Entered NaClManifestProxyConnectionDtor: self 0x%"NACL_PRIxPTR"\n",
257           (uintptr_t) self);
258   NaClXMutexLock(&self->mu);
259   while (!self->channel_initialized) {
260     NaClLog(4,
261             "NaClManifestProxyConnectionDtor:"
262             " waiting for connection initialization\n");
263     NaClXCondVarWait(&self->cv, &self->mu);
264   }
265   NaClXMutexUnlock(&self->mu);
266
267   NaClLog(4, "NaClManifestProxyConnectionDtor: dtoring\n");
268
269   NaClCondVarDtor(&self->cv);
270   NaClMutexDtor(&self->mu);
271
272   NaClSrpcDtor(&self->client_channel);
273   NACL_VTBL(NaClSimpleServiceConnection, self) =
274       &kNaClSimpleServiceConnectionVtbl;
275   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
276 }
277
278 /*
279  * NaClManifestProxyConnection is a NaClSimpleServiceConnection
280  */
281 struct NaClSimpleServiceConnectionVtbl
282   const kNaClManifestProxyConnectionVtbl = {
283   {
284     NaClManifestProxyConnectionDtor,
285   },
286   NaClSimpleServiceConnectionServerLoop,
287 };
288
289 static void NaClManifestReverseClientCallback(
290     void                        *state,
291     struct NaClThreadInterface  *tif,
292     struct NaClDesc             *new_conn) {
293   struct NaClManifestProxyConnection *mconn =
294       (struct NaClManifestProxyConnection *) state;
295
296   UNREFERENCED_PARAMETER(tif);
297   NaClLog(4, "Entered NaClManifestReverseClientCallback\n");
298   NaClManifestProxyConnectionRevHandleConnect(mconn, new_conn);
299 }
300
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;
309   int                                 bool_status;
310
311   NaClLog(4,
312           ("Entered NaClManifestProxyConnectionFactory, self 0x%"NACL_PRIxPTR
313            "\n"),
314           (uintptr_t) self);
315   mconn = (struct NaClManifestProxyConnection *) malloc(sizeof *mconn);
316   if (NULL == mconn) {
317     NaClLog(4, "NaClManifestProxyConnectionFactory: no memory\n");
318     return -NACL_ABI_ENOMEM;
319   }
320   NaClLog(4, "NaClManifestProxyConnectionFactory: creating connection obj\n");
321   if (!NaClManifestProxyConnectionCtor(mconn, self, conn)) {
322     free(mconn);
323     return -NACL_ABI_EIO;
324   }
325
326   /*
327    * Construct via NaClSecureReverseClientCtor with a callback to
328    * process the new reverse connection -- which should be stored in
329    * the mconn object.
330    *
331    * Make reverse RPC to obtain a new reverse RPC connection.
332    */
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) {
339     NaClLog(LOG_FATAL,
340             "NaClManifestProxyConnectionFactory invoked w/o reverse channel\n");
341   }
342   NaClLog(4, "NaClManifestProxyConnectionFactory: inserting handler\n");
343   if (!(*NACL_VTBL(NaClSecureReverseClient, self->server->reverse_client)->
344         InsertHandler)(self->server->reverse_client,
345                        NaClManifestReverseClientCallback,
346                        (void *) mconn)) {
347     NaClLog(LOG_FATAL,
348             ("NaClManifestProxyConnectionFactory:"
349              " NaClSecureReverseClientInsertHandler failed\n"));
350   }
351   /*
352    * NaClSrpcInvokeBySignature(""); tell plugin to connect and create
353    * a reverse channel
354    */
355   NaClLog(4,
356           ("NaClManifestProxyConnectionFactory: making RPC"
357            " to set up connection\n"));
358   rpc_result = NaClSrpcInvokeBySignature(&self->server->reverse_channel,
359                                          NACL_REVERSE_CONTROL_ADD_CHANNEL,
360                                          &bool_status);
361   if (NACL_SRPC_RESULT_OK != rpc_result) {
362     NaClLog(LOG_FATAL,
363             "NaClManifestProxyConnectionFactory: add channel RPC failed: %d",
364             rpc_result);
365   }
366   NaClLog(4,
367           "NaClManifestProxyConnectionFactory: Start status %d\n", bool_status);
368
369   NaClXMutexUnlock(&self->server->mu);
370
371   *out = (struct NaClSimpleServiceConnection *) mconn;
372   return 0;
373 }
374
375 struct NaClSimpleServiceVtbl const kNaClManifestProxyVtbl = {
376   {
377     NaClManifestProxyDtor,
378   },
379   NaClManifestProxyConnectionFactory,
380   /* see name_service.c vtbl for connection factory and ownership */
381   /*
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.
386    */
387   NaClSimpleServiceAcceptConnection,
388   NaClSimpleServiceAcceptAndSpawnHandler,
389   NaClSimpleServiceRpcHandler,
390 };