LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_main_chrome.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 128 98 76.6 %
Date: 2014-07-02 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/public/chrome_main.h"
       8                 : 
       9                 : #include "native_client/src/include/portability.h"
      10                 : #include "native_client/src/include/portability_io.h"
      11                 : #include "native_client/src/include/portability_sockets.h"
      12                 : 
      13                 : #if NACL_OSX
      14                 : #include <crt_externs.h>
      15                 : #endif
      16                 : 
      17                 : #include <stdio.h>
      18                 : #include <string.h>
      19                 : 
      20                 : #include "native_client/src/include/nacl_macros.h"
      21                 : #include "native_client/src/public/nacl_app.h"
      22                 : #include "native_client/src/shared/platform/nacl_check.h"
      23                 : #include "native_client/src/shared/platform/nacl_exit.h"
      24                 : #include "native_client/src/shared/platform/nacl_log.h"
      25                 : #include "native_client/src/shared/platform/nacl_secure_random.h"
      26                 : #include "native_client/src/shared/platform/nacl_sync.h"
      27                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      28                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      29                 : #include "native_client/src/trusted/fault_injection/fault_injection.h"
      30                 : #include "native_client/src/trusted/gio/gio_nacl_desc.h"
      31                 : #include "native_client/src/trusted/service_runtime/env_cleanser.h"
      32                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      33                 : #include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
      34                 : #include "native_client/src/trusted/service_runtime/nacl_app.h"
      35                 : #include "native_client/src/trusted/service_runtime/nacl_bootstrap_channel_error_reporter.h"
      36                 : #include "native_client/src/trusted/service_runtime/nacl_error_log_hook.h"
      37                 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
      38                 : #include "native_client/src/trusted/service_runtime/nacl_debug_init.h"
      39                 : #include "native_client/src/trusted/service_runtime/nacl_signal.h"
      40                 : #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h"
      41                 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
      42                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      43                 : #include "native_client/src/trusted/service_runtime/sel_main_common.h"
      44                 : #include "native_client/src/trusted/service_runtime/sel_qualify.h"
      45                 : #include "native_client/src/trusted/service_runtime/win/exception_patch/ntdll_patch.h"
      46                 : #include "native_client/src/trusted/validator/validation_metadata.h"
      47                 : 
      48                 : static int g_initialized = 0;
      49                 : 
      50                 : #if NACL_LINUX || NACL_OSX
      51               0 : void NaClChromeMainSetUrandomFd(int urandom_fd) {
      52               0 :   CHECK(!g_initialized);
      53               0 :   NaClSecureRngModuleSetUrandomFd(urandom_fd);
      54               0 : }
      55                 : #endif
      56                 : 
      57               4 : void NaClChromeMainInit(void) {
      58               4 :   CHECK(!g_initialized);
      59               4 :   NaClAllModulesInit();
      60               4 :   g_initialized = 1;
      61               4 : }
      62                 : 
      63               4 : struct NaClChromeMainArgs *NaClChromeMainArgsCreate(void) {
      64                 :   struct NaClChromeMainArgs *args;
      65                 : 
      66               4 :   CHECK(g_initialized);
      67               4 :   args = malloc(sizeof(*args));
      68               4 :   if (args == NULL)
      69               0 :     return NULL;
      70               4 :   args->imc_bootstrap_handle = NACL_INVALID_HANDLE;
      71               4 :   args->irt_fd = -1;
      72               4 :   args->enable_exception_handling = 0;
      73               4 :   args->enable_debug_stub = 0;
      74               4 :   args->enable_dyncode_syscalls = 1;
      75               4 :   args->pnacl_mode = 0;
      76               4 :   args->initial_nexe_max_code_bytes = 0;  /* No limit */
      77                 : #if NACL_LINUX || NACL_OSX
      78               4 :   args->debug_stub_server_bound_socket_fd = NACL_INVALID_SOCKET;
      79                 : #endif
      80                 : #if NACL_WINDOWS
      81                 :   args->debug_stub_server_port_selected_handler_func = NULL;
      82                 : #endif
      83               4 :   args->create_memory_object_func = NULL;
      84               4 :   args->validation_cache = NULL;
      85                 : #if NACL_WINDOWS
      86                 :   args->broker_duplicate_handle_func = NULL;
      87                 :   args->attach_debug_exception_handler_func = NULL;
      88                 : #endif
      89                 : #if NACL_LINUX || NACL_OSX
      90               4 :   args->number_of_cores = -1;  /* unknown */
      91                 : #endif
      92                 : #if NACL_LINUX
      93               4 :   args->prereserved_sandbox_size = 0;
      94                 : #endif
      95               4 :   args->nexe_desc = NULL;
      96               4 :   return args;
      97                 : }
      98                 : 
      99                 : static char kFakeIrtName[] = "\0IRT";
     100                 : 
     101               4 : static void NaClLoadIrt(struct NaClApp *nap, int irt_fd) {
     102                 :   int file_desc;
     103                 :   struct NaClDesc *nd;
     104                 :   struct NaClValidationMetadata metadata;
     105                 :   NaClErrorCode errcode;
     106                 : 
     107               4 :   if (irt_fd == -1) {
     108               0 :     NaClLog(LOG_FATAL, "NaClLoadIrt: Integrated runtime (IRT) not present.\n");
     109                 :   }
     110                 : 
     111               4 :   file_desc = DUP(irt_fd);
     112               4 :   if (file_desc < 0) {
     113               0 :     NaClLog(LOG_FATAL, "NaClLoadIrt: Failed to dup() file descriptor\n");
     114                 :   }
     115                 : 
     116                 :   /*
     117                 :    * For the IRT use a fake file name with null characters at the begining and
     118                 :    * the end of the name.
     119                 :    */
     120                 :   /* TODO(ncbray) plumb the real filename in from Chrome. */
     121               4 :   NaClMetadataFromFDCtor(&metadata, file_desc,
     122                 :                          kFakeIrtName, sizeof(kFakeIrtName));
     123                 : 
     124               4 :   nd = NaClDescIoDescFromDescAllocCtor(file_desc, NACL_ABI_O_RDONLY);
     125               4 :   if (NULL == nd) {
     126               0 :     NaClLog(LOG_FATAL,
     127                 :             "NaClLoadIrt: failed to construct NaClDesc object from"
     128                 :             " descriptor\n");
     129                 :   }
     130                 : 
     131               4 :   errcode = NaClMainLoadIrt(nap, nd, &metadata);
     132               4 :   if (errcode != LOAD_OK) {
     133               0 :     NaClLog(LOG_FATAL,
     134                 :             "NaClLoadIrt: Failed to load the integrated runtime (IRT): %s\n",
     135                 :             NaClErrorString(errcode));
     136                 :   }
     137                 : 
     138               4 :   NaClMetadataDtor(&metadata);
     139               4 :   NaClDescUnref(nd);
     140               4 : }
     141                 : 
     142               4 : static int LoadApp(struct NaClApp *nap, struct NaClChromeMainArgs *args) {
     143               4 :   NaClErrorCode errcode = LOAD_OK;
     144                 :   int skip_qualification;
     145                 : 
     146               4 :   CHECK(g_initialized);
     147                 : 
     148               4 :   NaClBootstrapChannelErrorReporterInit();
     149               4 :   NaClErrorLogHookInit(NaClBootstrapChannelErrorReporter, nap);
     150                 : 
     151                 :   /* Allow or disallow dyncode API based on args. */
     152               4 :   nap->enable_dyncode_syscalls = args->enable_dyncode_syscalls;
     153               4 :   nap->initial_nexe_max_code_bytes = args->initial_nexe_max_code_bytes;
     154               4 :   nap->pnacl_mode = args->pnacl_mode;
     155                 : 
     156                 : #if NACL_LINUX
     157               4 :   g_prereserved_sandbox_size = args->prereserved_sandbox_size;
     158                 : #endif
     159                 : #if NACL_LINUX || NACL_OSX
     160                 :   /*
     161                 :    * Overwrite value of sc_nprocessors_onln set in NaClAppCtor.  In
     162                 :    * the Chrome embedding, the outer sandbox was already enabled when
     163                 :    * the NaClApp Ctor was invoked, so a bogus value was written in
     164                 :    * sc_nprocessors_onln.
     165                 :    */
     166               4 :   if (-1 != args->number_of_cores) {
     167               0 :     nap->sc_nprocessors_onln = args->number_of_cores;
     168                 :   }
     169                 : #endif
     170                 : 
     171               4 :   if (args->create_memory_object_func != NULL)
     172               0 :     NaClSetCreateMemoryObjectFunc(args->create_memory_object_func);
     173                 : 
     174                 :   /* Inject the validation caching interface, if it exists. */
     175               4 :   nap->validation_cache = args->validation_cache;
     176                 : 
     177                 : #if NACL_WINDOWS
     178                 :   if (args->broker_duplicate_handle_func != NULL)
     179                 :     NaClSetBrokerDuplicateHandleFunc(args->broker_duplicate_handle_func);
     180                 : #endif
     181                 : 
     182               4 :   NaClAppInitialDescriptorHookup(nap);
     183                 : 
     184                 :   /*
     185                 :    * NACL_SERVICE_PORT_DESCRIPTOR and NACL_SERVICE_ADDRESS_DESCRIPTOR
     186                 :    * are 3 and 4.
     187                 :    */
     188                 : 
     189                 :   /*
     190                 :    * in order to report load error to the browser plugin through the
     191                 :    * secure command channel, we do not immediate jump to cleanup code
     192                 :    * on error.  rather, we continue processing (assuming earlier
     193                 :    * errors do not make it inappropriate) until the secure command
     194                 :    * channel is set up, and then bail out.
     195                 :    */
     196                 : 
     197                 :   /*
     198                 :    * Ensure this operating system platform is supported.
     199                 :    */
     200               4 :   skip_qualification = getenv("NACL_DANGEROUS_SKIP_QUALIFICATION_TEST") != NULL;
     201               4 :   if (skip_qualification) {
     202               0 :     fprintf(stderr, "PLATFORM QUALIFICATION DISABLED - "
     203                 :         "Native Client's sandbox will be unreliable!\n");
     204                 :   } else {
     205               4 :     errcode = NACL_FI_VAL("pq", NaClErrorCode,
     206                 :                           NaClRunSelQualificationTests());
     207               4 :     if (LOAD_OK != errcode) {
     208               0 :       nap->module_load_status = errcode;
     209               0 :       fprintf(stderr, "Error while loading in SelMain: %s\n",
     210                 :               NaClErrorString(errcode));
     211                 :     }
     212                 :   }
     213                 : 
     214                 :   /*
     215                 :    * Patch the Windows exception dispatcher to be safe in the case
     216                 :    * of faults inside x86-64 sandboxed code.  The sandbox is not
     217                 :    * secure on 64-bit Windows without this.
     218                 :    */
     219                 : #if (NACL_WINDOWS && NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && \
     220                 :      NACL_BUILD_SUBARCH == 64)
     221                 :   NaClPatchWindowsExceptionDispatcher();
     222                 : #endif
     223               4 :   NaClSignalTestCrashOnStartup();
     224                 : 
     225               4 :   nap->enable_exception_handling = args->enable_exception_handling;
     226                 : 
     227               4 :   if (args->enable_exception_handling || args->enable_debug_stub) {
     228                 : #if NACL_LINUX
     229                 :     /* NaCl's signal handler is always enabled on Linux. */
     230                 : #elif NACL_OSX
     231                 :     if (!NaClInterceptMachExceptions()) {
     232                 :       NaClLog(LOG_FATAL, "LoadApp: Failed to set up Mach exception handler\n");
     233                 :     }
     234                 : #elif NACL_WINDOWS
     235                 :     nap->attach_debug_exception_handler_func =
     236                 :         args->attach_debug_exception_handler_func;
     237                 : #else
     238                 : # error Unknown host OS
     239                 : #endif
     240                 :   }
     241                 : #if NACL_LINUX
     242               4 :   NaClSignalHandlerInit();
     243                 : #endif
     244                 : 
     245                 :   /* Give debuggers a well known point at which xlate_base is known.  */
     246               4 :   NaClGdbHook(nap);
     247                 : 
     248               4 :   NaClCreateServiceSocket(nap);
     249                 :   /*
     250                 :    * LOG_FATAL errors that occur before NaClSetUpBootstrapChannel will
     251                 :    * not be reported via the crash log mechanism (for Chromium
     252                 :    * embedding of NaCl, shown in the JavaScript console).
     253                 :    *
     254                 :    * Some errors, such as due to NaClRunSelQualificationTests, do not
     255                 :    * trigger a LOG_FATAL but instead set module_load_status to be sent
     256                 :    * in the start_module RPC reply.  Log messages associated with such
     257                 :    * errors would be seen, since NaClSetUpBootstrapChannel will get
     258                 :    * called.
     259                 :    */
     260               4 :   NaClSetUpBootstrapChannel(nap, args->imc_bootstrap_handle);
     261                 : 
     262               4 :   if (args->nexe_desc) {
     263               2 :     NaClAppLoadModule(nap, args->nexe_desc, NULL, NULL);
     264               2 :     NaClDescUnref(args->nexe_desc);
     265               2 :     args->nexe_desc = NULL;
     266                 :   }
     267                 : 
     268               4 :   NACL_FI_FATAL("BeforeSecureCommandChannel");
     269                 :   /*
     270                 :    * Spawns a thread that uses the command channel.
     271                 :    * Hereafter any changes to nap should be done while holding locks.
     272                 :    */
     273               4 :   NaClSecureCommandChannel(nap);
     274                 : 
     275               4 :   NaClLog(4, "NaClSecureCommandChannel has spawned channel\n");
     276                 : 
     277               4 :   NaClLog(4, "secure service = %"NACL_PRIxPTR"\n",
     278               4 :           (uintptr_t) nap->secure_service);
     279               4 :   NACL_FI_FATAL("BeforeWaitForStartModule");
     280                 : 
     281               4 :   if (NULL != nap->secure_service) {
     282                 :     NaClErrorCode start_result;
     283                 :     /*
     284                 :      * wait for start_module RPC call on secure channel thread.
     285                 :      */
     286               4 :     start_result = NaClWaitForStartModuleCommand(nap);
     287               4 :     if (LOAD_OK == errcode) {
     288               4 :       errcode = start_result;
     289                 :     }
     290                 :   }
     291                 : 
     292               4 :   NACL_FI_FATAL("BeforeLoadIrt");
     293                 : 
     294                 :   /*
     295                 :    * error reporting done; can quit now if there was an error earlier.
     296                 :    */
     297               4 :   if (LOAD_OK != errcode) {
     298               0 :     goto done;
     299                 :   }
     300                 : 
     301                 :   /*
     302                 :    * Load the integrated runtime (IRT) library.
     303                 :    */
     304               4 :   if (args->irt_fd != -1) {
     305               4 :     NaClLoadIrt(nap, args->irt_fd);
     306                 :   }
     307                 : 
     308               4 :   if (NACL_FI_ERROR_COND("LaunchServiceThreads",
     309                 :                          !NaClAppLaunchServiceThreads(nap))) {
     310               0 :     NaClLog(LOG_FATAL, "Launch service threads failed\n");
     311                 :   }
     312                 : 
     313               4 :   if (args->enable_debug_stub) {
     314                 : #if NACL_LINUX || NACL_OSX
     315               0 :     if (args->debug_stub_server_bound_socket_fd != NACL_INVALID_SOCKET) {
     316               0 :       NaClDebugSetBoundSocket(args->debug_stub_server_bound_socket_fd);
     317                 :     }
     318                 : #endif
     319               0 :     if (!NaClDebugInit(nap)) {
     320               0 :       goto done;
     321                 :     }
     322                 : #if NACL_WINDOWS
     323                 :     if (NULL != args->debug_stub_server_port_selected_handler_func) {
     324                 :       args->debug_stub_server_port_selected_handler_func(nap->debug_stub_port);
     325                 :     }
     326                 : #endif
     327                 :   }
     328                 : 
     329               4 :   free(args);
     330               4 :   return LOAD_OK;
     331                 : 
     332                 : done:
     333               0 :   fflush(stdout);
     334                 : 
     335                 :   /*
     336                 :    * If there is a secure command channel, we sent an RPC reply with
     337                 :    * the reason that the nexe was rejected.  If we exit now, that
     338                 :    * reply may still be in-flight and the various channel closure (esp
     339                 :    * reverse channel) may be detected first.  This would result in a
     340                 :    * crash being reported, rather than the error in the RPC reply.
     341                 :    * Instead, we wait for the hard-shutdown on the command channel.
     342                 :    */
     343               0 :   if (LOAD_OK != errcode) {
     344               0 :     NaClBlockIfCommandChannelExists(nap);
     345                 :   } else {
     346                 :     /*
     347                 :      * Don't return LOAD_OK if we had some failure loading.
     348                 :      */
     349               0 :     errcode = LOAD_INTERNAL;
     350                 :   }
     351               0 :   return errcode;
     352                 : }
     353                 : 
     354               4 : static void StartApp(struct NaClApp *nap) {
     355               4 :   int ac = 1;
     356                 :   char *av[1];
     357                 :   int ret_code;
     358                 :   const char **envp;
     359                 :   struct NaClEnvCleanser env_cleanser;
     360                 : 
     361                 : #if NACL_OSX
     362                 :   /* Mac dynamic libraries cannot access the environ variable directly. */
     363                 :   envp = (const char **) *_NSGetEnviron();
     364                 : #else
     365                 :   /* Overzealous code style check is overzealous. */
     366                 :   /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */
     367                 :   extern char **environ;
     368               4 :   envp = (const char **) environ;
     369                 : #endif
     370                 : 
     371               4 :   NACL_FI_FATAL("BeforeEnvCleanserCtor");
     372                 : 
     373               4 :   NaClEnvCleanserCtor(&env_cleanser, 1);
     374               4 :   if (!NaClEnvCleanserInit(&env_cleanser, envp, NULL)) {
     375               0 :     NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n");
     376                 :   }
     377                 : 
     378                 :   /* to be passed to NaClMain, eventually... */
     379               4 :   av[0] = "NaClMain";
     380                 : 
     381               4 :   if (NACL_FI_ERROR_COND(
     382                 :           "CreateMainThread",
     383                 :           !NaClCreateMainThread(nap, ac, av,
     384                 :                                 NaClEnvCleanserEnvironment(&env_cleanser)))) {
     385               0 :     NaClLog(LOG_FATAL, "creating main thread failed\n");
     386                 :   }
     387               4 :   NACL_FI_FATAL("BeforeEnvCleanserDtor");
     388                 : 
     389               4 :   NaClEnvCleanserDtor(&env_cleanser);
     390                 : 
     391               4 :   ret_code = NaClWaitForMainThreadToExit(nap);
     392                 : 
     393               4 :   if (NACL_ABI_WIFEXITED(nap->exit_status)) {
     394                 :     /*
     395                 :      * Under Chrome, a call to _exit() often indicates that something
     396                 :      * has gone awry, so we report it here to aid debugging.
     397                 :      *
     398                 :      * This conditional does not run if the NaCl process was
     399                 :      * terminated forcibly, which is the normal case under Chrome.
     400                 :      * This forcible exit is triggered by the renderer closing the
     401                 :      * trusted SRPC channel, which we record as NACL_ABI_SIGKILL
     402                 :      * internally.
     403                 :      */
     404               4 :     NaClLog(LOG_INFO, "NaCl untrusted code called _exit(0x%x)\n", ret_code);
     405                 :   }
     406                 : 
     407                 :   /*
     408                 :    * exit_group or equiv kills any still running threads while module
     409                 :    * addr space is still valid.  otherwise we'd have to kill threads
     410                 :    * before we clean up the address space.
     411                 :    */
     412               4 :   NaClExit(ret_code);
     413               0 : }
     414                 : 
     415               4 : void NaClChromeMainStartApp(struct NaClApp *nap,
     416                 :                             struct NaClChromeMainArgs *args) {
     417               4 :   if (LoadApp(nap, args) != 0)
     418               0 :     NaClExit(1);
     419               4 :   StartApp(nap);
     420               0 : }

Generated by: LCOV version 1.7