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