LCOV - code coverage report
Current view: directory - src/trusted/nonnacl_util - sel_ldr_launcher.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 169 103 60.9 %
Date: 2012-02-16 Functions: 0 0 -

       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 <assert.h>
       8                 : 
       9                 : #include <algorithm>
      10                 : #include <iterator>
      11                 : #include <vector>
      12                 : 
      13                 : #if NACL_OSX
      14                 : #include <crt_externs.h>
      15                 : #endif
      16                 : 
      17                 : #include "native_client/src/include/nacl_macros.h"
      18                 : #include "native_client/src/include/nacl_scoped_ptr.h"
      19                 : #include "native_client/src/include/nacl_string.h"
      20                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      21                 : #include "native_client/src/shared/platform/nacl_check.h"
      22                 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
      23                 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
      24                 : #include "native_client/src/trusted/service_runtime/env_cleanser.h"
      25                 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
      26                 : 
      27                 : using std::vector;
      28                 : 
      29                 : 
      30                 : namespace nacl {
      31                 : 
      32              12 : SelLdrLauncher::SelLdrLauncher()
      33                 :   : child_process_(kInvalidHandle),
      34                 :     channel_(kInvalidHandle),
      35                 :     channel_number_(-1),
      36                 :     command_prefix_(""),
      37                 :     bootstrap_socket_(NULL),
      38                 :     socket_addr_(NULL),
      39              12 :     sel_ldr_locator_(new PluginSelLdrLocator()) {
      40              12 : }
      41                 : 
      42               0 : SelLdrLauncher::SelLdrLauncher(SelLdrLocator* sel_ldr_locator)
      43                 :   : child_process_(kInvalidHandle),
      44                 :     channel_(kInvalidHandle),
      45                 :     channel_number_(-1),
      46                 :     bootstrap_socket_(NULL),
      47                 :     socket_addr_(NULL),
      48               0 :     sel_ldr_locator_(sel_ldr_locator) {
      49               0 :   CHECK(sel_ldr_locator != NULL);
      50               0 : }
      51                 : 
      52               0 : void SelLdrLauncher::GetPluginDirectory(char* buffer, size_t len) {
      53               0 :   sel_ldr_locator_->GetDirectory(buffer, len);
      54               0 : }
      55                 : 
      56              11 : static DescWrapper* GetSockAddr(DescWrapper* desc) {
      57                 :   DescWrapper::MsgHeader   header;
      58                 :   DescWrapper::MsgIoVec    iovec[1];
      59                 :   DescWrapper*             descs[NACL_ABI_IMC_USER_DESC_MAX];
      60                 :   scoped_array<unsigned char> bytes(
      61              11 :       new unsigned char[NACL_ABI_IMC_USER_BYTES_MAX]);
      62              11 :   if (bytes.get() == NULL) {
      63               0 :     return NULL;
      64                 :   }
      65                 : 
      66                 :   // Set up to receive a message.
      67              11 :   iovec[0].base = bytes.get();
      68              11 :   iovec[0].length = NACL_ABI_IMC_USER_BYTES_MAX;
      69              11 :   header.iov = iovec;
      70              11 :   header.iov_length = NACL_ARRAY_SIZE(iovec);
      71              11 :   header.ndescv = descs;
      72              11 :   header.ndescv_length = NACL_ARRAY_SIZE(descs);
      73              11 :   header.flags = 0;
      74                 :   // Receive the message.
      75              11 :   if (0 != desc->RecvMsg(&header, 0,
      76                 :                          static_cast<struct NaClDescQuotaInterface*>(NULL))) {
      77               0 :     return NULL;
      78                 :   }
      79                 :   // Check that there was exactly one descriptor passed.
      80              11 :   if (1 != header.ndescv_length) {
      81               0 :     return NULL;
      82                 :   }
      83                 : 
      84              11 :   return descs[0];
      85                 : }
      86                 : 
      87              11 : bool SelLdrLauncher::LoadModule(NaClSrpcChannel* command, DescWrapper* nexe) {
      88              11 :   NaClLog(4, "Entered SelLdrLauncher::LoadModule\n");
      89                 :   NaClSrpcResultCodes rpc_result = NaClSrpcInvokeBySignature(command,
      90                 :                                                              "load_module:hs:",
      91                 :                                                              nexe->desc(),
      92              11 :                                                              "place holder");
      93              11 :   NaClLog(4, "SelLdrLauncher::LoadModule rpc result %d\n", (int) rpc_result);
      94              11 :   return NACL_SRPC_RESULT_OK == rpc_result;
      95                 : }
      96                 : 
      97                 : bool SelLdrLauncher::StartModule(NaClSrpcChannel* command,
      98              11 :                                  NaClErrorCode* code) {
      99                 :   // Start untrusted code module
     100              11 :   NaClLog(4, "Entered SelLdrLauncher::StartModule\n");
     101                 :   int start_result;
     102                 :   NaClSrpcResultCodes rpc_result = NaClSrpcInvokeBySignature(command,
     103                 :                                                              "start_module::i",
     104              11 :                                                              &start_result);
     105              11 :   NaClLog(4, "SelLdrLauncher::StartModule rpc result %d\n", (int) rpc_result);
     106              11 :   if (NACL_SRPC_RESULT_OK != rpc_result) {
     107               0 :     NaClSrpcDtor(command);
     108               0 :     *code = LOAD_INTERNAL;
     109               0 :     NaClLog(4, "Leaving SelLdrLauncher::StartModule, FAILED\n");
     110               0 :     return false;
     111                 :   }
     112                 : 
     113              11 :   *code = (NaClErrorCode) start_result;
     114              11 :   NaClLog(4, "Leaving SelLdrLauncher::StartModule, success\n");
     115              11 :   return true;
     116                 : }
     117                 : 
     118                 : 
     119              11 : bool SelLdrLauncher::SetupBootstrapChannel() {
     120                 :   // channel_ is initialized in LaunchFromCommandLine if
     121                 :   // channel_number_ is not -1, and InitCommandLine requires imc_fd to be
     122                 :   // supplied which is used to initialize channel_number_, so channel_ should
     123                 :   // never be invalid.
     124                 : 
     125              11 :   CHECK(factory_ == NULL);
     126              11 :   factory_.reset(new DescWrapperFactory);
     127                 : 
     128              11 :   CHECK(channel_ != kInvalidHandle);
     129              11 :   bootstrap_socket_.reset(factory_->MakeImcSock(channel_));
     130              11 :   if (bootstrap_socket_ == NULL) {
     131                 :     NaClLog(4, ("Leaving SelLdrLauncher::SetupBootstrapChannel"
     132               0 :                 " SetupBootstrapChannel failed\n"));
     133               0 :     return false;
     134                 :   }
     135                 : 
     136                 :   // bootstrap_socket_ now has ownership of channel_, so we get rid of
     137                 :   // our "reference" to it.
     138              11 :   channel_ = kInvalidHandle;
     139              11 :   return true;
     140                 : }
     141                 : 
     142              11 : bool SelLdrLauncher::GetLdrSocketAddress() {
     143                 :   // Get the socket address from the descriptor.
     144              11 :   socket_addr_.reset(GetSockAddr(bootstrap_socket_.get()));
     145              11 :   if (socket_addr_ == NULL) {
     146               0 :     NaClLog(4, "SelLdrLauncher::GetLdrSocketAddress: GetSockAddr failed\n");
     147               0 :     return false;
     148                 :   }
     149              11 :   return true;
     150                 : }
     151                 : 
     152              11 : bool SelLdrLauncher::SetupCommandChannel(NaClSrpcChannel* command) {
     153                 :   // The first connection goes to the trusted command channel.
     154              11 :   scoped_ptr<DescWrapper> command_desc(socket_addr_->Connect());
     155              11 :   if (command_desc == NULL) {
     156               0 :     NaClLog(4, "SelLdrLauncher::SetupCommandChannel: Connect failed\n");
     157               0 :     return false;
     158                 :   }
     159                 :   // Start the SRPC client to communicate with the trusted command channel.
     160                 :   // SRPC client takes an additional reference to command_desc.
     161              11 :   if (!NaClSrpcClientCtor(command, command_desc->desc())) {
     162               0 :     NaClLog(4, "SelLdrLauncher::SetupCommandChannel: command ctor failed\n");
     163               0 :     return false;
     164                 :   }
     165              11 :   return true;
     166                 : }
     167                 : 
     168              11 : bool SelLdrLauncher::SetupApplicationChannel(NaClSrpcChannel* app_channel) {
     169                 :   // The second connection goes to the service itself.
     170              11 :   scoped_ptr<DescWrapper> untrusted_desc(socket_addr_->Connect());
     171              11 :   if (untrusted_desc == NULL) {
     172               0 :     return false;
     173                 :   }
     174                 :   // Start the SRPC client to communicate with the untrusted service
     175                 :   // SRPC client takes an additional reference to untrusted_desc.
     176              11 :   if (!NaClSrpcClientCtor(app_channel, untrusted_desc->desc())) {
     177                 :     NaClLog(4,
     178               1 :             "SelLdrLauncher::SetupApplicationChannel: untrusted ctor failed\n");
     179               1 :     return false;
     180                 :   }
     181              10 :   return true;
     182                 : }
     183                 : 
     184                 : bool SelLdrLauncher::SetupCommandAndLoad(NaClSrpcChannel* command,
     185              11 :                                          DescWrapper* nexe) {
     186              11 :   if (!SetupBootstrapChannel()) {
     187               0 :     return false;
     188                 :   }
     189              11 :   if (!GetLdrSocketAddress()) {
     190               0 :     return false;
     191                 :   }
     192              11 :   if (!SetupCommandChannel(command)) {
     193               0 :     return false;
     194                 :   }
     195              11 :   if (NULL != nexe) {
     196              11 :     if (!LoadModule(command, nexe)) {
     197               0 :       NaClSrpcDtor(command);
     198               0 :       return false;
     199                 :     }
     200                 :   }
     201              11 :   return true;
     202                 : }
     203                 : 
     204                 : bool
     205                 : SelLdrLauncher::StartModuleAndSetupAppChannel(NaClSrpcChannel* command,
     206              11 :                                               NaClSrpcChannel* out_app_chan) {
     207                 :   NaClErrorCode code;
     208              11 :   if (!StartModule(command, &code)) {
     209                 :     NaClLog(4,
     210                 :             ("SelLdrLauncher::StartModuleAndSetupAppChannel: start module"
     211                 :              " failed %d (%s) \n"),
     212                 :             (int) code,
     213               0 :             NaClErrorString(code));
     214               0 :     return false;
     215                 :   }
     216              11 :   if (!SetupApplicationChannel(out_app_chan)) {
     217               1 :     return false;
     218                 :   }
     219                 : 
     220              10 :   return true;
     221                 : }
     222                 : 
     223                 : #ifdef NACL_STANDALONE
     224                 : /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */
     225                 : extern "C" char **environ;
     226                 : 
     227              12 : static char **GetEnviron() {
     228                 : #if NACL_OSX
     229                 :   /* Mac dynamic libraries cannot access the environ variable directly. */
     230              12 :   return *_NSGetEnviron();
     231                 : #else
     232                 :   return environ;
     233                 : #endif
     234                 : }
     235                 : #endif
     236                 : 
     237               0 : void SelLdrLauncher::SetCommandPrefix(const nacl::string& prefix) {
     238               0 :   command_prefix_ = prefix;
     239               0 : }
     240                 : 
     241              12 : void SelLdrLauncher::BuildCommandLine(vector<nacl::string>* command) {
     242              12 :   assert(sel_ldr_ != NACL_NO_FILE_PATH);  // Set by InitCommandLine().
     243              12 :   if (!command_prefix_.empty())
     244               0 :     command->push_back(command_prefix_);
     245              12 :   if (!sel_ldr_bootstrap_.empty())
     246               0 :     command->push_back(sel_ldr_bootstrap_);
     247              12 :   command->push_back(sel_ldr_);
     248              12 :   if (!sel_ldr_bootstrap_.empty())
     249               0 :     command->push_back("--r_debug=0xXXXXXXXXXXXXXXXX");
     250              12 :   command->push_back("-R");  // RPC will be used to point to the nexe.
     251                 : 
     252              12 :   command->insert(command->end(), sel_ldr_argv_.begin(), sel_ldr_argv_.end());
     253                 : 
     254                 :   // Our use of "environ" above fails to link in the "shared" (DLL)
     255                 :   // build of Chromium on Windows.  However, we do not use
     256                 :   // BuildCommandLine() when integrated into Chromium anyway -- we use
     257                 :   // sel_main_chrome.c -- so it is safe to disable this code, which is
     258                 :   // largely for debugging.
     259                 :   // TODO(mseaborn): Tidy this up so that we do not need a conditional.
     260                 : #ifdef NACL_STANDALONE
     261                 :   struct NaClEnvCleanser env_cleanser;
     262              12 :   NaClEnvCleanserCtor(&env_cleanser, 1);
     263              12 :   if (!NaClEnvCleanserInit(&env_cleanser, GetEnviron(), NULL)) {
     264               0 :     NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n");
     265                 :   }
     266              24 :   for (const char* const* env = NaClEnvCleanserEnvironment(&env_cleanser);
     267                 :        *env != NULL;
     268                 :        ++env) {
     269               0 :     command->push_back("-E");
     270               0 :     command->push_back(*env);
     271                 :   }
     272              12 :   NaClEnvCleanserDtor(&env_cleanser);
     273                 : #endif
     274                 : 
     275              12 :   if (application_argv_.size() > 0) {
     276                 :     // Separator between sel_universal and app args.
     277               1 :     command->push_back("--");
     278                 :     command->insert(command->end(),
     279               1 :                     application_argv_.begin(), application_argv_.end());
     280                 :   }
     281              12 : }
     282                 : 
     283                 : void SelLdrLauncher::InitCommandLine(int imc_fd,
     284                 :                                      const vector<nacl::string>& sel_ldr_argv,
     285              12 :                                      const vector<nacl::string>& app_argv) {
     286              12 :   assert(sel_ldr_ == NACL_NO_FILE_PATH);  // Make sure we don't call this twice.
     287                 : 
     288              12 :   char* var = getenv("NACL_SEL_LDR");
     289              12 :   if (var != NULL) {
     290              12 :     sel_ldr_ = var;
     291                 :   } else {
     292               0 :     sel_ldr_ = GetSelLdrPathName();
     293                 :   }
     294              12 :   char *bootstrap_var = getenv("NACL_SEL_LDR_BOOTSTRAP");
     295              12 :   if (bootstrap_var != NULL) {
     296               0 :     sel_ldr_bootstrap_ = bootstrap_var;
     297                 :   } else {
     298              12 :     sel_ldr_bootstrap_ = GetSelLdrBootstrapPathName();
     299                 :   }
     300              12 :   copy(sel_ldr_argv.begin(), sel_ldr_argv.end(), back_inserter(sel_ldr_argv_));
     301              12 :   copy(app_argv.begin(), app_argv.end(), back_inserter(application_argv_));
     302              12 :   channel_number_ = imc_fd;
     303              12 : }
     304                 : 
     305              22 : void SelLdrLauncher::CloseHandlesAfterLaunch() {
     306              33 :   for (size_t i = 0; i < close_after_launch_.size(); i++) {
     307              11 :     Close(close_after_launch_[i]);
     308                 :   }
     309              22 :   close_after_launch_.clear();
     310              22 : }
     311                 : 
     312               0 : DescWrapper* SelLdrLauncher::Wrap(NaClDesc* raw_desc) {
     313               0 :   CHECK(factory_ != NULL);
     314               0 :   return factory_->MakeGeneric(raw_desc);
     315                 : }
     316                 : 
     317               2 : DescWrapper* SelLdrLauncher::WrapCleanup(NaClDesc* raw_desc) {
     318               2 :   CHECK(factory_ != NULL);
     319               2 :   return factory_->MakeGenericCleanup(raw_desc);
     320                 : }
     321                 : 
     322                 : #if defined(NACL_STANDALONE)
     323               0 : bool SelLdrLauncher::Start(int socket_count, Handle* result_sockets) {
     324                 :   // Temporary: this interface is highly tailored to use by the browser
     325                 :   // plugin, which currently wants to have exactly three sockets.
     326                 :   // 0 -- the "bootstrap" socket.
     327                 :   // 1 -- the "async receive" socket.
     328                 :   // 2 -- the "async send" socket.
     329                 :   // TODO(sehr): Change this API to return only the bootstrap socket when
     330                 :   // the async support is removed.
     331               0 :   if (socket_count != 3) {
     332               0 :     return false;
     333                 :   }
     334                 :   // The arguments we want to pass to the service runtime are
     335                 :   // "-X 5" causes the service runtime to create a bound socket and socket
     336                 :   //      address at descriptors 3 and 4 in the untrusted code for the nexe
     337                 :   //      or IRT to use.  The argument to "-X", 5, is the host-OS descriptor
     338                 :   //      over which the internal representation of the sock addr is sent in
     339                 :   //      order to bootstrap communications with the untrusted NaCl module.
     340                 :   //      (NB: 5 is in a completely different namespace from the 3,4.)
     341               0 :   const char* kSelLdrArgs[] = { "-X", "5" };
     342               0 :   const int kSelLdrArgLength = NACL_ARRAY_SIZE(kSelLdrArgs);
     343                 :   vector<nacl::string> args_for_sel_ldr(kSelLdrArgs,
     344               0 :                                         kSelLdrArgs + kSelLdrArgLength);
     345               0 :   vector<nacl::string> args_for_nexe;
     346               0 :   const char* irt_library_path = getenv("NACL_IRT_LIBRARY");
     347               0 :   if (NULL != irt_library_path) {
     348               0 :     args_for_sel_ldr.push_back("-B");
     349               0 :     args_for_sel_ldr.push_back(irt_library_path);
     350                 :   }
     351                 :   // This "5" matches the "-X 5" argument above.
     352               0 :   InitCommandLine(5, args_for_sel_ldr, args_for_nexe);
     353                 : 
     354               0 :   result_sockets[1] = ExportImcFD(6);
     355               0 :   if (result_sockets[1] == nacl::kInvalidHandle) {
     356               0 :     return false;
     357                 :   }
     358               0 :   result_sockets[2] = ExportImcFD(7);
     359               0 :   if (result_sockets[2] == nacl::kInvalidHandle) {
     360               0 :     return false;
     361                 :   }
     362               0 :   if (!LaunchFromCommandLine()) {
     363               0 :     return false;
     364                 :   }
     365               0 :   result_sockets[0] = channel_;
     366               0 :   return true;
     367                 : }
     368                 : #endif  // defined(NACL_STANDALONE)
     369                 : 
     370                 : }  // namespace nacl

Generated by: LCOV version 1.7