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