Upstream version 5.34.104.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 #include <string.h>
8
9 #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
10
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"
26
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);
35   }
36   NaClLog(4, "Leaving NaClManifestWaitForChannel_yield_mu\n");
37 }
38
39 static void NaClManifestReleaseChannel_release_mu(
40     struct NaClManifestProxyConnection *self) {
41   NaClLog(4, "NaClManifestReleaseChannel_release_mu\n");
42   NaClXMutexUnlock(&self->mu);
43 }
44
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;
55
56   UNREFERENCED_PARAMETER(in_args);
57   NaClLog(4,
58           "NaClManifestNameServiceListRpc, proxy_conn 0x%"NACL_PRIxPTR"\n",
59           (uintptr_t) proxy_conn);
60
61   NaClManifestWaitForChannel_yield_mu(proxy_conn);
62
63   NaClLog(4,
64           ("NaClManifestNameServiceListRpc: nbytes %"NACL_PRIu32", dest"
65            " 0x%"NACL_PRIxPTR"\n"),
66           nbytes, (uintptr_t) dest);
67   if (NACL_SRPC_RESULT_OK !=
68       (srpc_error =
69        NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
70                                  NACL_MANIFEST_LIST,
71                                  &nbytes, dest))) {
72     NaClLog(LOG_ERROR,
73             ("Manifest list via channel 0x%"NACL_PRIxPTR" with RPC "
74              NACL_MANIFEST_LIST" failed: %d\n"),
75             (uintptr_t) &proxy_conn->client_channel,
76             srpc_error);
77     rpc->result = srpc_error;
78   } else {
79     NaClLog(3,
80             "NaClManifestNameServiceListRpc, proxy returned %"NACL_PRId32
81             " bytes\n",
82             nbytes);
83     out_args[0]->u.count = nbytes;
84     rpc->result = NACL_SRPC_RESULT_OK;
85   }
86   (*done_cls->Run)(done_cls);
87   NaClManifestReleaseChannel_release_mu(proxy_conn);
88 }
89
90 static void NaClManifestNameServiceInsertRpc(
91     struct NaClSrpcRpc      *rpc,
92     struct NaClSrpcArg      **in_args,
93     struct NaClSrpcArg      **out_args,
94     struct NaClSrpcClosure  *done_cls) {
95
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);
102 }
103
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;
113   char                                cookie[20];
114   uint32_t                            cookie_size = sizeof cookie;
115   int                                 status;
116   struct NaClDesc                     *desc;
117   struct NaClFileToken                file_token;
118   NaClSrpcError                       srpc_error;
119
120   NaClLog(4, "NaClManifestNameServiceLookupRpc\n");
121
122   NaClManifestWaitForChannel_yield_mu(proxy_conn);
123
124   NaClLog(4,
125           "NaClManifestNameServiceLookupRpc: name %s, flags %d\n",
126           name, flags);
127   NaClLog(4,
128           "NaClManifestNameServiceLookupRpc: invoking %s\n",
129           NACL_MANIFEST_LOOKUP);
130
131   if (NACL_SRPC_RESULT_OK !=
132       (srpc_error =
133        NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
134                                  NACL_MANIFEST_LOOKUP,
135                                  name,
136                                  flags,
137                                  &status,
138                                  &desc,
139                                  &file_token.lo,
140                                  &file_token.hi,
141                                  &cookie_size,
142                                  cookie))) {
143     NaClLog(LOG_ERROR,
144             ("Manifest lookup via channel 0x%"NACL_PRIxPTR" with RPC "
145              NACL_MANIFEST_LOOKUP" failed: %d\n"),
146             (uintptr_t) &proxy_conn->client_channel,
147             srpc_error);
148     rpc->result = srpc_error;
149   } else {
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;
155
156     /*
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
164      * problem.
165      */
166     NaClLog(4,
167             "NaClManifestNameServiceLookupRpc: got cookie %.*s\n",
168             cookie_size, cookie);
169     replacement_desc = NaClExchangeFileTokenForMappableDesc(&file_token,
170                                                             validation_cache);
171     if (NULL != replacement_desc) {
172       NaClDescUnref(desc);
173       desc = replacement_desc;
174     }
175
176     out_args[0]->u.ival = status;
177     out_args[1]->u.hval = desc;
178     rpc->result = NACL_SRPC_RESULT_OK;
179   }
180   (*done_cls->Run)(done_cls);
181   NaClDescUnref(desc);
182   NaClManifestReleaseChannel_release_mu(proxy_conn);
183 }
184
185 static void NaClManifestNameServiceDeleteRpc(
186     struct NaClSrpcRpc      *rpc,
187     struct NaClSrpcArg      **in_args,
188     struct NaClSrpcArg      **out_args,
189     struct NaClSrpcClosure  *done_cls) {
190
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);
196 }
197
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, },
204 };
205
206
207 int NaClManifestProxyCtor(struct NaClManifestProxy        *self,
208                           NaClThreadIfFactoryFunction     thread_factory_fn,
209                           void                            *thread_factory_data,
210                           struct NaClSecureService        *server) {
211   NaClLog(4,
212           ("Entered NaClManifestProxyCtor: self 0x%"NACL_PRIxPTR
213            ", client 0x%"NACL_PRIxPTR"\n"),
214           (uintptr_t) self,
215           (uintptr_t) server);
216   if (!NaClSimpleServiceCtor(&self->base,
217                              kNaClManifestProxyHandlers,
218                              thread_factory_fn,
219                              thread_factory_data)) {
220     return 0;
221   }
222   self->server = (struct NaClSecureService *)
223       NaClRefCountRef((struct NaClRefCount *) server);
224   NACL_VTBL(NaClRefCount, self) =
225       (struct NaClRefCountVtbl *) &kNaClManifestProxyVtbl;
226   return 1;
227 }
228
229 static void NaClManifestProxyDtor(struct NaClRefCount *vself) {
230   struct NaClManifestProxy *self =
231       (struct NaClManifestProxy *) vself;
232
233   NaClRefCountUnref((struct NaClRefCount *) self->server);
234
235   NACL_VTBL(NaClRefCount, self) =
236       (struct NaClRefCountVtbl *) &kNaClSimpleServiceVtbl;
237   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
238 }
239
240 int NaClManifestProxyConnectionCtor(struct NaClManifestProxyConnection  *self,
241                                     struct NaClManifestProxy            *server,
242                                     struct NaClDesc                     *conn) {
243   NaClLog(4,
244           "Entered NaClManifestProxyConnectionCtor, self 0x%"NACL_PRIxPTR"\n",
245           (uintptr_t) self);
246   if (!NaClSimpleServiceConnectionCtor(
247           &self->base,
248           (struct NaClSimpleService *) server,
249           conn,
250           (void *) self)) {
251     NaClLog(4,
252             ("NaClManifestProxyConnectionCtor: base class ctor"
253              " NaClSimpleServiceConnectionCtor failed\n"));
254     return 0;
255   }
256   NaClXMutexCtor(&self->mu);
257   NaClXCondVarCtor(&self->cv);
258   self->channel_initialized = 0;
259   NACL_VTBL(NaClRefCount, self) =
260       (struct NaClRefCountVtbl *) &kNaClManifestProxyConnectionVtbl;
261   return 1;
262 }
263
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) {
270     NaClLog(LOG_FATAL,
271             "NaClManifestProxyConnectionRevHandleConnect: double connect?\n");
272   }
273   /*
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.
277    */
278   NaClLog(4,
279           "NaClManifestProxyConnectionRevHandleConnect: Creating SrpcClient\n");
280   if (NaClSrpcClientCtor(&self->client_channel, rev)) {
281     NaClLog(4,
282             ("NaClManifestProxyConnectionRevHandleConnect: SrpcClientCtor"
283              " succeded, announcing.\n"));
284     self->channel_initialized = 1;
285     NaClXCondVarBroadcast(&self->cv);
286     /* ownership of rev taken */
287   } else {
288     NaClLog(4,
289             ("NaClManifestProxyConnectionRevHandleConnect: NaClSrpcClientCtor"
290              " failed\n"));
291   }
292   NaClXMutexUnlock(&self->mu);
293   NaClLog(4, "Leaving NaClManifestProxyConnectionRevHandleConnect\n");
294 }
295
296 static void NaClManifestProxyConnectionDtor(struct NaClRefCount *vself) {
297   struct NaClManifestProxyConnection *self =
298       (struct NaClManifestProxyConnection *) vself;
299   NaClLog(4,
300           "Entered NaClManifestProxyConnectionDtor: self 0x%"NACL_PRIxPTR"\n",
301           (uintptr_t) self);
302   NaClXMutexLock(&self->mu);
303   while (!self->channel_initialized) {
304     NaClLog(4,
305             "NaClManifestProxyConnectionDtor:"
306             " waiting for connection initialization\n");
307     NaClXCondVarWait(&self->cv, &self->mu);
308   }
309   NaClXMutexUnlock(&self->mu);
310
311   NaClLog(4, "NaClManifestProxyConnectionDtor: dtoring\n");
312
313   NaClCondVarDtor(&self->cv);
314   NaClMutexDtor(&self->mu);
315
316   NaClSrpcDtor(&self->client_channel);
317   NACL_VTBL(NaClSimpleServiceConnection, self) =
318       &kNaClSimpleServiceConnectionVtbl;
319   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
320 }
321
322 /*
323  * NaClManifestProxyConnection is a NaClSimpleServiceConnection
324  */
325 struct NaClSimpleServiceConnectionVtbl
326   const kNaClManifestProxyConnectionVtbl = {
327   {
328     NaClManifestProxyConnectionDtor,
329   },
330   NaClSimpleServiceConnectionServerLoop,
331 };
332
333 static void NaClManifestReverseClientCallback(
334     void                        *state,
335     struct NaClThreadInterface  *tif,
336     struct NaClDesc             *new_conn) {
337   struct NaClManifestProxyConnection *mconn =
338       (struct NaClManifestProxyConnection *) state;
339
340   UNREFERENCED_PARAMETER(tif);
341   NaClLog(4, "Entered NaClManifestReverseClientCallback\n");
342   NaClManifestProxyConnectionRevHandleConnect(mconn, new_conn);
343 }
344
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;
353   int                                 bool_status;
354
355   NaClLog(4,
356           ("Entered NaClManifestProxyConnectionFactory, self 0x%"NACL_PRIxPTR
357            "\n"),
358           (uintptr_t) self);
359   mconn = (struct NaClManifestProxyConnection *) malloc(sizeof *mconn);
360   if (NULL == mconn) {
361     NaClLog(4, "NaClManifestProxyConnectionFactory: no memory\n");
362     return -NACL_ABI_ENOMEM;
363   }
364   NaClLog(4, "NaClManifestProxyConnectionFactory: creating connection obj\n");
365   if (!NaClManifestProxyConnectionCtor(mconn, self, conn)) {
366     free(mconn);
367     return -NACL_ABI_EIO;
368   }
369
370   /*
371    * Construct via NaClSecureReverseClientCtor with a callback to
372    * process the new reverse connection -- which should be stored in
373    * the mconn object.
374    *
375    * Make reverse RPC to obtain a new reverse RPC connection.
376    */
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) {
383     NaClLog(LOG_FATAL,
384             "NaClManifestProxyConnectionFactory invoked w/o reverse channel\n");
385   }
386   NaClLog(4, "NaClManifestProxyConnectionFactory: inserting handler\n");
387   if (!(*NACL_VTBL(NaClSecureReverseClient, self->server->reverse_client)->
388         InsertHandler)(self->server->reverse_client,
389                        NaClManifestReverseClientCallback,
390                        (void *) mconn)) {
391     NaClLog(LOG_FATAL,
392             ("NaClManifestProxyConnectionFactory:"
393              " NaClSecureReverseClientInsertHandler failed\n"));
394   }
395   /*
396    * NaClSrpcInvokeBySignature(""); tell plugin to connect and create
397    * a reverse channel
398    */
399   NaClLog(4,
400           ("NaClManifestProxyConnectionFactory: making RPC"
401            " to set up connection\n"));
402   rpc_result = NaClSrpcInvokeBySignature(&self->server->reverse_channel,
403                                          NACL_REVERSE_CONTROL_ADD_CHANNEL,
404                                          &bool_status);
405   if (NACL_SRPC_RESULT_OK != rpc_result) {
406     NaClLog(LOG_FATAL,
407             "NaClManifestProxyConnectionFactory: add channel RPC failed: %d",
408             rpc_result);
409   }
410   NaClLog(4,
411           "NaClManifestProxyConnectionFactory: Start status %d\n", bool_status);
412
413   NaClXMutexUnlock(&self->server->mu);
414
415   *out = (struct NaClSimpleServiceConnection *) mconn;
416   return 0;
417 }
418
419 struct NaClSimpleServiceVtbl const kNaClManifestProxyVtbl = {
420   {
421     NaClManifestProxyDtor,
422   },
423   NaClManifestProxyConnectionFactory,
424   /* see name_service.c vtbl for connection factory and ownership */
425   /*
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.
430    */
431   NaClSimpleServiceAcceptConnection,
432   NaClSimpleServiceAcceptAndSpawnHandler,
433   NaClSimpleServiceRpcHandler,
434 };