1 : /*
2 : * Copyright (c) 2011 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/shared/platform/nacl_log.h"
12 : #include "native_client/src/shared/platform/nacl_sync.h"
13 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
14 : #include "native_client/src/shared/srpc/nacl_srpc.h"
15 : #include "native_client/src/trusted/reverse_service/manifest_rpc.h"
16 : #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h"
17 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
18 : #include "native_client/src/trusted/service_runtime/include/sys/nacl_name_service.h"
19 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
20 :
21 : static void NaClManifestWaitForChannel_yield_mu(
22 0 : struct NaClManifestProxyConnection *self) {
23 0 : NaClLog(4, "Entered NaClManifestWaitForChannel_yield_mu\n");
24 0 : NaClXMutexLock(&self->mu);
25 0 : NaClLog(4, "NaClManifestWaitForChannel_yield_mu: checking channel\n");
26 0 : while (!self->channel_initialized) {
27 0 : NaClLog(4, "NaClManifestWaitForChannel_yield_mu: waiting\n");
28 0 : NaClXCondVarWait(&self->cv, &self->mu);
29 : }
30 0 : NaClLog(4, "Leaving NaClManifestWaitForChannel_yield_mu\n");
31 0 : }
32 :
33 : static void NaClManifestReleaseChannel_release_mu(
34 0 : struct NaClManifestProxyConnection *self) {
35 0 : NaClLog(4, "NaClManifestReleaseChannel_release_mu\n");
36 0 : NaClXMutexUnlock(&self->mu);
37 0 : }
38 :
39 : static void NaClManifestNameServiceListRpc(
40 : struct NaClSrpcRpc *rpc,
41 : struct NaClSrpcArg **in_args,
42 : struct NaClSrpcArg **out_args,
43 0 : struct NaClSrpcClosure *done_cls) {
44 : struct NaClManifestProxyConnection *proxy_conn =
45 0 : (struct NaClManifestProxyConnection *) rpc->channel->server_instance_data;
46 0 : uint32_t nbytes = out_args[0]->u.count;
47 0 : char *dest = out_args[0]->arrays.carr;
48 : NaClSrpcError srpc_error;
49 :
50 : UNREFERENCED_PARAMETER(in_args);
51 0 : NaClLog(4,
52 : "NaClManifestNameServiceListRpc, proxy_conn 0x%"NACL_PRIxPTR"\n",
53 : (uintptr_t) proxy_conn);
54 :
55 0 : NaClManifestWaitForChannel_yield_mu(proxy_conn);
56 :
57 0 : NaClLog(4,
58 : ("NaClManifestNameServiceListRpc: nbytes %"NACL_PRIu32", dest"
59 : " 0x%"NACL_PRIxPTR"\n"),
60 : nbytes, (uintptr_t) dest);
61 0 : if (NACL_SRPC_RESULT_OK !=
62 : (srpc_error =
63 : NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
64 : NACL_MANIFEST_LIST,
65 : &nbytes, dest))) {
66 0 : NaClLog(LOG_ERROR,
67 : ("Manifest list via channel 0x%"NACL_PRIxPTR" with RPC "
68 : NACL_MANIFEST_LIST" failed: %d\n"),
69 : (uintptr_t) &proxy_conn->client_channel,
70 : srpc_error);
71 0 : rpc->result = srpc_error;
72 : } else {
73 0 : NaClLog(3,
74 : "NaClManifestNameServiceListRpc, proxy returned %"NACL_PRId32
75 : " bytes\n",
76 : nbytes);
77 0 : out_args[0]->u.count = nbytes;
78 0 : rpc->result = NACL_SRPC_RESULT_OK;
79 : }
80 0 : (*done_cls->Run)(done_cls);
81 0 : NaClManifestReleaseChannel_release_mu(proxy_conn);
82 0 : }
83 :
84 : static void NaClManifestNameServiceInsertRpc(
85 : struct NaClSrpcRpc *rpc,
86 : struct NaClSrpcArg **in_args,
87 : struct NaClSrpcArg **out_args,
88 0 : struct NaClSrpcClosure *done_cls) {
89 :
90 : UNREFERENCED_PARAMETER(in_args);
91 0 : NaClLog(4, "NaClManifestNameServiceInsertRpc\n");
92 0 : out_args[0]->u.ival = NACL_NAME_SERVICE_PERMISSION_DENIED;
93 : /* cannot add names to the manifest! */
94 0 : rpc->result = NACL_SRPC_RESULT_OK;
95 0 : (*done_cls->Run)(done_cls);
96 0 : }
97 :
98 : static void NaClManifestNameServiceLookupRpc(
99 : struct NaClSrpcRpc *rpc,
100 : struct NaClSrpcArg **in_args,
101 : struct NaClSrpcArg **out_args,
102 0 : struct NaClSrpcClosure *done_cls) {
103 : struct NaClManifestProxyConnection *proxy_conn =
104 0 : (struct NaClManifestProxyConnection *) rpc->channel->server_instance_data;
105 0 : char *name = in_args[0]->arrays.str;
106 0 : int flags = in_args[1]->u.ival;
107 : char cookie[20];
108 0 : uint32_t cookie_size = sizeof cookie;
109 : int status;
110 : struct NaClDesc *desc;
111 : NaClSrpcError srpc_error;
112 :
113 0 : NaClLog(4, "NaClManifestNameServiceLookupRpc\n");
114 :
115 0 : NaClManifestWaitForChannel_yield_mu(proxy_conn);
116 :
117 0 : NaClLog(4,
118 : "NaClManifestNameServiceLookupRpc: name %s, flags %d\n",
119 : name, flags);
120 0 : NaClLog(4,
121 : "NaClManifestNameServiceLookupRpc: invoking %s\n",
122 : NACL_MANIFEST_LOOKUP);
123 :
124 0 : if (NACL_SRPC_RESULT_OK !=
125 : (srpc_error =
126 : NaClSrpcInvokeBySignature(&proxy_conn->client_channel,
127 : NACL_MANIFEST_LOOKUP,
128 : name,
129 : flags,
130 : &status,
131 : &desc,
132 : &cookie_size,
133 : cookie))) {
134 0 : NaClLog(LOG_ERROR,
135 : ("Manifest lookup via channel 0x%"NACL_PRIxPTR" with RPC "
136 : NACL_MANIFEST_LOOKUP" failed: %d\n"),
137 : (uintptr_t) &proxy_conn->client_channel,
138 : srpc_error);
139 0 : rpc->result = srpc_error;
140 : } else {
141 0 : NaClLog(4,
142 : "NaClManifestNameServiceLookupRpc: got cookie %.*s\n",
143 : cookie_size, cookie);
144 0 : out_args[0]->u.ival = status;
145 0 : out_args[1]->u.hval = desc;
146 0 : rpc->result = NACL_SRPC_RESULT_OK;
147 : }
148 0 : (*done_cls->Run)(done_cls);
149 0 : NaClManifestReleaseChannel_release_mu(proxy_conn);
150 0 : }
151 :
152 : static void NaClManifestNameServiceDeleteRpc(
153 : struct NaClSrpcRpc *rpc,
154 : struct NaClSrpcArg **in_args,
155 : struct NaClSrpcArg **out_args,
156 0 : struct NaClSrpcClosure *done_cls) {
157 :
158 : UNREFERENCED_PARAMETER(in_args);
159 0 : NaClLog(4, "NaClManifestNameServiceDeleteRpc\n");
160 0 : out_args[0]->u.ival = NACL_NAME_SERVICE_PERMISSION_DENIED;
161 0 : rpc->result = NACL_SRPC_RESULT_OK;
162 0 : (*done_cls->Run)(done_cls);
163 0 : }
164 :
165 : struct NaClSrpcHandlerDesc const kNaClManifestProxyHandlers[] = {
166 : { NACL_NAME_SERVICE_LIST, NaClManifestNameServiceListRpc, },
167 : { NACL_NAME_SERVICE_INSERT, NaClManifestNameServiceInsertRpc, },
168 : { NACL_NAME_SERVICE_LOOKUP, NaClManifestNameServiceLookupRpc, },
169 : { NACL_NAME_SERVICE_DELETE, NaClManifestNameServiceDeleteRpc, },
170 : { (char const *) NULL, (NaClSrpcMethod) NULL, },
171 : };
172 :
173 :
174 : int NaClManifestProxyCtor(struct NaClManifestProxy *self,
175 : NaClThreadIfFactoryFunction thread_factory_fn,
176 : void *thread_factory_data,
177 0 : struct NaClApp *nap) {
178 0 : NaClLog(4,
179 : ("Entered NaClManifestProxyCtor: self 0x%"NACL_PRIxPTR
180 : ", nap 0x%"NACL_PRIxPTR"\n"),
181 : (uintptr_t) self,
182 : (uintptr_t) nap);
183 0 : if (!NaClSimpleServiceCtor(&self->base,
184 : kNaClManifestProxyHandlers,
185 : thread_factory_fn,
186 : thread_factory_data)) {
187 0 : return 0;
188 : }
189 0 : self->nap = nap;
190 0 : NACL_VTBL(NaClRefCount, self) =
191 : (struct NaClRefCountVtbl *) &kNaClManifestProxyVtbl;
192 0 : return 1;
193 : }
194 :
195 0 : static void NaClManifestProxyDtor(struct NaClRefCount *vself) {
196 : struct NaClManifestProxy *self =
197 0 : (struct NaClManifestProxy *) vself;
198 :
199 0 : NACL_VTBL(NaClRefCount, self) =
200 : (struct NaClRefCountVtbl *) &kNaClSimpleServiceVtbl;
201 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
202 0 : }
203 :
204 : int NaClManifestProxyConnectionCtor(struct NaClManifestProxyConnection *self,
205 : struct NaClManifestProxy *server,
206 0 : struct NaClDesc *conn) {
207 0 : NaClLog(4,
208 : "Entered NaClManifestProxyConnectionCtor, self 0x%"NACL_PRIxPTR"\n",
209 : (uintptr_t) self);
210 0 : if (!NaClSimpleServiceConnectionCtor(
211 : &self->base,
212 : (struct NaClSimpleService *) server,
213 : conn,
214 : (void *) self)) {
215 0 : NaClLog(4,
216 : ("NaClManifestProxyConnectionCtor: base class ctor"
217 : " NaClSimpleServiceConnectionCtor failed\n"));
218 0 : return 0;
219 : }
220 0 : NaClXMutexCtor(&self->mu);
221 0 : NaClXCondVarCtor(&self->cv);
222 0 : self->channel_initialized = 0;
223 0 : NACL_VTBL(NaClRefCount, self) =
224 : (struct NaClRefCountVtbl *) &kNaClManifestProxyConnectionVtbl;
225 0 : return 1;
226 : }
227 :
228 : void NaClManifestProxyConnectionRevHandleConnect(
229 : struct NaClManifestProxyConnection *self,
230 0 : struct NaClDesc *rev) {
231 0 : NaClLog(4, "Entered NaClManifestProxyConnectionRevHandleConnect\n");
232 0 : NaClXMutexLock(&self->mu);
233 0 : if (self->channel_initialized) {
234 0 : NaClLog(LOG_FATAL,
235 : "NaClManifestProxyConnectionRevHandleConnect: double connect?\n");
236 : }
237 : /*
238 : * If NaClSrpcClientCtor proves to take too long, we should spin off
239 : * another thread to do the initialization so that the reverse
240 : * client can accept additional reverse channels.
241 : */
242 0 : NaClLog(4,
243 : "NaClManifestProxyConnectionRevHandleConnect: Creating SrpcClient\n");
244 0 : if (NaClSrpcClientCtor(&self->client_channel, rev)) {
245 0 : NaClLog(4,
246 : ("NaClManifestProxyConnectionRevHandleConnect: SrpcClientCtor"
247 : " succeded, announcing.\n"));
248 0 : self->channel_initialized = 1;
249 0 : NaClXCondVarBroadcast(&self->cv);
250 : /* ownership of rev taken */
251 : } else {
252 0 : NaClLog(4,
253 : ("NaClManifestProxyConnectionRevHandleConnect: NaClSrpcClientCtor"
254 : " failed\n"));
255 : }
256 0 : NaClXMutexUnlock(&self->mu);
257 0 : NaClLog(4, "Leaving NaClManifestProxyConnectionRevHandleConnect\n");
258 0 : }
259 :
260 0 : static void NaClManifestProxyConnectionDtor(struct NaClRefCount *vself) {
261 : struct NaClManifestProxyConnection *self =
262 0 : (struct NaClManifestProxyConnection *) vself;
263 0 : NaClLog(4,
264 : "Entered NaClManifestProxyConnectionDtor: self 0x%"NACL_PRIxPTR"\n",
265 : (uintptr_t) self);
266 0 : NaClXMutexLock(&self->mu);
267 0 : while (!self->channel_initialized) {
268 0 : NaClLog(4,
269 : "NaClManifestProxyConnectionDtor:"
270 : " waiting for connection initialization\n");
271 0 : NaClXCondVarWait(&self->cv, &self->mu);
272 : }
273 0 : NaClXMutexUnlock(&self->mu);
274 :
275 0 : NaClLog(4, "NaClManifestProxyConnectionDtor: dtoring\n");
276 :
277 0 : NaClCondVarDtor(&self->cv);
278 0 : NaClMutexDtor(&self->mu);
279 :
280 0 : NaClSrpcDtor(&self->client_channel);
281 0 : NACL_VTBL(NaClSimpleServiceConnection, self) =
282 : &kNaClSimpleServiceConnectionVtbl;
283 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
284 0 : }
285 :
286 : /*
287 : * NaClManifestProxyConnection is a NaClSimpleServiceConnection
288 : */
289 : struct NaClSimpleServiceConnectionVtbl
290 : const kNaClManifestProxyConnectionVtbl = {
291 : {
292 : NaClManifestProxyConnectionDtor,
293 : },
294 : NaClSimpleServiceConnectionServerLoop,
295 : };
296 :
297 : static void NaClManifestReverseClientCallback(
298 : void *state,
299 : struct NaClThreadInterface *tif,
300 0 : struct NaClDesc *new_conn) {
301 : struct NaClManifestProxyConnection *mconn =
302 0 : (struct NaClManifestProxyConnection *) state;
303 :
304 : UNREFERENCED_PARAMETER(tif);
305 0 : NaClLog(4, "Entered NaClManifestReverseClientCallback\n");
306 0 : NaClManifestProxyConnectionRevHandleConnect(mconn, new_conn);
307 0 : }
308 :
309 : int NaClManifestProxyConnectionFactory(
310 : struct NaClSimpleService *vself,
311 : struct NaClDesc *conn,
312 0 : struct NaClSimpleServiceConnection **out) {
313 : struct NaClManifestProxy *self =
314 0 : (struct NaClManifestProxy *) vself;
315 0 : struct NaClApp *nap = self->nap;
316 : struct NaClManifestProxyConnection *mconn;
317 : NaClSrpcError rpc_result;
318 : int bool_status;
319 :
320 0 : NaClLog(4,
321 : ("Entered NaClManifestProxyConnectionFactory, self 0x%"NACL_PRIxPTR
322 : "\n"),
323 : (uintptr_t) self);
324 0 : mconn = (struct NaClManifestProxyConnection *) malloc(sizeof *mconn);
325 0 : if (NULL == mconn) {
326 0 : NaClLog(4, "NaClManifestProxyConnectionFactory: no memory\n");
327 0 : return -NACL_ABI_ENOMEM;
328 : }
329 0 : NaClLog(4, "NaClManifestProxyConnectionFactory: creating connection obj\n");
330 0 : if (!NaClManifestProxyConnectionCtor(mconn, self, conn)) {
331 0 : free(mconn);
332 0 : return -NACL_ABI_EIO;
333 : }
334 :
335 : /*
336 : * Construct via NaClSecureReverseClientCtor with a callback to
337 : * process the new reverse connection -- which should be stored in
338 : * the mconn object.
339 : *
340 : * Make reverse RPC to obtain a new reverse RPC connection.
341 : */
342 0 : NaClLog(4, "NaClManifestProxyConnectionFactory: locking reverse channel\n");
343 0 : NaClLog(4, "NaClManifestProxyConnectionFactory: nap 0x%"NACL_PRIxPTR"\n",
344 : (uintptr_t) nap);
345 0 : NaClXMutexLock(&nap->mu);
346 0 : if (NACL_REVERSE_CHANNEL_INITIALIZED !=
347 : nap->reverse_channel_initialization_state) {
348 0 : NaClLog(LOG_FATAL,
349 : "NaClManifestProxyConnectionFactory invoked w/o reverse channel\n");
350 : }
351 0 : NaClLog(4, "NaClManifestProxyConnectionFactory: inserting handler\n");
352 0 : if (!NaClSecureReverseClientInsertHandler(nap->reverse_client,
353 : NaClManifestReverseClientCallback,
354 : (void *) mconn)) {
355 0 : NaClLog(LOG_FATAL,
356 : ("NaClManifestProxyConnectionFactory:"
357 : " NaClSecureReverseClientInsertHandler failed\n"));
358 : }
359 : /*
360 : * NaClSrpcInvokeBySignature(""); tell plugin to connect and create
361 : * a reverse channel
362 : */
363 0 : NaClLog(4,
364 : ("NaClManifestProxyConnectionFactory: making RPC"
365 : " to set up connection\n"));
366 0 : rpc_result = NaClSrpcInvokeBySignature(&nap->reverse_channel,
367 : NACL_REVERSE_CONTROL_ADD_CHANNEL,
368 : &bool_status);
369 0 : if (NACL_SRPC_RESULT_OK != rpc_result) {
370 0 : NaClLog(LOG_FATAL,
371 : "NaClManifestProxyConnectionFactory: add channel RPC failed: %d",
372 : rpc_result);
373 : }
374 0 : NaClLog(4,
375 : "NaClManifestProxyConnectionFactory: Start status %d\n", bool_status);
376 :
377 0 : NaClXMutexUnlock(&nap->mu);
378 :
379 0 : *out = (struct NaClSimpleServiceConnection *) mconn;
380 0 : return 0;
381 : }
382 :
383 : struct NaClSimpleServiceVtbl const kNaClManifestProxyVtbl = {
384 : {
385 : NaClManifestProxyDtor,
386 : },
387 : NaClManifestProxyConnectionFactory,
388 : /* see name_service.c vtbl for connection factory and ownership */
389 : /*
390 : * The NaClManifestProxyConnectionFactory creates a subclass of a
391 : * NaClSimpleServiceConnectionFactory object that uses the reverse
392 : * connection object nap->reverse_client to obtain a new RPC channel
393 : * with each manifest connection.
394 : */
395 : NaClSimpleServiceAcceptConnection,
396 : NaClSimpleServiceAcceptAndSpawnHandler,
397 : NaClSimpleServiceRpcHandler,
398 : };
|