OLD | NEW |
| (Empty) |
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/public/nacl_file_info.h" | |
15 #include "native_client/src/shared/platform/nacl_log.h" | |
16 #include "native_client/src/shared/platform/nacl_sync.h" | |
17 #include "native_client/src/shared/platform/nacl_sync_checked.h" | |
18 #include "native_client/src/shared/srpc/nacl_srpc.h" | |
19 #include "native_client/src/trusted/desc/nacl_desc_io.h" | |
20 #include "native_client/src/trusted/desc_cacheability/desc_cacheability.h" | |
21 #include "native_client/src/trusted/reverse_service/manifest_rpc.h" | |
22 #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h" | |
23 #include "native_client/src/trusted/service_runtime/include/sys/errno.h" | |
24 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h" | |
25 #include "native_client/src/trusted/service_runtime/nacl_secure_service.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 }; | |
OLD | NEW |