LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_secure_service.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 349 248 71.1 %
Date: 2014-06-18 Functions: 0 0 -

       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 "native_client/src/trusted/service_runtime/nacl_secure_service.h"
       8                 : 
       9                 : #include <string.h>
      10                 : 
      11                 : #include "native_client/src/public/secure_service.h"
      12                 : 
      13                 : #include "native_client/src/shared/platform/nacl_exit.h"
      14                 : #include "native_client/src/shared/platform/nacl_log.h"
      15                 : #include "native_client/src/shared/platform/nacl_sync.h"
      16                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      17                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      18                 : 
      19                 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
      20                 : #include "native_client/src/trusted/fault_injection/fault_injection.h"
      21                 : #include "native_client/src/trusted/manifest_name_service_proxy/manifest_proxy.h"
      22                 : #include "native_client/src/trusted/simple_service/nacl_simple_service.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_app.h"
      26                 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
      27                 : #include "native_client/src/trusted/service_runtime/nacl_reverse_host_interface.h"
      28                 : #include "native_client/src/trusted/service_runtime/nacl_reverse_quota_interface.h"
      29                 : #include "native_client/src/trusted/service_runtime/nacl_signal.h"
      30                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      31                 : 
      32                 : struct NaClSrpcHandlerDesc const kNaClSecureServiceHandlers[];
      33                 : 
      34              10 : int NaClSecureServiceCtor(struct NaClSecureService  *self,
      35              10 :                           struct NaClApp            *nap,
      36              10 :                           struct NaClDesc           *service_port,
      37              10 :                           struct NaClDesc           *sock_addr) {
      38              10 :   NaClLog(4,
      39                 :           "Entered NaClSecureServiceCtor: self 0x%"NACL_PRIxPTR"\n",
      40                 :           (uintptr_t) self);
      41              20 :   if (NACL_FI_ERROR_COND(
      42                 :           "NaClSecureServiceCtor__NaClSimpleServiceWithSocketCtor",
      43                 :           !NaClSimpleServiceWithSocketCtor(
      44                 :               &self->base,
      45                 :               kNaClSecureServiceHandlers,
      46                 :               NaClThreadInterfaceThreadFactory,
      47                 :               (void *) self,
      48                 :               service_port,
      49                 :               sock_addr))) {
      50               0 :     goto done;
      51                 :   }
      52              10 :   if (!NaClMutexCtor(&self->mu)) {
      53               0 :     NaClLog(4, "NaClMutexCtor failed\n");
      54               0 :     goto failure_mutex_ctor;
      55                 :   }
      56              10 :   if (!NaClCondVarCtor(&self->cv)) {
      57               0 :     NaClLog(4, "NaClCondVar failed\n");
      58               0 :     goto failure_condvar_ctor;
      59                 :   }
      60              10 :   NaClXMutexCtor(&self->mu);
      61              10 :   NaClXCondVarCtor(&self->cv);
      62              10 :   self->nap = nap;
      63              10 :   self->reverse_channel_initialization_state =
      64                 :       NACL_REVERSE_CHANNEL_UNINITIALIZED;
      65              10 :   self->reverse_client = NULL;
      66              10 :   self->conn_count = 0;
      67              10 :   NACL_VTBL(NaClRefCount, self) =
      68                 :       (struct NaClRefCountVtbl *) &kNaClSecureServiceVtbl;
      69              10 :   return 1;
      70                 : 
      71                 :  failure_condvar_ctor:
      72               0 :   NaClMutexDtor(&self->mu);
      73                 :  failure_mutex_ctor:
      74               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
      75                 :  done:
      76               0 :   return 0;
      77              10 : }
      78                 : 
      79               0 : void NaClSecureServiceDtor(struct NaClRefCount *vself) {
      80               0 :   struct NaClSecureService *self = (struct NaClSecureService *) vself;
      81                 : 
      82               0 :   NaClXMutexLock(&self->mu);
      83               0 :   if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
      84                 :       self->reverse_channel_initialization_state) {
      85               0 :     while (NACL_REVERSE_CHANNEL_INITIALIZED !=
      86                 :            self->reverse_channel_initialization_state) {
      87               0 :       NaClXCondVarWait(&self->cv, &self->mu);
      88               0 :     }
      89               0 :   }
      90                 : 
      91               0 :   if (0 != self->conn_count) {
      92               0 :     NaClLog(LOG_FATAL,
      93                 :             "SecureService dtor when connection count is nonzero\n");
      94               0 :   }
      95               0 :   self->conn_count = 0;
      96                 : 
      97               0 :   if (NACL_REVERSE_CHANNEL_INITIALIZED ==
      98                 :       self->reverse_channel_initialization_state) {
      99               0 :     NaClSrpcDtor(&self->reverse_channel);
     100               0 :   }
     101               0 :   if (NULL != self->reverse_client) {
     102               0 :     NaClRefCountUnref((struct NaClRefCount *) self->reverse_client);
     103               0 :   }
     104               0 :   NaClXMutexUnlock(&self->mu);
     105                 : 
     106               0 :   NaClCondVarDtor(&self->cv);
     107               0 :   NaClMutexDtor(&self->mu);
     108                 : 
     109               0 :   NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
     110                 :       &kNaClSimpleServiceVtbl;
     111               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     112               0 : }
     113                 : 
     114                 : int NaClSecureServiceConnectionFactory(
     115              10 :     struct NaClSimpleService            *vself,
     116              10 :     struct NaClDesc                     *conn,
     117              10 :     struct NaClSimpleServiceConnection  **out) {
     118                 :   /* our instance_data is not connection specific */
     119              10 :   return NaClSimpleServiceConnectionFactoryWithInstanceData(
     120                 :       vself, conn, (struct NaClSecureService *) vself, out);
     121                 : }
     122                 : 
     123                 : static void NaClSecureServiceConnectionCountIncr(
     124              10 :     struct NaClSecureService *self) {
     125              10 :   NaClLog(5, "NaClSecureServiceThreadCountIncr\n");
     126              10 :   NaClXMutexLock(&self->mu);
     127              10 :   if (0 == ++self->conn_count) {
     128               0 :     NaClLog(LOG_FATAL,
     129                 :             "NaClSecureServiceThreadCountIncr: "
     130                 :             "thread count overflow!\n");
     131               0 :   }
     132              10 :   NaClXMutexUnlock(&self->mu);
     133              10 : }
     134                 : 
     135                 : static void NaClSecureServiceConnectionCountDecr(
     136               3 :     struct NaClSecureService *self) {
     137               3 :   uint32_t conn_count;
     138                 : 
     139               3 :   NaClLog(5, "NaClSecureServiceThreadCountDecr\n");
     140               3 :   NaClXMutexLock(&self->mu);
     141               3 :   if (0 == self->conn_count) {
     142               0 :     NaClLog(LOG_FATAL,
     143                 :             "NaClSecureServiceThreadCountDecr: "
     144                 :             "decrementing thread count when count is zero\n");
     145               0 :   }
     146               3 :   conn_count = --self->conn_count;
     147               3 :   NaClXMutexUnlock(&self->mu);
     148                 : 
     149               3 :   if (0 == conn_count) {
     150               3 :     NaClLog(4, "NaClSecureServiceThread: all channels closed, exiting.\n");
     151                 :     /*
     152                 :      * Set that we are killed by SIGKILL so that debug stub could report
     153                 :      * this to debugger.
     154                 :      */
     155               3 :     NaClAppShutdown(self->nap, NACL_ABI_W_EXITCODE(0, NACL_ABI_SIGKILL));
     156               3 :   }
     157               0 : }
     158                 : 
     159                 : int NaClSecureServiceAcceptConnection(
     160              10 :     struct NaClSimpleService            *vself,
     161              10 :     struct NaClSimpleServiceConnection  **vconn) {
     162              10 :   struct NaClSecureService *self =
     163                 :     (struct NaClSecureService *) vself;
     164              10 :   int status;
     165                 : 
     166              10 :   NaClLog(4, "NaClSecureServiceAcceptConnection\n");
     167              10 :   status = (*kNaClSimpleServiceVtbl.AcceptConnection)(vself, vconn);
     168              10 :   if (0 == status) {
     169              10 :     NaClSecureServiceConnectionCountIncr(self);
     170              10 :   }
     171              10 :   NaClLog(4, "Leaving NaClSecureServiceAcceptConnection, status %d.\n", status);
     172              10 :   return status;
     173                 : }
     174                 : 
     175              10 : void NaClSecureServiceRpcHandler(struct NaClSimpleService           *vself,
     176              10 :                                  struct NaClSimpleServiceConnection *vconn) {
     177              10 :   struct NaClSecureService *self =
     178                 :     (struct NaClSecureService *) vself;
     179                 : 
     180              10 :   NaClLog(4, "NaClSecureChannelThread started\n");
     181              10 :   (*kNaClSimpleServiceVtbl.RpcHandler)(vself, vconn);
     182              10 :   NaClLog(4, "NaClSecureChannelThread closed.\n");
     183              10 :   NaClSecureServiceConnectionCountDecr(self);
     184              10 : }
     185                 : 
     186                 : static void NaClSecureServiceLoadModuleRpcCallback(
     187               8 :     void            *instance_data,
     188               8 :     NaClErrorCode   status) {
     189               8 :   struct NaClSrpcClosure *done_cls =
     190                 :       (struct NaClSrpcClosure *) instance_data;
     191              16 :   UNREFERENCED_PARAMETER(status);
     192               8 :   NaClLog(4, "NaClSecureChannelLoadModuleRpcCallback: status %d\n", status);
     193               8 :   (*done_cls->Run)(done_cls);
     194               8 : }
     195                 : 
     196                 : /* TODO(teravest): Remove this once http://crbug.com/333950 is resolved. */
     197                 : static void NaClSecureServiceLoadModuleRpc(
     198               8 :     struct NaClSrpcRpc      *rpc,
     199               8 :     struct NaClSrpcArg      **in_args,
     200               8 :     struct NaClSrpcArg      **out_args,
     201               8 :     struct NaClSrpcClosure  *done_cls) {
     202               8 :   struct NaClSecureService        *nssp =
     203                 :       (struct NaClSecureService *) rpc->channel->server_instance_data;
     204               8 :   struct NaClDesc                 *nexe = in_args[0]->u.hval;
     205              16 :   UNREFERENCED_PARAMETER(out_args);
     206                 : 
     207               8 :   NaClLog(4, "NaClSecureServiceLoadModuleRpc: loading module\n");
     208               8 :   rpc->result = NACL_SRPC_RESULT_OK;
     209               8 :   NaClAppLoadModule(nssp->nap,
     210                 :                     nexe,
     211                 :                     NaClSecureServiceLoadModuleRpcCallback,
     212                 :                     (void *) done_cls);
     213               8 :   NaClDescUnref(nexe);
     214               8 :   nexe = NULL;
     215                 : 
     216               8 :   NaClLog(4, "NaClSecureServiceLoadModuleRpc: done\n");
     217               8 : }
     218                 : 
     219                 : /*
     220                 :  * The first connection is performed by this callback handler.  This
     221                 :  * spawns a client thread that will bootstrap the other connections by
     222                 :  * stashing the connection represented by |conn| to make reverse RPCs
     223                 :  * to ask the peer to connect to us.  No thread is spawned; we just
     224                 :  * wrap access to the connection with a lock.
     225                 :  *
     226                 :  * Subsequent connection callbacks will pass the connection to the
     227                 :  * actual thread that made the connection request using |conn|
     228                 :  * received in the first connection.
     229                 :  */
     230                 : static void NaClSecureReverseClientCallback(
     231               3 :     void                        *state,
     232               3 :     struct NaClThreadInterface  *tif,
     233               3 :     struct NaClDesc             *new_conn) {
     234               3 :   struct NaClSecureService          *self =
     235                 :       (struct NaClSecureService *) state;
     236               3 :   struct NaClApp                    *nap = self->nap;
     237               3 :   struct NaClManifestProxy          *manifest_proxy;
     238               3 :   struct NaClReverseHostInterface   *reverse_host_interface;
     239               3 :   struct NaClReverseQuotaInterface  *reverse_quota_interface;
     240               6 :   UNREFERENCED_PARAMETER(tif);
     241                 : 
     242               3 :   NaClLog(4,
     243                 :           ("Entered NaClSecureReverseClientCallback: self 0x%"NACL_PRIxPTR","
     244                 :            " nap 0x%"NACL_PRIxPTR", new_conn 0x%"NACL_PRIxPTR"\n"),
     245                 :           (uintptr_t) self, (uintptr_t) nap, (uintptr_t) new_conn);
     246                 : 
     247               3 :   NaClXMutexLock(&self->mu);
     248               3 :   if (NACL_REVERSE_CHANNEL_INITIALIZATING !=
     249                 :       self->reverse_channel_initialization_state) {
     250                 :     /*
     251                 :      * The reverse channel connection capability is used to make the
     252                 :      * RPC that invokes this callback (this callback is invoked on a
     253                 :      * reverse channel connect), so the plugin wants to initialize the
     254                 :      * reverse channel and in particular the state must be either be
     255                 :      * in-progress or finished.
     256                 :      */
     257               0 :     NaClLog(LOG_FATAL, "Reverse channel already initialized\n");
     258               0 :   }
     259               3 :   NaClXMutexUnlock(&self->mu);
     260               3 :   if (!NaClSrpcClientCtor(&self->reverse_channel, new_conn)) {
     261               0 :     NaClLog(LOG_FATAL, "Reverse channel SRPC Client Ctor failed\n");
     262               0 :     goto done;
     263                 :   }
     264                 :   reverse_host_interface = (struct NaClReverseHostInterface *)
     265               3 :     malloc(sizeof *reverse_host_interface);
     266               3 :   if (NULL == reverse_host_interface ||
     267               6 :       NACL_FI_ERROR_COND(
     268                 :           ("NaClSecureReverseClientCallback"
     269                 :            "__NaClReverseInterfaceCtor"),
     270                 :           !NaClReverseHostInterfaceCtor(reverse_host_interface,
     271                 :                                         self))) {
     272               0 :     NaClLog(LOG_FATAL, "Reverse interface ctor failed\n");
     273               0 :     goto cleanup_reverse_host_interface;
     274                 :   }
     275               3 :   NaClAppRuntimeHostSetup(nap, (struct NaClRuntimeHostInterface *)
     276                 :       reverse_host_interface);
     277                 : 
     278                 :   reverse_quota_interface = (struct NaClReverseQuotaInterface *)
     279               3 :     malloc(sizeof *reverse_quota_interface);
     280               3 :   if (NULL == reverse_quota_interface ||
     281               6 :       NACL_FI_ERROR_COND(
     282                 :           ("NaClSecureReverseClientCallback"
     283                 :            "__NaClReverseQuotaInterfaceCtor"),
     284                 :           !NaClReverseQuotaInterfaceCtor(reverse_quota_interface,
     285                 :                                          self))) {
     286               0 :     NaClLog(LOG_FATAL, "Reverse quota interface ctor failed\n");
     287               0 :     goto cleanup_reverse_quota_interface;
     288                 :   }
     289               3 :   NaClAppDescQuotaSetup(nap, (struct NaClDescQuotaInterface *)
     290                 :       reverse_quota_interface);
     291                 : 
     292               3 :   NaClRefCountSafeUnref((struct NaClRefCount *) reverse_quota_interface);
     293               3 :   reverse_quota_interface = NULL;
     294                 : 
     295                 :   manifest_proxy = (struct NaClManifestProxy *)
     296               3 :       malloc(sizeof *manifest_proxy);
     297               3 :   if (NULL == manifest_proxy ||
     298               3 :       !NaClManifestProxyCtor(manifest_proxy,
     299                 :                              NaClAddrSpSquattingThreadIfFactoryFunction,
     300                 :                              (void *) nap,
     301                 :                              self)) {
     302               0 :     NaClLog(LOG_FATAL, "Manifest proxy ctor failed\n");
     303               0 :     goto cleanup_manifest_proxy;
     304                 :   }
     305                 : 
     306                 :   /*
     307                 :    * NaClSimpleServiceStartServiceThread requires the nap->mu lock.
     308                 :    */
     309               3 :   if (!NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
     310                 :                                            manifest_proxy)) {
     311               0 :     NaClLog(LOG_FATAL, "ManifestProxy start service failed\n");
     312               0 :     goto cleanup_manifest_proxy;
     313                 :   }
     314                 : 
     315               3 :   NaClXMutexLock(&nap->mu);
     316               6 :   (*NACL_VTBL(NaClNameService, nap->name_service)->
     317                 :     CreateDescEntry)(nap->name_service,
     318                 :                      "ManifestNameService", NACL_ABI_O_RDWR,
     319               3 :                      NaClDescRef(manifest_proxy->base.bound_and_cap[1]));
     320               3 :   NaClXMutexUnlock(&nap->mu);
     321                 : 
     322               3 :   NaClXMutexLock(&self->mu);
     323               3 :   self->reverse_channel_initialization_state =
     324                 :     NACL_REVERSE_CHANNEL_INITIALIZED;
     325               3 :   NaClXCondVarBroadcast(&self->cv);
     326               3 :   NaClXMutexUnlock(&self->mu);
     327                 : 
     328                 :  cleanup_manifest_proxy:
     329               3 :   NaClRefCountSafeUnref((struct NaClRefCount *) manifest_proxy);
     330                 :  cleanup_reverse_quota_interface:
     331               3 :   NaClRefCountSafeUnref((struct NaClRefCount *) reverse_quota_interface);
     332                 :  cleanup_reverse_host_interface:
     333               3 :   NaClRefCountSafeUnref((struct NaClRefCount *) reverse_host_interface);
     334                 :  done:
     335               3 :   NaClLog(4, "Leaving NaClSecureReverseClientCallback\n");
     336               3 : }
     337                 : 
     338                 : static void NaClSecureServiceReverseSetupRpc(
     339               3 :     struct NaClSrpcRpc      *rpc,
     340               3 :     struct NaClSrpcArg      **in_args,
     341               3 :     struct NaClSrpcArg      **out_args,
     342               3 :     struct NaClSrpcClosure  *done_cls) {
     343               3 :   struct NaClSecureService        *nssp =
     344                 :       (struct NaClSecureService *) rpc->channel->server_instance_data;
     345               3 :   struct NaClDesc                 *rev_addr = NULL;
     346               3 :   struct NaClSecureReverseClient  *rev;
     347               6 :   UNREFERENCED_PARAMETER(in_args);
     348                 : 
     349               3 :   NaClLog(4, "NaClSecureServiceReverseSetupRpc: reverse setup\n");
     350                 : 
     351               3 :   NaClXMutexLock(&nssp->mu);
     352               3 :   if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
     353                 :       nssp->reverse_channel_initialization_state) {
     354               0 :     NaClLog(LOG_ERROR, "NaClSecureServiceReverseSetupRpc:"
     355                 :             " reverse channel initialization state not uninitialized\n");
     356               0 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
     357               0 :     goto cleanup;
     358                 :   }
     359               3 :   nssp->reverse_channel_initialization_state =
     360                 :       NACL_REVERSE_CHANNEL_INITIALIZATING;
     361               3 :   NaClXCondVarBroadcast(&nssp->cv);
     362                 : 
     363                 :   /* the reverse connection is still coming */
     364               3 :   rev = (struct NaClSecureReverseClient *) malloc(sizeof *rev);
     365               3 :   if (NULL == rev) {
     366               0 :     rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
     367               0 :     goto cleanup;
     368                 :   }
     369               3 :   NaClLog(4, "NaClSecureServiceReverseSetupRpc:"
     370                 :           " invoking NaClSecureReverseClientCtor\n");
     371               3 :   if (!NaClSecureReverseClientCtor(rev,
     372                 :                                    NaClSecureReverseClientCallback,
     373                 :                                    (void *) nssp)) {
     374               0 :     free(rev);
     375               0 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
     376               0 :     goto cleanup;
     377                 :   }
     378                 : 
     379               3 :   if (!NaClSimpleRevClientStartServiceThread(&rev->base)) {
     380               0 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
     381               0 :     goto cleanup;
     382                 :   }
     383                 : 
     384               3 :   nssp->reverse_client = (struct NaClSecureReverseClient *) NaClRefCountRef(
     385                 :       (struct NaClRefCount *) rev);
     386                 : 
     387               3 :   out_args[0]->u.hval = NaClDescRef(rev->base.bound_and_cap[1]);
     388               3 :   rpc->result = NACL_SRPC_RESULT_OK;
     389                 :  cleanup:
     390               3 :   NaClXMutexUnlock(&nssp->mu);
     391               3 :   NaClLog(4, "NaClSecureServiceReverseSetupRpc: done, "
     392                 :           " rev_addr 0x%08"NACL_PRIxPTR"\n",
     393                 :           (uintptr_t) rev_addr);
     394               3 :   (*done_cls->Run)(done_cls);
     395               3 : }
     396                 : 
     397                 : struct StartModuleCallbackState {
     398                 :   int                    *out_status;
     399                 :   struct NaClSrpcClosure *cls;
     400                 : };
     401                 : 
     402                 : static void NaClSecureServiceStartModuleRpcCallback(
     403              10 :     void            *instance_data,
     404              10 :     NaClErrorCode   status) {
     405              10 :   struct StartModuleCallbackState *state =
     406                 :       (struct StartModuleCallbackState *) instance_data;
     407              10 :   NaClLog(4, "NaClSecureChannelStartModuleRpcCallback: status %d\n", status);
     408                 : 
     409                 :   /*
     410                 :    * The RPC reply is now sent.  This has to occur before we signal
     411                 :    * the main thread to possibly start, since in the case of a failure
     412                 :    * the main thread may quickly exit.  If the main thread does this
     413                 :    * before we sent the RPC reply, then the plugin will be left
     414                 :    * without an answer.
     415                 :    */
     416              10 :   *state->out_status = (int) status;
     417              10 :   (*state->cls->Run)(state->cls);
     418              10 :   free(state);
     419              10 : }
     420                 : 
     421                 : static void NaClSecureServiceStartModuleRpc(
     422              10 :     struct NaClSrpcRpc      *rpc,
     423              10 :     struct NaClSrpcArg      **in_args,
     424              10 :     struct NaClSrpcArg      **out_args,
     425              10 :     struct NaClSrpcClosure  *done_cls) {
     426              10 :   struct NaClSecureService        *nssp =
     427                 :       (struct NaClSecureService *) rpc->channel->server_instance_data;
     428              10 :   struct StartModuleCallbackState *state;
     429              20 :   UNREFERENCED_PARAMETER(in_args);
     430                 : 
     431              10 :   NaClLog(4, "NaClSecureChannelStartModuleRpc: starting module\n");
     432                 : 
     433                 :   /*
     434                 :    * When reverse setup is being used, we have to block and wait for reverse
     435                 :    * channel to become initialized before we can proceed with start module.
     436                 :    */
     437              10 :   NaClXMutexLock(&nssp->mu);
     438              10 :   if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
     439                 :       nssp->reverse_channel_initialization_state) {
     440               9 :     while (NACL_REVERSE_CHANNEL_INITIALIZED !=
     441                 :            nssp->reverse_channel_initialization_state) {
     442               3 :       NaClXCondVarWait(&nssp->cv, &nssp->mu);
     443               3 :     }
     444               3 :   }
     445              10 :   NaClXMutexUnlock(&nssp->mu);
     446                 : 
     447              10 :   state = (struct StartModuleCallbackState *) malloc(sizeof *state);
     448              10 :   if (NULL == state) {
     449               0 :     rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
     450               0 :     (*done_cls->Run)(done_cls);
     451               0 :     return;
     452                 :   }
     453              10 :   state->out_status = &out_args[0]->u.ival;
     454              10 :   state->cls = done_cls;
     455                 : 
     456              10 :   rpc->result = NACL_SRPC_RESULT_OK;
     457              10 :   NaClAppStartModule(nssp->nap,
     458                 :                      NaClSecureServiceStartModuleRpcCallback,
     459                 :                      (void *) state);
     460                 : 
     461              10 :   NaClLog(4, "NaClSecureChannelStartModuleRpc: done\n");
     462              20 : }
     463                 : 
     464                 : static void NaClSecureServiceLogRpc(
     465               0 :     struct NaClSrpcRpc      *rpc,
     466               0 :     struct NaClSrpcArg      **in_args,
     467               0 :     struct NaClSrpcArg      **out_args,
     468               0 :     struct NaClSrpcClosure  *done_cls) {
     469               0 :   int   severity = in_args[0]->u.ival;
     470               0 :   char  *msg = in_args[1]->arrays.str;
     471               0 :   UNREFERENCED_PARAMETER(out_args);
     472                 : 
     473               0 :   NaClLog(5, "NaClSecureChannelLogRpc\n");
     474               0 :   NaClLog(severity, "%s\n", msg);
     475               0 :   NaClLog(5, "NaClSecureChannelLogRpc\n");
     476               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     477               0 :   (*done_cls->Run)(done_cls);
     478               0 : }
     479                 : 
     480                 : static void NaClSecureServiceShutdownRpc(
     481               2 :     struct NaClSrpcRpc      *rpc,
     482               2 :     struct NaClSrpcArg      **in_args,
     483               2 :     struct NaClSrpcArg      **out_args,
     484               2 :     struct NaClSrpcClosure  *done) {
     485               2 :   struct NaClSecureService  *nssp =
     486                 :       (struct NaClSecureService *) rpc->channel->server_instance_data;
     487               4 :   UNREFERENCED_PARAMETER(rpc);
     488               4 :   UNREFERENCED_PARAMETER(in_args);
     489               4 :   UNREFERENCED_PARAMETER(out_args);
     490               4 :   UNREFERENCED_PARAMETER(done);
     491                 : 
     492               2 :   NaClAppShutdown(nssp->nap, 0);
     493               2 : }
     494                 : 
     495                 : struct NaClSrpcHandlerDesc const kNaClSecureServiceHandlers[] = {
     496                 :   { NACL_SECURE_SERVICE_LOAD_MODULE, NaClSecureServiceLoadModuleRpc, },
     497                 :   { NACL_SECURE_SERVICE_REVERSE_SETUP, NaClSecureServiceReverseSetupRpc, },
     498                 :   { NACL_SECURE_SERVICE_START_MODULE, NaClSecureServiceStartModuleRpc, },
     499                 :   { NACL_SECURE_SERVICE_LOG, NaClSecureServiceLogRpc, },
     500                 :   { NACL_SECURE_SERVICE_HARD_SHUTDOWN, NaClSecureServiceShutdownRpc, },
     501                 :   { (char const *) NULL, (NaClSrpcMethod) NULL, },
     502                 : };
     503                 : 
     504                 : struct NaClSimpleServiceVtbl const kNaClSecureServiceVtbl = {
     505                 :   {
     506                 :     NaClSecureServiceDtor,
     507                 :   },
     508                 :   NaClSecureServiceConnectionFactory,
     509                 :   NaClSecureServiceAcceptConnection,
     510                 :   NaClSimpleServiceAcceptAndSpawnHandler,
     511                 :   NaClSecureServiceRpcHandler,
     512                 : };
     513                 : 
     514                 : struct NaClSecureRevClientConnHandler {
     515                 :   struct NaClSecureRevClientConnHandler  *next;
     516                 : 
     517                 :   /* used by NaClSimpleRevServiceClient's ClientCallback fn */
     518                 :   void                                   (*handler)(
     519                 :       void                                          *state,
     520                 :       struct NaClThreadInterface                    *tif,
     521                 :       struct NaClDesc                               *conn);
     522                 :   void                                   *state;
     523                 : };
     524                 : 
     525                 : static void NaClSecureReverseClientInternalCallback(
     526               4 :     void                        *state,
     527               4 :     struct NaClThreadInterface  *tif,
     528               4 :     struct NaClDesc             *conn) {
     529               4 :   struct NaClSecureReverseClient *self =
     530                 :       (struct NaClSecureReverseClient *) state;
     531               4 :   struct NaClSecureRevClientConnHandler *hand_ptr;
     532                 : 
     533               4 :   NaClLog(4, "Entered NaClSecureReverseClientInternalCallback\n");
     534               4 :   hand_ptr = (*NACL_VTBL(NaClSecureReverseClient, self)->RemoveHandler)(self);
     535               4 :   NaClLog(4, " got callback object %"NACL_PRIxPTR"\n", (uintptr_t) hand_ptr);
     536               4 :   NaClLog(4,
     537                 :           " callback:0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n",
     538                 :           (uintptr_t) hand_ptr->handler,
     539                 :           (uintptr_t) hand_ptr->state,
     540                 :           (uintptr_t) conn);
     541               4 :   (*hand_ptr->handler)(hand_ptr->state, tif, conn);
     542               4 :   NaClLog(4, "NaClSecureReverseClientInternalCallback: freeing memory\n");
     543               4 :   free(hand_ptr);
     544               4 :   NaClLog(4, "Leaving NaClSecureReverseClientInternalCallback\n");
     545               4 : }
     546                 : 
     547                 : /*
     548                 :  * Require an initial connection handler in the Ctor, so that it's
     549                 :  * obvious that a reverse client needs to accept an IMC connection
     550                 :  * from the server to get things bootstrapped.
     551                 :  */
     552                 : int NaClSecureReverseClientCtor(
     553               3 :     struct NaClSecureReverseClient  *self,
     554               3 :     void                            (*client_callback)(
     555                 :         void *, struct NaClThreadInterface*, struct NaClDesc *),
     556               3 :     void                            *state) {
     557               3 :   NaClLog(4,
     558                 :           "Entered NaClSecureReverseClientCtor, self 0x%"NACL_PRIxPTR"\n",
     559                 :           (uintptr_t) self);
     560               3 :   if (!NaClSimpleRevClientCtor(&self->base,
     561                 :                                NaClSecureReverseClientInternalCallback,
     562                 :                                (void *) self,
     563                 :                                NaClThreadInterfaceThreadFactory,
     564                 :                                (void *) NULL)) {
     565               0 :     goto failure_simple_ctor;
     566                 :   }
     567               3 :   NaClLog(4, "NaClSecureReverseClientCtor: Mutex\n");
     568               3 :   if (!NaClMutexCtor(&self->mu)) {
     569               0 :     goto failure_mutex_ctor;
     570                 :   }
     571               3 :   self->queue_head = (struct NaClSecureRevClientConnHandler *) NULL;
     572               3 :   self->queue_insert = &self->queue_head;
     573                 : 
     574               3 :   NACL_VTBL(NaClRefCount, self) =
     575                 :       (struct NaClRefCountVtbl *) &kNaClSecureReverseClientVtbl;
     576                 : 
     577               3 :   NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler\n");
     578               3 :   if (!(*NACL_VTBL(NaClSecureReverseClient, self)->
     579                 :         InsertHandler)(self, client_callback, state)) {
     580               0 :     goto failure_handler_insert;
     581                 :   }
     582                 : 
     583               3 :   NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
     584               3 :   return 1;
     585                 : 
     586                 :  failure_handler_insert:
     587               0 :   NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler failed\n");
     588               0 :   NACL_VTBL(NaClRefCount, self) =
     589                 :       (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
     590                 : 
     591               0 :   self->queue_insert = (struct NaClSecureRevClientConnHandler **) NULL;
     592               0 :   NaClMutexDtor(&self->mu);
     593                 : 
     594                 :  failure_mutex_ctor:
     595               0 :   NaClLog(4, "NaClSecureReverseClientCtor: Mutex failed\n");
     596               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
     597                 :  failure_simple_ctor:
     598               0 :   NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
     599               0 :   return 0;
     600               3 : }
     601                 : 
     602               0 : void NaClSecureReverseClientDtor(struct NaClRefCount *vself) {
     603               0 :   struct NaClSecureReverseClient *self =
     604                 :       (struct NaClSecureReverseClient *) vself;
     605                 : 
     606               0 :   struct NaClSecureRevClientConnHandler  *entry;
     607               0 :   struct NaClSecureRevClientConnHandler  *next;
     608                 : 
     609               0 :   for (entry = self->queue_head; NULL != entry; entry = next) {
     610               0 :     next = entry->next;
     611               0 :     free(entry);
     612               0 :   }
     613               0 :   NaClMutexDtor(&self->mu);
     614                 : 
     615               0 :   NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
     616                 :       &kNaClSimpleRevClientVtbl;
     617               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
     618               0 : }
     619                 : 
     620                 : /*
     621                 :  * Caller must set up handler before issuing connection request RPC on
     622                 :  * nap->reverse_channel, since otherwise the connection handler queue
     623                 :  * may be empty and the connect code would abort.  Because the connect
     624                 :  * doesn't wait for a handler, we don't need a condvar.
     625                 :  *
     626                 :  * We do not need to serialize on the handlers, since the
     627                 :  * RPC-server/IMC-client implementation should not distinguish one
     628                 :  * connection from another: it is okay for two handlers to be
     629                 :  * inserted, and two connection request RPCs to be preformed
     630                 :  * (sequentially, since they are over a single channel), and have the
     631                 :  * server side spawn threads that asynchronously connect twice, in the
     632                 :  * "incorrect" order, etc.
     633                 :  */
     634                 : int NaClSecureReverseClientInsertHandler(
     635               4 :     struct NaClSecureReverseClient  *self,
     636               4 :     void                            (*handler)(
     637                 :         void                        *handler_state,
     638                 :         struct NaClThreadInterface  *thread_if,
     639                 :         struct NaClDesc             *new_conn),
     640               4 :     void                            *state) {
     641               4 :   struct NaClSecureRevClientConnHandler *entry;
     642               4 :   int                                   retval = 0; /* fail */
     643                 : 
     644               4 :   NaClLog(4,
     645                 :           ("NaClSecureReverseClientInsertHandler: "
     646                 :            "handler 0x%"NACL_PRIxPTR", state 0x%"NACL_PRIxPTR"\n"),
     647                 :           (uintptr_t) handler, (uintptr_t) state);
     648                 : 
     649               4 :   NaClXMutexLock(&self->mu);
     650                 : 
     651               4 :   entry = (struct NaClSecureRevClientConnHandler *) malloc(sizeof *entry);
     652               4 :   if (NULL == entry) {
     653               0 :     goto cleanup;
     654                 :   }
     655               4 :   entry->handler = handler;
     656               4 :   entry->state = state;
     657               4 :   entry->next = (struct NaClSecureRevClientConnHandler *) NULL;
     658               4 :   *self->queue_insert = entry;
     659               4 :   self->queue_insert = &entry->next;
     660               4 :   retval = 1;
     661                 : 
     662                 :  cleanup:
     663               4 :   NaClXMutexUnlock(&self->mu);
     664               4 :   return retval;
     665                 : }
     666                 : 
     667                 : struct NaClSecureRevClientConnHandler *NaClSecureReverseClientRemoveHandler(
     668               4 :     struct NaClSecureReverseClient *self) {
     669               4 :   struct NaClSecureRevClientConnHandler *head;
     670                 : 
     671               4 :   NaClLog(4, "Entered NaClSecureReverseClientRemoveHandler, acquiring lock\n");
     672               4 :   NaClXMutexLock(&self->mu);
     673               4 :   NaClLog(4, "NaClSecureReverseClientRemoveHandler, got lock\n");
     674               4 :   head = self->queue_head;
     675               4 :   if (NULL == head) {
     676               0 :     NaClLog(LOG_FATAL,
     677                 :             "NaClSecureReverseClientRemoveHandler:  empty handler queue\n");
     678               0 :   }
     679               4 :   if (NULL == (self->queue_head = head->next)) {
     680               4 :     NaClLog(4, "NaClSecureReverseClientRemoveHandler, last elt patch up\n");
     681               4 :     self->queue_insert = &self->queue_head;
     682               4 :   }
     683               4 :   NaClLog(4, "NaClSecureReverseClientRemoveHandler, unlocking\n");
     684               4 :   NaClXMutexUnlock(&self->mu);
     685                 : 
     686               4 :   head->next = NULL;
     687               4 :   NaClLog(4,
     688                 :           ("Leaving NaClSecureReverseClientRemoveHandler:"
     689                 :            " returning %"NACL_PRIxPTR"\n"),
     690                 :           (uintptr_t) head);
     691               4 :   return head;
     692                 : }
     693                 : 
     694                 : struct NaClSecureReverseClientVtbl const kNaClSecureReverseClientVtbl = {
     695                 :   {
     696                 :     {
     697                 :       NaClSecureReverseClientDtor,
     698                 :     },
     699                 :   },
     700                 :   NaClSecureReverseClientInsertHandler,
     701                 :   NaClSecureReverseClientRemoveHandler,
     702                 : };

Generated by: LCOV version 1.7