LCOV - code coverage report
Current view: directory - src/trusted/sel_universal - sel_universal.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 185 134 72.4 %
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                 : // Second generation sel_universal implemented in C++
       8                 : 
       9                 : #include <stdio.h>
      10                 : 
      11                 : #include <fstream>
      12                 : #include <map>
      13                 : #include <sstream>
      14                 : #include <string>
      15                 : #include <vector>
      16                 : 
      17                 : #include "native_client/src/include/nacl_string.h"
      18                 : #include "native_client/src/include/nacl_macros.h"
      19                 : #include "native_client/src/include/nacl_scoped_ptr.h"
      20                 : #include "native_client/src/include/portability.h"
      21                 : #include "native_client/src/include/portability_io.h"
      22                 : #include "native_client/src/public/secure_service.h"
      23                 : #include "native_client/src/shared/platform/nacl_log.h"
      24                 : #include "native_client/src/shared/platform/scoped_ptr_refcount.h"
      25                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      26                 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
      27                 : #include "native_client/src/trusted/desc/nrd_all_modules.h"
      28                 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
      29                 : #include "native_client/src/trusted/reverse_service/reverse_service.h"
      30                 : #include "native_client/src/trusted/sel_universal/pnacl_emu_handler.h"
      31                 : #include "native_client/src/trusted/sel_universal/reverse_emulate.h"
      32                 : #include "native_client/src/trusted/sel_universal/replay_handler.h"
      33                 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
      34                 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
      35                 : 
      36                 : #include "native_client/src/trusted/nonnacl_util/launcher_factory.h"
      37                 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher_zygote.h"
      38                 : 
      39                 : using std::ifstream;
      40                 : using std::map;
      41                 : using std::string;
      42                 : using std::vector;
      43                 : using nacl::DescWrapper;
      44                 : 
      45                 : // TODO(robertm): add explanation for flags
      46                 : static const char* kUsage =
      47                 :     "Usage:\n"
      48                 :     "\n"
      49                 :     "sel_universal <sel_universal_arg> <sel_ldr_arg>* [-- <nexe> <nexe_arg>*]\n"
      50                 :     "\n"
      51                 :     "Exactly one nexe argument is required.\n"
      52                 :     "After startup the user is prompted for interactive commands.\n"
      53                 :     "For sample commands have a look at: tests/srpc/srpc_basic_test.stdin\n"
      54                 :     "\n"
      55                 :     "sel_universal arguments are:\n"
      56                 :     "\n"
      57                 :     "  --help\n"
      58                 :     "  --event_record <file>\n"
      59                 :     "  --event_replay <file>\n"
      60                 :     "  --debug\n"
      61                 :     "  --abort_on_error\n"
      62                 :     "  --silence_nexe\n"
      63                 :     "  --command_prefix <prefix>\n"
      64                 :     "  --command_file <file>\n"
      65                 :     "  --var <tag> <value>\n"
      66                 :     "  --url_alias <url> <filename>\n"
      67                 :     "  --uses_reverse_service\n"
      68                 :     "  --no_app_channel\n"
      69                 :     "\n"
      70                 :     "The following sel_ldr arguments might be useful:\n"
      71                 :     "  -v                    increase verbosity\n"
      72                 :     "  -E NACL_SRPC_DEBUG=1  even more verbosity for srpc debugging\n";
      73                 : 
      74                 : 
      75                 : // NOTE: this used to be stack allocated inside main which cause
      76                 : // problems on ARM (probably a tool chain bug).
      77                 : // NaClSrpcChannel is pretty big (> 256kB)
      78                 : static NaClSrpcChannel command_channel;
      79                 : static NaClSrpcChannel channel;
      80                 : 
      81                 : // variables set via command line
      82              14 : static map<string, string> initial_vars;
      83              28 : static vector<string> initial_commands;
      84                 : static bool abort_on_error = false;
      85                 : static bool silence_nexe = false;
      86              28 : static vector<string> command_prefix;
      87                 : static bool uses_reverse_service = false;
      88                 : static bool app_channel = true;
      89                 : 
      90                 : // When given argc and argv this function (a) extracts the nexe argument,
      91                 : // (b) populates sel_ldr_argv with sel_ldr arguments, and (c) populates
      92                 : // app_argv with nexe module args. Also see kUsage above for details.
      93                 : // It will call exit with codes 0 (help message) and 1 (incorrect args).
      94              14 : static nacl::string ProcessArguments(int argc,
      95              14 :                                      char* argv[],
      96              14 :                                      vector<nacl::string>* const sel_ldr_argv,
      97              14 :                                      vector<nacl::string>* const app_argv) {
      98              14 :   if (argc == 1) {
      99               0 :     printf("%s", kUsage);
     100               0 :     exit(0);
     101                 :   }
     102                 : 
     103              14 :   int debug_level = 0;
     104                 :   // Extract sel_universal arguments and transfer the rest to sel_ldr_argv
     105              14 :   nacl::string app_name;
     106             116 :   for (int i = 1; i < argc; i++) {
     107              88 :     const string flag(argv[i]);
     108              88 :     if (flag == "--help") {
     109               0 :       printf("%s", kUsage);
     110               0 :       exit(0);
     111              88 :     } else if (flag == "--debug") {
     112               0 :       ++debug_level;
     113              88 :     } else if (flag == "--abort_on_error") {
     114               0 :       abort_on_error = true;
     115              88 :     } else if (flag == "--silence_nexe") {
     116               0 :       silence_nexe = true;
     117              88 :     } else if (flag == "--command_prefix") {
     118               0 :       if (argc <= i + 1) {
     119               0 :         NaClLog(LOG_FATAL,
     120                 :                 "not enough args for --command_prefix option\n");
     121               0 :       }
     122               0 :       ++i;
     123               0 :       command_prefix.push_back(argv[i]);
     124              88 :     } else if (flag == "--command_file") {
     125               6 :       if (argc <= i + 1) {
     126               0 :         NaClLog(LOG_FATAL, "not enough args for --command_file option\n");
     127               0 :       }
     128               6 :       NaClLog(LOG_INFO, "reading commands from %s\n", argv[i + 1]);
     129               6 :       ifstream f;
     130               6 :       f.open(argv[i + 1]);
     131               6 :       ++i;
     132              88 :       while (!f.eof()) {
     133              35 :         string s;
     134              35 :         getline(f, s);
     135              35 :         initial_commands.push_back(s);
     136              70 :       }
     137               6 :       f.close();
     138               6 :       NaClLog(LOG_INFO, "total commands now: %d\n",
     139              12 :               static_cast<int>(initial_commands.size()));
     140              88 :     } else if (flag == "--var") {
     141               2 :       if (argc <= i + 2) {
     142               0 :         NaClLog(LOG_FATAL, "not enough args for --var option\n");
     143               0 :       }
     144                 : 
     145               4 :       const string tag = string(argv[i + 1]);
     146               4 :       const string val = string(argv[i + 2]);
     147               2 :       i += 2;
     148               4 :       initial_vars[tag] = val;
     149              78 :     } else if (flag == "--uses_reverse_service") {
     150               5 :       uses_reverse_service = true;
     151              67 :     } else if (flag == "--no_app_channel") {
     152               3 :       app_channel = false;
     153              59 :     } else if (flag == "--") {
     154                 :       // Done processing sel_ldr args.  The first argument after '--' is the
     155                 :       // nexe.
     156              14 :       i++;
     157              42 :       if (app_name == "" && i < argc) {
     158              14 :         app_name = argv[i++];
     159              14 :       }
     160                 :       // The remaining arguments are passed to the executable.
     161              28 :       for (; i < argc; i++) {
     162               0 :         app_argv->push_back(argv[i]);
     163               0 :       }
     164              14 :     } else {
     165                 :       // NOTE: most sel_ldr args start with a single hyphen so there is not
     166                 :       // much confusion with sel_universal args. But this remains a hack.
     167              56 :       sel_ldr_argv->push_back(argv[i]);
     168                 :     }
     169              88 :   }
     170                 : 
     171              14 :   if (debug_level > 0) {
     172               0 :     NaClLogSetVerbosity(debug_level);
     173               0 :   }
     174                 : 
     175              28 :   if (app_name == "") {
     176               0 :     NaClLog(LOG_FATAL, "missing app\n");
     177               0 :   }
     178                 : 
     179              14 :   return app_name;
     180              28 : }
     181                 : 
     182                 : 
     183               2 : static bool HandlerHardShutdown(NaClCommandLoop* ncl,
     184               2 :                                const vector<string>& args) {
     185               4 :   UNREFERENCED_PARAMETER(ncl);
     186               4 :   UNREFERENCED_PARAMETER(args);
     187               2 :   NaClSrpcInvokeBySignature(&command_channel,
     188                 :                             NACL_SECURE_SERVICE_HARD_SHUTDOWN);
     189               2 :   return true;
     190                 : }
     191                 : 
     192                 : 
     193               0 : static bool HandlerForceShutdown(NaClCommandLoop* ncl,
     194               0 :                                 const vector<string>& args) {
     195               0 :   UNREFERENCED_PARAMETER(ncl);
     196               0 :   UNREFERENCED_PARAMETER(args);
     197               0 :   NaClSrpcDtor(&command_channel);
     198               0 :   return true;
     199                 : }
     200                 : 
     201                 : 
     202              14 : int raii_main(int argc, char* argv[]) {
     203                 :   // Get the arguments to sed_ldr and the nexe module
     204              28 :   vector<nacl::string> sel_ldr_argv;
     205              28 :   vector<nacl::string> app_argv;
     206              14 :   nacl::string app_name =
     207              14 :     ProcessArguments(argc, argv, &sel_ldr_argv, &app_argv);
     208                 : 
     209              14 :   if (silence_nexe) {
     210                 :     // redirect stdout/stderr in the nexe to /dev/null
     211               0 :     std::stringstream ss_stdout;
     212               0 :     std::stringstream ss_stderr;
     213                 : 
     214               0 :     int fd = open(PORTABLE_DEV_NULL, O_RDWR);
     215               0 :     sel_ldr_argv.push_back("-w");
     216               0 :     ss_stdout << "1:" << fd;
     217               0 :     sel_ldr_argv.push_back(ss_stdout.str());
     218               0 :     sel_ldr_argv.push_back("-w");
     219               0 :     ss_stderr << "2:" << fd;
     220               0 :     sel_ldr_argv.push_back(ss_stderr.str());
     221               0 :   }
     222              14 :   nacl::Zygote zygote;
     223              28 :   if (!zygote.Init()) {
     224               0 :     NaClLog(LOG_FATAL, "sel_universal: cannot spawn zygote process\n");
     225               0 :   }
     226              14 :   NaClLog(4, "sel_universal: zygote.Init() okay\n");
     227              14 :   nacl::SelLdrLauncherStandaloneFactory launcher_factory(&zygote);
     228              14 :   NaClLog(4, "sel_universal: launcher_factory ctor() okay\n");
     229                 : 
     230                 :   // Start sel_ldr with the given application and arguments.
     231              28 :   nacl::scoped_ptr<nacl::SelLdrLauncherStandalone> launcher(
     232              14 :       launcher_factory.MakeSelLdrLauncherStandalone());
     233              14 :   NaClLog(4, "sel_universal: MakeSelLdrLauncherStandalone() okay\n");
     234              14 :   nacl::DescWrapperFactory factory;  // DescWrapper "namespace"
     235                 : 
     236              42 :   if (!launcher->StartViaCommandLine(command_prefix, sel_ldr_argv, app_argv)) {
     237               0 :     NaClLog(LOG_FATAL, "sel_universal: Failed to launch sel_ldr\n");
     238               0 :   }
     239                 : 
     240              42 :   if (!launcher->SetupCommand(&command_channel)) {
     241               0 :     NaClLog(LOG_ERROR, "sel_universal: set up command failed\n");
     242               0 :     exit(1);
     243                 :   }
     244                 : 
     245              42 :   DescWrapper *host_file = factory.OpenHostFile(app_name.c_str(), O_RDONLY, 0);
     246              14 :   if (NULL == host_file) {
     247               0 :     NaClLog(LOG_ERROR, "Could not open %s\n", app_name.c_str());
     248               0 :     exit(1);
     249                 :   }
     250                 : 
     251              42 :   if (!launcher->LoadModule(&command_channel, host_file)) {
     252               0 :     NaClLog(LOG_ERROR, "sel_universal: load module failed\n");
     253               0 :     exit(1);
     254                 :   }
     255                 : 
     256              42 :   delete host_file;
     257                 : 
     258              14 :   if (uses_reverse_service) {
     259              10 :     ReverseEmulateInit(&command_channel, launcher.get(), &launcher_factory,
     260                 :         command_prefix, sel_ldr_argv);
     261               5 :   }
     262                 : 
     263              42 :   if (!launcher->StartModule(&command_channel)) {
     264               0 :     NaClLog(LOG_ERROR,
     265                 :             "sel_universal: start module failed\n");
     266               0 :     exit(1);
     267                 :   }
     268                 : 
     269              14 :   if (app_channel) {
     270              33 :     if (!launcher->SetupAppChannel(&channel)) {
     271               1 :       NaClLog(LOG_ERROR,
     272                 :               "sel_universal: set up app channel failed\n");
     273               0 :       exit(1);
     274                 :     }
     275              10 :   }
     276                 : 
     277              26 :   NaClCommandLoop loop(channel.client,
     278                 :                        &channel,
     279              39 :                        launcher->socket_addr()->desc());
     280                 : 
     281                 :   // Sample built-in commands accepted by sel_universal:
     282                 :   //
     283                 :   // install_upcalls service
     284                 :   // show_variables
     285                 :   // show_descriptors
     286                 :   // rpc <name> <in-arg>* "*" <out-arg>*
     287                 :   //
     288                 :   // TODO(robertm): add more documentation
     289                 :   //
     290                 :   // More custom command handlers are installed below:
     291                 : 
     292              52 :   loop.AddHandler("replay_activate", HandlerReplayActivate);
     293              52 :   loop.AddHandler("replay", HandlerReplay);
     294              52 :   loop.AddHandler("replay_unused", HandlerUnusedReplays);
     295                 : 
     296                 :   // possible platform specific stuff
     297              52 :   loop.AddHandler("readonly_file", HandlerReadonlyFile);
     298              52 :   loop.AddHandler("readwrite_file", HandlerReadwriteFile);
     299              52 :   loop.AddHandler("readwrite_quota_file", HandlerReadwriteFileQuota);
     300              52 :   loop.AddHandler("sleep", HandlerSleep);
     301              52 :   loop.AddHandler("save_to_file", HandlerSaveToFile);
     302              52 :   loop.AddHandler("load_from_file", HandlerLoadFromFile);
     303              52 :   loop.AddHandler("file_size", HandlerFileSize);
     304              52 :   loop.AddHandler("sync_socket_create", HandlerSyncSocketCreate);
     305              52 :   loop.AddHandler("sync_socket_write", HandlerSyncSocketWrite);
     306                 :   // new names
     307              52 :   loop.AddHandler("pnacl_emu_initialize", HandlerPnaclEmuInitialize);
     308              52 :   loop.AddHandler("pnacl_emu_add_varname_mapping",
     309                 :                   HandlerPnaclEmuAddVarnameMapping);
     310              52 :   loop.AddHandler("reverse_service_add_manifest_mapping",
     311                 :                   HandlerReverseEmuAddManifestMapping);
     312              52 :   loop.AddHandler("reverse_service_dump_manifest_mappings",
     313                 :                   HandlerReverseEmuDumpManifestMappings);
     314              52 :   loop.AddHandler("stream_file", HandlerPnaclFileStream);
     315              52 :   loop.AddHandler("wait_for_exit", HandlerWaitForExit);
     316                 : 
     317              52 :   loop.AddHandler("hard_shutdown", HandlerHardShutdown);
     318              52 :   loop.AddHandler("force_shutdown", HandlerForceShutdown);
     319                 : 
     320              13 :   NaClLog(1, "populating initial vars\n");
     321              26 :   for (map<string, string>::iterator it = initial_vars.begin();
     322              45 :        it != initial_vars.end();
     323               4 :        ++it) {
     324              14 :     loop.SetVariable(it->first, it->second);
     325               2 :   }
     326                 : 
     327              26 :   const bool success = initial_commands.size() > 0 ?
     328              12 :                        loop.ProcessCommands(initial_commands) :
     329              27 :                        loop.StartInteractiveLoop(abort_on_error);
     330                 : 
     331                 :   // Close the connections to sel_ldr.
     332              13 :   NaClSrpcDtor(&command_channel);
     333              13 :   NaClSrpcDtor(&channel);
     334                 : 
     335              13 :   if (uses_reverse_service) {
     336               5 :     ReverseEmulateFini();
     337               5 :   }
     338                 : 
     339              13 :   return success ? 0 : -1;
     340             104 : }
     341                 : 
     342              14 : int main(int argc, char* argv[]) {
     343                 :   // Descriptor transfer requires the following
     344              14 :   NaClSrpcModuleInit();
     345              14 :   NaClNrdAllModulesInit();
     346                 : 
     347              14 :   int exit_status = raii_main(argc, argv);
     348                 : 
     349              14 :   NaClSrpcModuleFini();
     350              14 :   NaClNrdAllModulesFini();
     351                 : 
     352              14 :   return exit_status;
     353                 : }

Generated by: LCOV version 1.7