LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_ldr.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 572 462 80.8 %
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 <string.h>
       8                 : 
       9                 : /*
      10                 :  * NaCl Simple/secure ELF loader (NaCl SEL).
      11                 :  */
      12                 : #include "native_client/src/include/portability.h"
      13                 : #include "native_client/src/include/portability_io.h"
      14                 : #include "native_client/src/include/portability_string.h"
      15                 : #include "native_client/src/include/nacl_macros.h"
      16                 : 
      17                 : #include "native_client/src/public/desc_metadata_types.h"
      18                 : #include "native_client/src/public/nacl_app.h"
      19                 : #include "native_client/src/public/secure_service.h"
      20                 : 
      21                 : #include "native_client/src/shared/gio/gio.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_sync.h"
      26                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      27                 : #include "native_client/src/shared/platform/nacl_time.h"
      28                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      29                 : 
      30                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      31                 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
      32                 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
      33                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      34                 : #include "native_client/src/trusted/desc/nrd_xfer.h"
      35                 : #include "native_client/src/trusted/desc_cacheability/desc_cacheability.h"
      36                 : #include "native_client/src/trusted/fault_injection/fault_injection.h"
      37                 : #include "native_client/src/trusted/fault_injection/test_injection.h"
      38                 : #include "native_client/src/trusted/gio/gio_nacl_desc.h"
      39                 : #include "native_client/src/trusted/gio/gio_shm.h"
      40                 : #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree_intern.h"
      41                 : #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
      42                 : #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
      43                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      44                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      45                 : #include "native_client/src/trusted/service_runtime/include/sys/time.h"
      46                 : #include "native_client/src/trusted/service_runtime/nacl_app.h"
      47                 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
      48                 : #include "native_client/src/trusted/service_runtime/nacl_desc_effector_ldr.h"
      49                 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
      50                 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
      51                 : #include "native_client/src/trusted/service_runtime/nacl_reverse_quota_interface.h"
      52                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
      53                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
      54                 : #include "native_client/src/trusted/service_runtime/nacl_valgrind_hooks.h"
      55                 : #include "native_client/src/trusted/service_runtime/name_service/default_name_service.h"
      56                 : #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
      57                 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
      58                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      59                 : #include "native_client/src/trusted/service_runtime/sel_memory.h"
      60                 : #include "native_client/src/trusted/service_runtime/sel_ldr_thread_interface.h"
      61                 : #include "native_client/src/trusted/simple_service/nacl_simple_rservice.h"
      62                 : #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
      63                 : #include "native_client/src/trusted/threading/nacl_thread_interface.h"
      64                 : #include "native_client/src/trusted/validator/validation_cache.h"
      65                 : 
      66            1240 : static int IsEnvironmentVariableSet(char const *env_name) {
      67            1240 :   return NULL != getenv(env_name);
      68                 : }
      69                 : 
      70             310 : static int ShouldEnableDyncodeSyscalls(void) {
      71             310 :   return !IsEnvironmentVariableSet("NACL_DISABLE_DYNCODE_SYSCALLS");
      72                 : }
      73                 : 
      74             310 : static int ShouldEnableDynamicLoading(void) {
      75             310 :   return !IsEnvironmentVariableSet("NACL_DISABLE_DYNAMIC_LOADING");
      76                 : }
      77                 : 
      78             310 : int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
      79                 :                                 struct NaClSyscallTableEntry *table) {
      80                 :   struct NaClDescEffectorLdr  *effp;
      81                 : 
      82                 :   /* Zero-initialize in case we miss any fields below. */
      83             310 :   memset(nap, 0, sizeof(*nap));
      84                 : 
      85                 :   /* The validation cache will be injected later, if it exists. */
      86             310 :   nap->validation_cache = NULL;
      87                 : 
      88             310 :   nap->validator = NaClCreateValidator();
      89                 : 
      90                 :   /* Get the set of features that the CPU we're running on supports. */
      91                 :   /* These may be adjusted later in sel_main.c for fixed-feature CPU mode. */
      92             310 :   nap->cpu_features = (NaClCPUFeatures *) malloc(
      93             310 :       nap->validator->CPUFeatureSize);
      94             310 :   if (NULL == nap->cpu_features) {
      95               0 :     goto cleanup_none;
      96                 :   }
      97             310 :   nap->validator->GetCurrentCPUFeatures(nap->cpu_features);
      98             310 :   nap->fixed_feature_cpu_mode = 0;
      99                 : 
     100             310 :   nap->addr_bits = NACL_MAX_ADDR_BITS;
     101                 : 
     102             310 :   nap->stack_size = NACL_DEFAULT_STACK_MAX;
     103             310 :   nap->initial_nexe_max_code_bytes = 0;
     104                 : 
     105             310 :   nap->mem_start = 0;
     106                 : 
     107                 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
     108                 :      && NACL_BUILD_SUBARCH == 32)
     109             310 :   nap->pcrel_thunk = 0;
     110             310 :   nap->pcrel_thunk_end = 0;
     111                 : #endif
     112                 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
     113                 :      && NACL_BUILD_SUBARCH == 64)
     114                 :   nap->nacl_syscall_addr = 0;
     115                 :   nap->get_tls_fast_path1_addr = 0;
     116                 :   nap->get_tls_fast_path2_addr = 0;
     117                 : #endif
     118                 : 
     119             310 :   nap->static_text_end = 0;
     120             310 :   nap->dynamic_text_start = 0;
     121             310 :   nap->dynamic_text_end = 0;
     122             310 :   nap->rodata_start = 0;
     123             310 :   nap->data_start = 0;
     124             310 :   nap->data_end = 0;
     125                 : 
     126             310 :   nap->initial_entry_pt = 0;
     127             310 :   nap->user_entry_pt = 0;
     128                 : 
     129             310 :   if (!DynArrayCtor(&nap->threads, 2)) {
     130               0 :     goto cleanup_cpu_features;
     131                 :   }
     132             310 :   if (!DynArrayCtor(&nap->desc_tbl, 2)) {
     133               0 :     goto cleanup_threads;
     134                 :   }
     135             310 :   if (!NaClVmmapCtor(&nap->mem_map)) {
     136               0 :     goto cleanup_desc_tbl;
     137                 :   }
     138                 : 
     139             310 :   nap->mem_io_regions = (struct NaClIntervalMultiset *) malloc(
     140                 :       sizeof(struct NaClIntervalRangeTree));
     141             310 :   if (NULL == nap->mem_io_regions) {
     142               0 :     goto cleanup_mem_map;
     143                 :   }
     144                 : 
     145             310 :   if (!NaClIntervalRangeTreeCtor((struct NaClIntervalRangeTree *)
     146             310 :                                  nap->mem_io_regions)) {
     147               0 :     free(nap->mem_io_regions);
     148               0 :     nap->mem_io_regions = NULL;
     149               0 :     goto cleanup_mem_map;
     150                 :   }
     151                 : 
     152             310 :   effp = (struct NaClDescEffectorLdr *) malloc(sizeof *effp);
     153             310 :   if (NULL == effp) {
     154               0 :     goto cleanup_mem_io_regions;
     155                 :   }
     156             310 :   if (!NaClDescEffectorLdrCtor(effp, nap)) {
     157               0 :     goto cleanup_effp_free;
     158                 :   }
     159             310 :   nap->effp = (struct NaClDescEffector *) effp;
     160                 : 
     161             310 :   nap->enable_dyncode_syscalls = ShouldEnableDyncodeSyscalls();
     162             310 :   nap->use_shm_for_dynamic_text = ShouldEnableDynamicLoading();
     163             310 :   nap->text_shm = NULL;
     164             310 :   if (!NaClMutexCtor(&nap->dynamic_load_mutex)) {
     165               0 :     goto cleanup_effp_free;
     166                 :   }
     167             310 :   nap->dynamic_page_bitmap = NULL;
     168                 : 
     169             310 :   nap->dynamic_regions = NULL;
     170             310 :   nap->num_dynamic_regions = 0;
     171             310 :   nap->dynamic_regions_allocated = 0;
     172             310 :   nap->dynamic_delete_generation = 0;
     173                 : 
     174             310 :   nap->dynamic_mapcache_offset = 0;
     175             310 :   nap->dynamic_mapcache_size = 0;
     176             310 :   nap->dynamic_mapcache_ret = 0;
     177                 : 
     178             310 :   nap->service_port = NULL;
     179             310 :   nap->service_address = NULL;
     180             310 :   nap->secure_service_port = NULL;
     181             310 :   nap->secure_service_address = NULL;
     182             310 :   nap->bootstrap_channel = NULL;
     183             310 :   nap->secure_service = NULL;
     184             310 :   nap->main_exe_prevalidated = 0;
     185                 : 
     186             310 :   nap->kernel_service = NULL;
     187             310 :   nap->resource_phase = NACL_RESOURCE_PHASE_START;
     188             310 :   if (!NaClResourceNaClAppInit(&nap->resources, nap)) {
     189               0 :     goto cleanup_dynamic_load_mutex;
     190                 :   }
     191                 : 
     192             310 :   if (!NaClMutexCtor(&nap->mu)) {
     193               0 :     goto cleanup_dynamic_load_mutex;
     194                 :   }
     195             310 :   if (!NaClCondVarCtor(&nap->cv)) {
     196               0 :     goto cleanup_mu;
     197                 :   }
     198                 : 
     199                 : #if NACL_WINDOWS
     200                 :   nap->vm_hole_may_exist = 0;
     201                 :   nap->threads_launching = 0;
     202                 : #endif
     203                 : 
     204             310 :   nap->syscall_table = table;
     205                 : 
     206             310 :   nap->runtime_host_interface = NULL;
     207             310 :   nap->desc_quota_interface = NULL;
     208                 : 
     209             310 :   nap->module_initialization_state = NACL_MODULE_UNINITIALIZED;
     210             310 :   nap->module_load_status = LOAD_STATUS_UNKNOWN;
     211                 : 
     212             310 :   nap->name_service = (struct NaClNameService *) malloc(
     213                 :       sizeof *nap->name_service);
     214             310 :   if (NULL == nap->name_service) {
     215               0 :     goto cleanup_cv;
     216                 :   }
     217             310 :   if (!NaClNameServiceCtor(nap->name_service,
     218                 :                            NaClAddrSpSquattingThreadIfFactoryFunction,
     219                 :                            (void *) nap)) {
     220               0 :     free(nap->name_service);
     221               0 :     goto cleanup_cv;
     222                 :   }
     223             310 :   nap->name_service_conn_cap = NaClDescRef(nap->name_service->
     224                 :                                            base.base.bound_and_cap[1]);
     225             310 :   if (!NaClDefaultNameServiceInit(nap->name_service)) {
     226               0 :     goto cleanup_name_service;
     227                 :   }
     228                 : 
     229             310 :   nap->ignore_validator_result = 0;
     230             310 :   nap->skip_validator = 0;
     231             310 :   nap->validator_stub_out_mode = 0;
     232                 : 
     233             310 :   if (IsEnvironmentVariableSet("NACL_DANGEROUS_ENABLE_FILE_ACCESS")) {
     234               0 :     NaClInsecurelyBypassAllAclChecks();
     235               0 :     NaClLog(LOG_INFO, "DANGER: ENABLED FILE ACCESS\n");
     236                 :   }
     237                 : 
     238             310 :   nap->enable_list_mappings = 0;
     239             310 :   if (IsEnvironmentVariableSet("NACL_DANGEROUS_ENABLE_LIST_MAPPINGS")) {
     240                 :     /*
     241                 :      * This syscall is not actually know to be dangerous, but is not yet
     242                 :      * exposed by our public API.
     243                 :      */
     244               1 :     NaClLog(LOG_INFO, "DANGER: ENABLED LIST_MAPPINGS\n");
     245               1 :     nap->enable_list_mappings = 1;
     246                 :   }
     247             310 :   nap->pnacl_mode = 0;
     248                 : 
     249             310 :   if (!NaClMutexCtor(&nap->threads_mu)) {
     250               0 :     goto cleanup_name_service;
     251                 :   }
     252             310 :   nap->num_threads = 0;
     253             310 :   if (!NaClFastMutexCtor(&nap->desc_mu)) {
     254               0 :     goto cleanup_threads_mu;
     255                 :   }
     256                 : 
     257             310 :   nap->running = 0;
     258             310 :   nap->exit_status = -1;
     259                 : 
     260                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     261             310 :   nap->code_seg_sel = 0;
     262             310 :   nap->data_seg_sel = 0;
     263                 : #endif
     264                 : 
     265             310 :   nap->debug_stub_callbacks = NULL;
     266                 : #if NACL_WINDOWS
     267                 :   nap->debug_stub_port = 0;
     268                 : #endif
     269             310 :   nap->main_nexe_desc = NULL;
     270             310 :   nap->irt_nexe_desc = NULL;
     271                 : 
     272             310 :   nap->exception_handler = 0;
     273             310 :   if (!NaClMutexCtor(&nap->exception_mu)) {
     274               0 :     goto cleanup_desc_mu;
     275                 :   }
     276             310 :   nap->enable_exception_handling = 0;
     277                 : #if NACL_WINDOWS
     278                 :   nap->debug_exception_handler_state = NACL_DEBUG_EXCEPTION_HANDLER_NOT_STARTED;
     279                 :   nap->attach_debug_exception_handler_func = NULL;
     280                 : #endif
     281             310 :   nap->enable_faulted_thread_queue = 0;
     282             310 :   nap->faulted_thread_count = 0;
     283                 : #if NACL_WINDOWS
     284                 :   nap->faulted_thread_event = INVALID_HANDLE_VALUE;
     285                 : #else
     286             310 :   nap->faulted_thread_fd_read = -1;
     287             310 :   nap->faulted_thread_fd_write = -1;
     288                 : #endif
     289                 : 
     290                 : 
     291                 : #if NACL_LINUX || NACL_OSX
     292                 :   /*
     293                 :    * Try to pre-cache information that we can't obtain with the outer
     294                 :    * sandbox on.  If the outer sandbox has already been enabled, this
     295                 :    * will just set sc_nprocessors_onln to -1, and it is the
     296                 :    * responsibility of the caller to replace this with a sane value
     297                 :    * after the Ctor returns.
     298                 :    */
     299             310 :   nap->sc_nprocessors_onln = sysconf(_SC_NPROCESSORS_ONLN);
     300                 : #endif
     301                 : 
     302             310 :   if (!NaClMutexCtor(&nap->futex_wait_list_mu)) {
     303               0 :     goto cleanup_exception_mu;
     304                 :   }
     305             310 :   nap->futex_wait_list_head.next = &nap->futex_wait_list_head;
     306             310 :   nap->futex_wait_list_head.prev = &nap->futex_wait_list_head;
     307                 : 
     308             310 :   return 1;
     309                 : 
     310                 :  cleanup_exception_mu:
     311               0 :   NaClMutexDtor(&nap->exception_mu);
     312                 :  cleanup_desc_mu:
     313               0 :   NaClFastMutexDtor(&nap->desc_mu);
     314                 :  cleanup_threads_mu:
     315               0 :   NaClMutexDtor(&nap->threads_mu);
     316                 :  cleanup_name_service:
     317               0 :   NaClDescUnref(nap->name_service_conn_cap);
     318               0 :   NaClRefCountUnref((struct NaClRefCount *) nap->name_service);
     319                 :  cleanup_cv:
     320               0 :   NaClCondVarDtor(&nap->cv);
     321                 :  cleanup_mu:
     322               0 :   NaClMutexDtor(&nap->mu);
     323                 :  cleanup_dynamic_load_mutex:
     324               0 :   NaClMutexDtor(&nap->dynamic_load_mutex);
     325                 :  cleanup_effp_free:
     326               0 :   free(nap->effp);
     327                 :  cleanup_mem_io_regions:
     328               0 :   NaClIntervalMultisetDelete(nap->mem_io_regions);
     329               0 :   nap->mem_io_regions = NULL;
     330                 :  cleanup_mem_map:
     331               0 :   NaClVmmapDtor(&nap->mem_map);
     332                 :  cleanup_desc_tbl:
     333               0 :   DynArrayDtor(&nap->desc_tbl);
     334                 :  cleanup_threads:
     335               0 :   DynArrayDtor(&nap->threads);
     336                 :  cleanup_cpu_features:
     337               0 :   free(nap->cpu_features);
     338                 :  cleanup_none:
     339               0 :   return 0;
     340                 : }
     341                 : 
     342             309 : int NaClAppCtor(struct NaClApp *nap) {
     343             309 :   return NaClAppWithSyscallTableCtor(nap, nacl_syscall);
     344                 : }
     345                 : 
     346             283 : struct NaClApp *NaClAppCreate(void) {
     347             283 :   struct NaClApp *nap = malloc(sizeof(struct NaClApp));
     348             283 :   if (nap == NULL)
     349               0 :     NaClLog(LOG_FATAL, "Failed to allocate NaClApp\n");
     350             283 :   if (!NaClAppCtor(nap))
     351               0 :     NaClLog(LOG_FATAL, "NaClAppCtor() failed\n");
     352             283 :   return nap;
     353                 : }
     354                 : 
     355                 : /*
     356                 :  * unaligned little-endian load.  precondition: nbytes should never be
     357                 :  * more than 8.
     358                 :  */
     359               0 : static uint64_t NaClLoadMem(uintptr_t addr,
     360                 :                             size_t    user_nbytes) {
     361               0 :   uint64_t      value = 0;
     362                 : 
     363               0 :   CHECK(0 != user_nbytes && user_nbytes <= 8);
     364                 : 
     365                 :   do {
     366               0 :     value = value << 8;
     367               0 :     value |= ((uint8_t *) addr)[--user_nbytes];
     368               0 :   } while (user_nbytes > 0);
     369               0 :   return value;
     370                 : }
     371                 : 
     372                 : #define GENERIC_LOAD(bits) \
     373                 :   static uint ## bits ## _t NaClLoad ## bits(uintptr_t addr) { \
     374                 :     return (uint ## bits ## _t) NaClLoadMem(addr, sizeof(uint ## bits ## _t)); \
     375                 :   }
     376                 : 
     377                 : #if NACL_TARGET_SUBARCH == 32
     378               0 : GENERIC_LOAD(32)
     379                 : #endif
     380               0 : GENERIC_LOAD(64)
     381                 : 
     382                 : #undef GENERIC_LOAD
     383                 : 
     384                 : /*
     385                 :  * unaligned little-endian store
     386                 :  */
     387         1138966 : static void NaClStoreMem(uintptr_t  addr,
     388                 :                          size_t     nbytes,
     389                 :                          uint64_t   value) {
     390                 :   size_t i;
     391                 : 
     392         1138966 :   CHECK(nbytes <= 8);
     393                 : 
     394         4556698 :   for (i = 0; i < nbytes; ++i) {
     395         3417732 :     ((uint8_t *) addr)[i] = (uint8_t) value;
     396         3417732 :     value = value >> 8;
     397                 :   }
     398         1138966 : }
     399                 : 
     400                 : #define GENERIC_STORE(bits) \
     401                 :   static void NaClStore ## bits(uintptr_t addr, \
     402                 :                                 uint ## bits ## _t v) { \
     403                 :     NaClStoreMem(addr, sizeof(uint ## bits ## _t), v); \
     404                 :   }
     405                 : 
     406          569066 : GENERIC_STORE(16)
     407          569900 : GENERIC_STORE(32)
     408               0 : GENERIC_STORE(64)
     409                 : 
     410                 : #undef GENERIC_STORE
     411                 : 
     412          569900 : struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self) {
     413          569900 :   if (NULL != self) {
     414          569900 :     memset(self, 0, sizeof *self);
     415                 :   }
     416          569900 :   return self;
     417                 : }
     418                 : 
     419                 : /*
     420                 :  * This function is called by NaClLoadTrampoline and NaClLoadSpringboard to
     421                 :  * patch a single memory location specified in NaClPatchInfo structure.
     422                 :  */
     423          569900 : void  NaClApplyPatchToMemory(struct NaClPatchInfo  *patch) {
     424                 :   size_t    i;
     425                 :   size_t    offset;
     426                 :   int64_t   reloc;
     427                 :   uintptr_t target_addr;
     428                 : 
     429          569900 :   memcpy((void *) patch->dst, (void *) patch->src, patch->nbytes);
     430                 : 
     431          569900 :   reloc = patch->dst - patch->src;
     432                 : 
     433                 : 
     434          569900 :   for (i = 0; i < patch->num_abs64; ++i) {
     435               0 :     offset = patch->abs64[i].target - patch->src;
     436               0 :     target_addr = patch->dst + offset;
     437               0 :     NaClStore64(target_addr, patch->abs64[i].value);
     438                 :   }
     439                 : 
     440         1139800 :   for (i = 0; i < patch->num_abs32; ++i) {
     441          569900 :     offset = patch->abs32[i].target - patch->src;
     442          569900 :     target_addr = patch->dst + offset;
     443          569900 :     NaClStore32(target_addr, (uint32_t) patch->abs32[i].value);
     444                 :   }
     445                 : 
     446         1138966 :   for (i = 0; i < patch->num_abs16; ++i) {
     447          569066 :     offset = patch->abs16[i].target - patch->src;
     448          569066 :     target_addr = patch->dst + offset;
     449          569066 :     NaClStore16(target_addr, (uint16_t) patch->abs16[i].value);
     450                 :   }
     451                 : 
     452          569900 :   for (i = 0; i < patch->num_rel64; ++i) {
     453               0 :     offset = patch->rel64[i] - patch->src;
     454               0 :     target_addr = patch->dst + offset;
     455               0 :     NaClStore64(target_addr, NaClLoad64(target_addr) - reloc);
     456                 :   }
     457                 : 
     458                 :   /*
     459                 :    * rel32 is only supported on 32-bit architectures. The range of a relative
     460                 :    * relocation in untrusted space is +/- 4GB. This can be represented as
     461                 :    * an unsigned 32-bit value mod 2^32, which is handy on a 32 bit system since
     462                 :    * all 32-bit pointer arithmetic is implicitly mod 2^32. On a 64 bit system,
     463                 :    * however, pointer arithmetic is implicitly modulo 2^64, which isn't as
     464                 :    * helpful for our purposes. We could simulate the 32-bit behavior by
     465                 :    * explicitly modding all relative addresses by 2^32, but that seems like an
     466                 :    * expensive way to save a few bytes per reloc.
     467                 :    */
     468                 : #if NACL_TARGET_SUBARCH == 32
     469          569900 :   for (i = 0; i < patch->num_rel32; ++i) {
     470               0 :     offset = patch->rel32[i] - patch->src;
     471               0 :     target_addr = patch->dst + offset;
     472               0 :     NaClStore32(target_addr,
     473               0 :       (uint32_t) NaClLoad32(target_addr) - (int32_t) reloc);
     474                 :   }
     475                 : #endif
     476          569900 : }
     477                 : 
     478                 : 
     479                 : /*
     480                 :  * Install syscall trampolines at all possible well-formed entry
     481                 :  * points within the trampoline pages.  Many of these syscalls will
     482                 :  * correspond to unimplemented system calls and will just abort the
     483                 :  * program.
     484                 :  */
     485             278 : void  NaClLoadTrampoline(struct NaClApp *nap, enum NaClAslrMode aslr_mode) {
     486                 :   int         num_syscalls;
     487                 :   int         i;
     488                 :   uintptr_t   addr;
     489                 : 
     490                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     491             278 :   if (!NaClMakePcrelThunk(nap, aslr_mode)) {
     492               0 :     NaClLog(LOG_FATAL, "NaClMakePcrelThunk failed!\n");
     493                 :   }
     494                 : #else
     495                 :   UNREFERENCED_PARAMETER(aslr_mode);
     496                 : #endif
     497                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     498                 :   if (!NaClMakeDispatchAddrs(nap)) {
     499                 :     NaClLog(LOG_FATAL, "NaClMakeDispatchAddrs failed!\n");
     500                 :   }
     501                 : #endif
     502             278 :   NaClFillTrampolineRegion(nap);
     503                 : 
     504                 :   /*
     505                 :    * Do not bother to fill in the contents of page 0, since we make it
     506                 :    * inaccessible later (see sel_addrspace.c, NaClMemoryProtection)
     507                 :    * anyway to help detect NULL pointer errors, and we might as well
     508                 :    * not dirty the page.
     509                 :    *
     510                 :    * The last syscall entry point is used for springboard code.
     511                 :    */
     512             278 :   num_syscalls = ((NACL_TRAMPOLINE_END - NACL_SYSCALL_START_ADDR)
     513                 :                   / NACL_SYSCALL_BLOCK_SIZE) - 1;
     514                 : 
     515             278 :   NaClLog(2, "num_syscalls = %d (0x%x)\n", num_syscalls, num_syscalls);
     516                 : 
     517          569622 :   for (i = 0, addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
     518                 :        i < num_syscalls;
     519          569066 :        ++i, addr += NACL_SYSCALL_BLOCK_SIZE) {
     520          569066 :     NaClPatchOneTrampoline(nap, addr);
     521                 :   }
     522                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     523                 :   NaClPatchOneTrampolineCall(nap->get_tls_fast_path1_addr,
     524                 :                              nap->mem_start + NACL_SYSCALL_START_ADDR
     525                 :                              + NACL_SYSCALL_BLOCK_SIZE * NACL_sys_tls_get);
     526                 :   NaClPatchOneTrampolineCall(nap->get_tls_fast_path2_addr,
     527                 :                              nap->mem_start + NACL_SYSCALL_START_ADDR
     528                 :                              + (NACL_SYSCALL_BLOCK_SIZE *
     529                 :                                 NACL_sys_second_tls_get));
     530                 : #endif
     531                 : 
     532             278 :   NACL_TEST_INJECTION(ChangeTrampolines, (nap));
     533             278 : }
     534                 : 
     535             131 : void  NaClMemRegionPrinter(void                   *state,
     536                 :                            struct NaClVmmapEntry  *entry) {
     537             131 :   struct Gio *gp = (struct Gio *) state;
     538                 : 
     539             131 :   gprintf(gp, "\nPage   %"NACL_PRIdPTR" (0x%"NACL_PRIxPTR")\n",
     540                 :           entry->page_num, entry->page_num);
     541             131 :   gprintf(gp,   "npages %"NACL_PRIdS" (0x%"NACL_PRIxS")\n", entry->npages,
     542                 :           entry->npages);
     543             131 :   gprintf(gp,   "start vaddr 0x%"NACL_PRIxPTR"\n",
     544             131 :           entry->page_num << NACL_PAGESHIFT);
     545             131 :   gprintf(gp,   "end vaddr   0x%"NACL_PRIxPTR"\n",
     546             131 :           (entry->page_num + entry->npages) << NACL_PAGESHIFT);
     547             131 :   gprintf(gp,   "prot   0x%08x\n", entry->prot);
     548             131 :   gprintf(gp,   "%sshared/backed by a file\n",
     549             131 :           (NULL == entry->desc) ? "not " : "");
     550             131 : }
     551                 : 
     552              22 : void  NaClAppPrintDetails(struct NaClApp  *nap,
     553                 :                           struct Gio      *gp) {
     554              22 :   NaClXMutexLock(&nap->mu);
     555              22 :   gprintf(gp,
     556                 :           "NaClAppPrintDetails((struct NaClApp *) 0x%08"NACL_PRIxPTR","
     557                 :           "(struct Gio *) 0x%08"NACL_PRIxPTR")\n", (uintptr_t) nap,
     558                 :           (uintptr_t) gp);
     559              22 :   gprintf(gp, "addr space size:  2**%"NACL_PRId32"\n", nap->addr_bits);
     560              22 :   gprintf(gp, "stack size:       0x%08"NACL_PRIx32"\n", nap->stack_size);
     561                 : 
     562              22 :   gprintf(gp, "mem start addr:   0x%08"NACL_PRIxPTR"\n", nap->mem_start);
     563                 :   /*           123456789012345678901234567890 */
     564                 : 
     565              22 :   gprintf(gp, "static_text_end:   0x%08"NACL_PRIxPTR"\n", nap->static_text_end);
     566              22 :   gprintf(gp, "end-of-text:       0x%08"NACL_PRIxPTR"\n",
     567                 :           NaClEndOfStaticText(nap));
     568              22 :   gprintf(gp, "rodata:            0x%08"NACL_PRIxPTR"\n", nap->rodata_start);
     569              22 :   gprintf(gp, "data:              0x%08"NACL_PRIxPTR"\n", nap->data_start);
     570              22 :   gprintf(gp, "data_end:          0x%08"NACL_PRIxPTR"\n", nap->data_end);
     571              22 :   gprintf(gp, "break_addr:        0x%08"NACL_PRIxPTR"\n", nap->break_addr);
     572                 : 
     573              22 :   gprintf(gp, "ELF initial entry point:  0x%08x\n", nap->initial_entry_pt);
     574              22 :   gprintf(gp, "ELF user entry point:  0x%08x\n", nap->user_entry_pt);
     575              22 :   gprintf(gp, "memory map:\n");
     576              22 :   NaClVmmapVisit(&nap->mem_map,
     577                 :                  NaClMemRegionPrinter,
     578                 :                  gp);
     579              22 :   NaClXMutexUnlock(&nap->mu);
     580              22 : }
     581                 : 
     582           71564 : struct NaClDesc *NaClAppGetDescMu(struct NaClApp *nap,
     583                 :                                   int            d) {
     584                 :   struct NaClDesc *result;
     585                 : 
     586           71564 :   result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
     587           71564 :   if (NULL != result) {
     588           71540 :     NaClDescRef(result);
     589                 :   }
     590                 : 
     591           71564 :   return result;
     592                 : }
     593                 : 
     594            1840 : void NaClAppSetDescMu(struct NaClApp   *nap,
     595                 :                       int              d,
     596                 :                       struct NaClDesc  *ndp) {
     597                 :   struct NaClDesc *result;
     598                 : 
     599            1840 :   result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
     600            1840 :   NaClDescSafeUnref(result);
     601                 : 
     602            1840 :   if (!DynArraySet(&nap->desc_tbl, d, ndp)) {
     603               0 :     NaClLog(LOG_FATAL,
     604                 :             "NaClAppSetDesc: could not set descriptor %d to 0x%08"
     605                 :             NACL_PRIxPTR"\n",
     606                 :             d,
     607                 :             (uintptr_t) ndp);
     608                 :   }
     609            1840 : }
     610                 : 
     611             278 : int32_t NaClAppSetDescAvailMu(struct NaClApp  *nap,
     612                 :                               struct NaClDesc *ndp) {
     613                 :   size_t pos;
     614                 : 
     615             278 :   pos = DynArrayFirstAvail(&nap->desc_tbl);
     616                 : 
     617             278 :   if (pos > INT32_MAX) {
     618               0 :     NaClLog(LOG_FATAL,
     619                 :             ("NaClAppSetDescAvailMu: DynArrayFirstAvail returned a value"
     620                 :              " that is greather than 2**31-1.\n"));
     621                 :   }
     622                 : 
     623             278 :   NaClAppSetDescMu(nap, (int) pos, ndp);
     624                 : 
     625             278 :   return (int32_t) pos;
     626                 : }
     627                 : 
     628           70894 : struct NaClDesc *NaClAppGetDesc(struct NaClApp *nap,
     629                 :                                 int            d) {
     630                 :   struct NaClDesc *res;
     631                 : 
     632           70894 :   NaClFastMutexLock(&nap->desc_mu);
     633           70894 :   res = NaClAppGetDescMu(nap, d);
     634           70894 :   NaClFastMutexUnlock(&nap->desc_mu);
     635           70894 :   return res;
     636                 : }
     637                 : 
     638             899 : void NaClAppSetDesc(struct NaClApp   *nap,
     639                 :                     int              d,
     640                 :                     struct NaClDesc  *ndp) {
     641             899 :   NaClFastMutexLock(&nap->desc_mu);
     642             899 :   NaClAppSetDescMu(nap, d, ndp);
     643             899 :   NaClFastMutexUnlock(&nap->desc_mu);
     644             899 : }
     645                 : 
     646             278 : int32_t NaClAppSetDescAvail(struct NaClApp  *nap,
     647                 :                             struct NaClDesc *ndp) {
     648                 :   int32_t pos;
     649                 : 
     650             278 :   NaClFastMutexLock(&nap->desc_mu);
     651             278 :   pos = NaClAppSetDescAvailMu(nap, ndp);
     652             278 :   NaClFastMutexUnlock(&nap->desc_mu);
     653                 : 
     654             278 :   return pos;
     655                 : }
     656                 : 
     657           29422 : int NaClAddThreadMu(struct NaClApp        *nap,
     658                 :                     struct NaClAppThread  *natp) {
     659                 :   size_t pos;
     660                 : 
     661           29422 :   pos = DynArrayFirstAvail(&nap->threads);
     662                 : 
     663           29422 :   if (!DynArraySet(&nap->threads, pos, natp)) {
     664               0 :     NaClLog(LOG_FATAL,
     665                 :             "NaClAddThreadMu: DynArraySet at position %"NACL_PRIuS" failed\n",
     666                 :             pos);
     667                 :   }
     668           29422 :   ++nap->num_threads;
     669           29422 :   return (int) pos;
     670                 : }
     671                 : 
     672               5 : int NaClAddThread(struct NaClApp        *nap,
     673                 :                   struct NaClAppThread  *natp) {
     674                 :   int pos;
     675                 : 
     676               5 :   NaClXMutexLock(&nap->threads_mu);
     677               5 :   pos = NaClAddThreadMu(nap, natp);
     678               5 :   NaClXMutexUnlock(&nap->threads_mu);
     679                 : 
     680               5 :   return pos;
     681                 : }
     682                 : 
     683           29367 : void NaClRemoveThreadMu(struct NaClApp  *nap,
     684                 :                         int             thread_num) {
     685           29367 :   if (NULL == DynArrayGet(&nap->threads, thread_num)) {
     686               1 :     NaClLog(LOG_FATAL,
     687                 :             "NaClRemoveThreadMu:: thread to be removed is not in the table\n");
     688                 :   }
     689           29366 :   if (nap->num_threads == 0) {
     690               0 :     NaClLog(LOG_FATAL,
     691                 :             "NaClRemoveThreadMu:: num_threads cannot be 0!!!\n");
     692                 :   }
     693           29366 :   --nap->num_threads;
     694           29366 :   if (!DynArraySet(&nap->threads, thread_num, (struct NaClAppThread *) NULL)) {
     695               0 :     NaClLog(LOG_FATAL,
     696                 :             "NaClRemoveThreadMu:: DynArraySet at position %d failed\n",
     697                 :             thread_num);
     698                 :   }
     699           29366 : }
     700                 : 
     701               3 : void NaClRemoveThread(struct NaClApp  *nap,
     702                 :                       int             thread_num) {
     703               3 :   NaClXMutexLock(&nap->threads_mu);
     704               3 :   NaClRemoveThreadMu(nap, thread_num);
     705               2 :   NaClXMutexUnlock(&nap->threads_mu);
     706               2 : }
     707                 : 
     708           35401 : struct NaClAppThread *NaClGetThreadMu(struct NaClApp  *nap,
     709                 :                                       int             thread_num) {
     710           35401 :   return (struct NaClAppThread *) DynArrayGet(&nap->threads, thread_num);
     711                 : }
     712                 : 
     713             865 : void NaClAddHostDescriptor(struct NaClApp *nap,
     714                 :                            int            host_os_desc,
     715                 :                            int            flag,
     716                 :                            int            nacl_desc) {
     717                 :   struct NaClDescIoDesc *dp;
     718                 : 
     719             865 :   NaClLog(4,
     720                 :           "NaClAddHostDescriptor: host %d as nacl desc %d, flag 0x%x\n",
     721                 :           host_os_desc,
     722                 :           nacl_desc,
     723                 :           flag);
     724             865 :   dp = NaClDescIoDescMake(NaClHostDescPosixMake(host_os_desc, flag));
     725             865 :   if (NULL == dp) {
     726               0 :     NaClLog(LOG_FATAL, "NaClAddHostDescriptor: NaClDescIoDescMake failed\n");
     727                 :   }
     728             865 :   NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
     729             865 : }
     730                 : 
     731               2 : void NaClAddImcHandle(struct NaClApp  *nap,
     732                 :                       NaClHandle      h,
     733                 :                       int             nacl_desc) {
     734                 :   struct NaClDescImcDesc  *dp;
     735                 : 
     736               2 :   NaClLog(4,
     737                 :           ("NaClAddImcHandle: importing NaClHandle %"NACL_PRIxPTR
     738                 :            " as nacl desc %d\n"),
     739                 :           (uintptr_t) h,
     740                 :           nacl_desc);
     741               2 :   dp = (struct NaClDescImcDesc *) malloc(sizeof *dp);
     742               2 :   if (NACL_FI_ERROR_COND("NaClAddImcHandle__malloc", NULL == dp)) {
     743               0 :     NaClLog(LOG_FATAL, "NaClAddImcHandle: no memory\n");
     744                 :   }
     745               2 :   if (NACL_FI_ERROR_COND("NaClAddImcHandle__ctor",
     746                 :                          !NaClDescImcDescCtor(dp, h))) {
     747               0 :     NaClLog(LOG_FATAL, ("NaClAddImcHandle: cannot construct"
     748                 :                         " IMC descriptor object\n"));
     749                 :   }
     750               2 :   NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
     751               2 : }
     752                 : 
     753                 : 
     754                 : static struct {
     755                 :   int         d;
     756                 :   char const  *env_name;
     757                 :   int         nacl_flags;
     758                 :   int         mode;
     759                 : } const g_nacl_redir_control[] = {
     760                 :   { 0, "NACL_EXE_STDIN",
     761                 :     NACL_ABI_O_RDONLY, 0, },
     762                 :   { 1, "NACL_EXE_STDOUT",
     763                 :     NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND | NACL_ABI_O_CREAT, 0777, },
     764                 :   { 2, "NACL_EXE_STDERR",
     765                 :     NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND | NACL_ABI_O_CREAT, 0777, },
     766                 : };
     767                 : 
     768                 : /*
     769                 :  * File redirection is impossible if an outer sandbox is in place.
     770                 :  * For the command-line embedding, we sometimes have an outer sandbox:
     771                 :  * on OSX, it is enabled after loading the file is loaded.  On the
     772                 :  * other hand, device redirection (DEBUG_ONLY:dev://postmessage) is
     773                 :  * impossible until the reverse channel setup has occurred.
     774                 :  *
     775                 :  * Because of this, we run NaClProcessRedirControl twice: once to
     776                 :  * process default inheritance, file redirection early on, and once
     777                 :  * after the reverse channel is in place to handle the device
     778                 :  * redirection.  We try to hide knowledge about which redirection
     779                 :  * control values can be handled in which phases by allowing the
     780                 :  * NaClResourceOpen to fail, and only in the last phase do we check
     781                 :  * that the redirection succeeded in *some* phase.
     782                 :  */
     783             292 : static void NaClProcessRedirControl(struct NaClApp *nap) {
     784                 : 
     785                 :   size_t          ix;
     786                 :   char const      *env;
     787                 :   struct NaClDesc *ndp;
     788                 : 
     789            1168 :   for (ix = 0; ix < NACL_ARRAY_SIZE(g_nacl_redir_control); ++ix) {
     790             876 :     ndp = NULL;
     791             876 :     if (NULL != (env = getenv(g_nacl_redir_control[ix].env_name))) {
     792               2 :       NaClLog(4, "getenv(%s) -> %s\n", g_nacl_redir_control[ix].env_name, env);
     793               2 :       ndp = NaClResourceOpen((struct NaClResource *) &nap->resources,
     794                 :                              env,
     795                 :                              g_nacl_redir_control[ix].nacl_flags,
     796                 :                              g_nacl_redir_control[ix].mode);
     797               2 :       NaClLog(4, " NaClResourceOpen returned %"NACL_PRIxPTR"\n",
     798                 :               (uintptr_t) ndp);
     799                 :     }
     800                 : 
     801             876 :     if (NULL != ndp) {
     802               2 :       NaClLog(4, "Setting descriptor %d\n", (int) ix);
     803               2 :       NaClAppSetDesc(nap, (int) ix, ndp);
     804             874 :     } else if (NACL_RESOURCE_PHASE_START == nap->resource_phase) {
     805                 :       /*
     806                 :        * Environment not set or redirect failed -- handle default inheritance.
     807                 :        */
     808             865 :       NaClAddHostDescriptor(nap, DUP(g_nacl_redir_control[ix].d),
     809                 :                             g_nacl_redir_control[ix].nacl_flags, (int) ix);
     810                 :     }
     811                 :   }
     812             292 : }
     813                 : 
     814                 : /*
     815                 :  * Process default descriptor inheritance.  This means dup'ing
     816                 :  * descriptors 0-2 and making them available to the NaCl App.
     817                 :  *
     818                 :  * When standard input is inherited, this could result in a NaCl
     819                 :  * module competing for input from the terminal; for graphical /
     820                 :  * browser plugin environments, this never is allowed to happen, and
     821                 :  * having this is useful for debugging, and for potential standalone
     822                 :  * text-mode applications of NaCl.
     823                 :  *
     824                 :  * TODO(bsy): consider whether default inheritance should occur only
     825                 :  * in debug mode.
     826                 :  */
     827             289 : void NaClAppInitialDescriptorHookup(struct NaClApp  *nap) {
     828                 : 
     829             289 :   NaClLog(4, "Processing I/O redirection/inheritance from environment\n");
     830             289 :   nap->resource_phase = NACL_RESOURCE_PHASE_START;
     831             289 :   NaClProcessRedirControl(nap);
     832             289 :   NaClLog(4, "... done.\n");
     833             289 : }
     834                 : 
     835              10 : void NaClCreateServiceSocket(struct NaClApp *nap) {
     836                 :   struct NaClDesc *secure_pair[2];
     837                 :   struct NaClDesc *pair[2];
     838                 : 
     839              10 :   NaClLog(3, "Entered NaClCreateServiceSocket\n");
     840                 : 
     841              10 :   if (NACL_FI_ERROR_COND("NaClCreateServiceSocket__secure_boundsock",
     842                 :                          0 != NaClCommonDescMakeBoundSock(secure_pair))) {
     843               0 :     NaClLog(LOG_FATAL, "Cound not create secure service socket\n");
     844                 :   }
     845              20 :   NaClLog(4,
     846                 :           "got bound socket at 0x%08"NACL_PRIxPTR", "
     847                 :           "addr at 0x%08"NACL_PRIxPTR"\n",
     848              10 :           (uintptr_t) secure_pair[0],
     849              10 :           (uintptr_t) secure_pair[1]);
     850                 : 
     851              10 :   NaClDescSafeUnref(nap->secure_service_port);
     852              10 :   nap->secure_service_port = secure_pair[0];
     853                 : 
     854              10 :   NaClDescSafeUnref(nap->secure_service_address);
     855              10 :   nap->secure_service_address = secure_pair[1];
     856                 : 
     857              10 :   if (NACL_FI_ERROR_COND("NaClCreateServiceSocket__boundsock",
     858                 :                          0 != NaClCommonDescMakeBoundSock(pair))) {
     859               0 :     NaClLog(LOG_FATAL, "Cound not create service socket\n");
     860                 :   }
     861              20 :   NaClLog(4,
     862                 :           "got bound socket at 0x%08"NACL_PRIxPTR", "
     863                 :           "addr at 0x%08"NACL_PRIxPTR"\n",
     864              10 :           (uintptr_t) pair[0],
     865              10 :           (uintptr_t) pair[1]);
     866              10 :   NaClAppSetDesc(nap, NACL_SERVICE_PORT_DESCRIPTOR, pair[0]);
     867              10 :   NaClAppSetDesc(nap, NACL_SERVICE_ADDRESS_DESCRIPTOR, pair[1]);
     868                 : 
     869              10 :   NaClDescSafeUnref(nap->service_port);
     870                 : 
     871              10 :   nap->service_port = pair[0];
     872              10 :   NaClDescRef(nap->service_port);
     873                 : 
     874              10 :   NaClDescSafeUnref(nap->service_address);
     875                 : 
     876              10 :   nap->service_address = pair[1];
     877              10 :   NaClDescRef(nap->service_address);
     878                 : 
     879              10 :   NaClLog(4, "Leaving NaClCreateServiceSocket\n");
     880              10 : }
     881                 : 
     882                 : /*
     883                 :  * Import the |inherited_desc| descriptor as an IMC handle, save a
     884                 :  * reference to it at nap->bootstrap_channel, then send the
     885                 :  * service_address over that channel.
     886                 :  */
     887               9 : void NaClSetUpBootstrapChannel(struct NaClApp  *nap,
     888                 :                                NaClHandle      inherited_desc) {
     889                 :   struct NaClDescImcDesc      *channel;
     890                 :   struct NaClImcTypedMsgHdr   hdr;
     891                 :   struct NaClDesc             *descs[2];
     892                 :   ssize_t                     rv;
     893                 : 
     894               9 :   NaClLog(4,
     895                 :           "NaClSetUpBootstrapChannel(0x%08"NACL_PRIxPTR", %"NACL_PRIdPTR")\n",
     896                 :           (uintptr_t) nap,
     897                 :           (uintptr_t) inherited_desc);
     898                 : 
     899               9 :   channel = (struct NaClDescImcDesc *) malloc(sizeof *channel);
     900               9 :   if (NULL == channel) {
     901               0 :     NaClLog(LOG_FATAL, "NaClSetUpBootstrapChannel: no memory\n");
     902                 :   }
     903               9 :   if (!NaClDescImcDescCtor(channel, inherited_desc)) {
     904               0 :     NaClLog(LOG_FATAL,
     905                 :             ("NaClSetUpBootstrapChannel: cannot construct IMC descriptor"
     906                 :              " object for inherited descriptor %"NACL_PRIdPTR"\n"),
     907                 :             (uintptr_t) inherited_desc);
     908               0 :     return;
     909                 :   }
     910               9 :   if (NULL == nap->secure_service_address) {
     911               0 :     NaClLog(LOG_FATAL,
     912                 :             "NaClSetUpBootstrapChannel: secure service address not set\n");
     913               0 :     return;
     914                 :   }
     915               9 :   if (NULL == nap->service_address) {
     916               0 :     NaClLog(LOG_FATAL,
     917                 :             "NaClSetUpBootstrapChannel: service address not set\n");
     918               0 :     return;
     919                 :   }
     920                 :   /*
     921                 :    * service_address and service_port are set together.
     922                 :    */
     923               9 :   descs[0] = nap->secure_service_address;
     924               9 :   descs[1] = nap->service_address;
     925                 : 
     926               9 :   hdr.iov = (struct NaClImcMsgIoVec *) NULL;
     927               9 :   hdr.iov_length = 0;
     928               9 :   hdr.ndescv = descs;
     929               9 :   hdr.ndesc_length = NACL_ARRAY_SIZE(descs);
     930                 : 
     931               9 :   rv = (*NACL_VTBL(NaClDesc, channel)->SendMsg)((struct NaClDesc *) channel,
     932                 :                                                 &hdr, 0);
     933               9 :   NaClXMutexLock(&nap->mu);
     934               9 :   if (NULL != nap->bootstrap_channel) {
     935               0 :     NaClLog(LOG_FATAL,
     936                 :             "NaClSetUpBootstrapChannel: cannot have two bootstrap channels\n");
     937                 :   }
     938               9 :   nap->bootstrap_channel = (struct NaClDesc *) channel;
     939               9 :   channel = NULL;
     940               9 :   NaClXMutexUnlock(&nap->mu);
     941                 : 
     942               9 :   NaClLog(1,
     943                 :           ("NaClSetUpBootstrapChannel: descriptor %"NACL_PRIdPTR
     944                 :            ", error %"NACL_PRIdS"\n"),
     945                 :           (uintptr_t) inherited_desc,
     946                 :           rv);
     947               9 :   if (NACL_FI_ERROR_COND("NaClSetUpBootstrapChannel__SendMsg", 0 != rv)) {
     948               0 :     NaClLog(LOG_FATAL,
     949                 :             "NaClSetUpBootstrapChannel: SendMsg failed, rv = %"NACL_PRIdS"\n",
     950                 :             rv);
     951                 :   }
     952                 : }
     953                 : 
     954               5 : NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) {
     955                 :   NaClErrorCode status;
     956                 : 
     957               5 :   NaClLog(4, "NaClWaitForLoadModuleCommand started\n");
     958               5 :   NaClXMutexLock(&nap->mu);
     959              15 :   while (nap->module_initialization_state < NACL_MODULE_LOADED) {
     960               5 :     NaClXCondVarWait(&nap->cv, &nap->mu);
     961                 :   }
     962               5 :   status = nap->module_load_status;
     963               5 :   NaClXMutexUnlock(&nap->mu);
     964               5 :   NaClLog(4, "NaClWaitForLoadModuleCommand finished\n");
     965                 : 
     966               5 :   return status;
     967                 : }
     968                 : 
     969             277 : NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) {
     970                 :   NaClErrorCode status;
     971                 : 
     972             277 :   NaClLog(4, "NaClWaitForLoadModuleStatus started\n");
     973             277 :   NaClXMutexLock(&nap->mu);
     974             554 :   while (LOAD_STATUS_UNKNOWN == (status = nap->module_load_status)) {
     975               0 :     NaClXCondVarWait(&nap->cv, &nap->mu);
     976                 :   }
     977             277 :   NaClXMutexUnlock(&nap->mu);
     978             277 :   NaClLog(4, "NaClWaitForLoadModuleStatus finished\n");
     979                 : 
     980             277 :   return status;
     981                 : }
     982                 : 
     983             278 : NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) {
     984                 :   NaClErrorCode status;
     985                 : 
     986             278 :   NaClLog(4, "NaClWaitForStartModuleCommand started\n");
     987             278 :   NaClXMutexLock(&nap->mu);
     988             574 :   while (nap->module_initialization_state < NACL_MODULE_STARTED) {
     989              18 :     NaClXCondVarWait(&nap->cv, &nap->mu);
     990                 :   }
     991             278 :   status = nap->module_load_status;
     992             278 :   NaClXMutexUnlock(&nap->mu);
     993             278 :   NaClLog(4, "NaClWaitForStartModuleCommand finished\n");
     994                 : 
     995             278 :   return status;
     996                 : }
     997                 : 
     998              11 : void NaClBlockIfCommandChannelExists(struct NaClApp *nap) {
     999              11 :   if (NULL != nap->secure_service) {
    1000                 :     for (;;) {
    1001                 :       struct nacl_abi_timespec req;
    1002               0 :       req.tv_sec = 1000;
    1003               0 :       req.tv_nsec = 0;
    1004               0 :       NaClNanosleep(&req, (struct nacl_abi_timespec *) NULL);
    1005               0 :     }
    1006                 :   }
    1007              11 : }
    1008                 : 
    1009               9 : void NaClSecureCommandChannel(struct NaClApp *nap) {
    1010                 :   struct NaClSecureService *secure_command_server;
    1011                 : 
    1012               9 :   NaClLog(4, "Entered NaClSecureCommandChannel\n");
    1013                 : 
    1014               9 :   secure_command_server = (struct NaClSecureService *) malloc(
    1015                 :       sizeof *secure_command_server);
    1016               9 :   if (NACL_FI_ERROR_COND("NaClSecureCommandChannel__malloc",
    1017                 :                          NULL == secure_command_server)) {
    1018               0 :     NaClLog(LOG_FATAL, "Out of memory for secure command channel\n");
    1019                 :   }
    1020               9 :   if (NACL_FI_ERROR_COND("NaClSecureCommandChannel__NaClSecureServiceCtor",
    1021                 :                          !NaClSecureServiceCtor(secure_command_server,
    1022                 :                                                 nap,
    1023                 :                                                 nap->secure_service_port,
    1024                 :                                                 nap->secure_service_address))) {
    1025               0 :     NaClLog(LOG_FATAL, "NaClSecureServiceCtor failed\n");
    1026                 :   }
    1027               9 :   nap->secure_service = secure_command_server;
    1028                 : 
    1029               9 :   NaClLog(4, "NaClSecureCommandChannel: starting service thread\n");
    1030               9 :   if (NACL_FI_ERROR_COND(
    1031                 :           "NaClSecureCommandChannel__NaClSimpleServiceStartServiceThread",
    1032                 :           !NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
    1033                 :                                                secure_command_server))) {
    1034               0 :     NaClLog(LOG_FATAL,
    1035                 :             "Could not start secure command channel service thread\n");
    1036                 :   }
    1037                 : 
    1038               9 :   NaClLog(4, "Leaving NaClSecureCommandChannel\n");
    1039               9 : }
    1040                 : 
    1041                 : 
    1042             288 : void NaClAppLoadModule(struct NaClApp   *nap,
    1043                 :                        struct NaClDesc  *nexe,
    1044                 :                        void             (*load_cb)(void *instance_data,
    1045                 :                                                    NaClErrorCode status),
    1046                 :                        void             *instance_data) {
    1047             288 :   NaClErrorCode status = LOAD_OK;
    1048                 : 
    1049             288 :   NaClLog(4,
    1050                 :           ("Entered NaClAppLoadModule: nap 0x%"NACL_PRIxPTR","
    1051                 :            " nexe 0x%"NACL_PRIxPTR"\n"),
    1052                 :           (uintptr_t) nap, (uintptr_t) nexe);
    1053                 :   /*
    1054                 :    * Ref was passed by value into |nexe| parameter, so up the refcount.
    1055                 :    * Be sure to unref when the parameter's copy goes out of scope
    1056                 :    * (when returning).
    1057                 :    */
    1058             288 :   NaClDescRef(nexe);
    1059                 : 
    1060                 :   /*
    1061                 :    * TODO(bsy): consider doing the processing below after sending the
    1062                 :    * RPC reply to increase parallelism.
    1063                 :    */
    1064             288 :   NaClXMutexLock(&nap->mu);
    1065             288 :   if (nap->module_initialization_state != NACL_MODULE_UNINITIALIZED) {
    1066               0 :     NaClLog(LOG_ERROR, "NaClAppLoadModule: repeated invocation\n");
    1067               0 :     status = LOAD_DUP_LOAD_MODULE;
    1068               0 :     NaClXMutexUnlock(&nap->mu);
    1069               0 :     if (NULL != load_cb) {
    1070               0 :       (*load_cb)(instance_data, status);
    1071                 :     }
    1072               0 :     NaClDescUnref(nexe);
    1073               0 :     return;
    1074                 :   }
    1075             288 :   nap->module_initialization_state = NACL_MODULE_LOADING;
    1076             288 :   NaClXCondVarBroadcast(&nap->cv);
    1077             288 :   NaClXMutexUnlock(&nap->mu);
    1078                 : 
    1079             288 :   if (NULL != load_cb) {
    1080               7 :     (*load_cb)(instance_data, status);
    1081                 :   }
    1082                 : 
    1083             288 :   NaClXMutexLock(&nap->mu);
    1084                 : 
    1085                 :   /*
    1086                 :    * Check and possibly mark the nexe binary as OK to attempt memory
    1087                 :    * mapping.  We first clear the safe-for-mmap flag -- if we do not
    1088                 :    * trust the renderer to really send us a safe-to-mmap descriptor
    1089                 :    * and have to query the validation cache, then we also do not want
    1090                 :    * to trust the metadata flag value that originated from the
    1091                 :    * renderer.
    1092                 :    */
    1093             288 :   NaClDescMarkUnsafeForMmap(nexe);
    1094             288 :   NaClReplaceDescIfValidationCacheAssertsMappable(&nexe,
    1095                 :                                                   nap->validation_cache);
    1096                 :   /* Transfer ownership from nexe to nap->main_nexe_desc. */
    1097             288 :   CHECK(nap->main_nexe_desc == NULL);
    1098             288 :   nap->main_nexe_desc = nexe;
    1099             288 :   nexe = NULL;
    1100                 : 
    1101             288 :   status = NACL_FI_VAL("load_module", NaClErrorCode,
    1102                 :                        NaClAppLoadFile(nap->main_nexe_desc, nap));
    1103                 : 
    1104             286 :   if (LOAD_OK != status) {
    1105              10 :     nap->module_load_status = status;
    1106              10 :     nap->module_initialization_state = NACL_MODULE_ERROR;
    1107              10 :     NaClXCondVarBroadcast(&nap->cv);
    1108                 :   }
    1109             286 :   NaClXMutexUnlock(&nap->mu);  /* NaClAppPrepareToLaunch takes mu */
    1110             286 :   if (LOAD_OK != status) {
    1111              10 :     NaClDescUnref(nap->main_nexe_desc);
    1112              10 :     nap->main_nexe_desc = NULL;
    1113              10 :     return;
    1114                 :   }
    1115                 : 
    1116                 :   /***************************************************************************
    1117                 :    * TODO(bsy): Remove/merge the code invoking NaClAppPrepareToLaunch
    1118                 :    * and NaClGdbHook below with sel_main's main function.  See comment
    1119                 :    * there.
    1120                 :    ***************************************************************************/
    1121                 : 
    1122                 :   /*
    1123                 :    * Finish setting up the NaCl App.
    1124                 :    */
    1125             276 :   status = NaClAppPrepareToLaunch(nap);
    1126                 : 
    1127             276 :   NaClXMutexLock(&nap->mu);
    1128             276 :   nap->module_load_status = status;
    1129             276 :   nap->module_initialization_state = NACL_MODULE_LOADED;
    1130             276 :   NaClXCondVarBroadcast(&nap->cv);
    1131             276 :   NaClXMutexUnlock(&nap->mu);
    1132                 : 
    1133                 :   /* Give debuggers a well known point at which xlate_base is known.  */
    1134             276 :   NaClGdbHook(nap);
    1135                 : }
    1136                 : 
    1137               3 : int NaClAppRuntimeHostSetup(struct NaClApp                  *nap,
    1138                 :                             struct NaClRuntimeHostInterface *host_itf) {
    1139               3 :   NaClErrorCode status = LOAD_OK;
    1140                 : 
    1141               3 :   NaClLog(4,
    1142                 :           ("Entered NaClAppRuntimeHostSetup, nap 0x%"NACL_PRIxPTR","
    1143                 :            " host_itf 0x%"NACL_PRIxPTR"\n"),
    1144                 :           (uintptr_t) nap, (uintptr_t) host_itf);
    1145                 : 
    1146               3 :   NaClXMutexLock(&nap->mu);
    1147               3 :   if (nap->module_initialization_state > NACL_MODULE_STARTING) {
    1148               0 :     NaClLog(LOG_ERROR, "NaClAppRuntimeHostSetup: too late\n");
    1149               0 :     status = LOAD_INTERNAL;
    1150               0 :     goto cleanup_status_mu;
    1151                 :   }
    1152                 : 
    1153               3 :   nap->runtime_host_interface = (struct NaClRuntimeHostInterface *)
    1154               3 :       NaClRefCountRef((struct NaClRefCount *) host_itf);
    1155                 : 
    1156                 :   /*
    1157                 :    * Hook up runtime host enabled resources, e.g.,
    1158                 :    * DEBUG_ONLY:dev://postmessage.  NB: Resources specified by
    1159                 :    * file:path should have been taken care of earlier, in
    1160                 :    * NaClAppInitialDescriptorHookup.
    1161                 :    */
    1162               3 :   nap->resource_phase = NACL_RESOURCE_PHASE_RUNTIME_HOST;
    1163               3 :   NaClLog(4, "Processing dev I/O redirection/inheritance from environment\n");
    1164               3 :   NaClProcessRedirControl(nap);
    1165               3 :   NaClLog(4, "... done.\n");
    1166                 : 
    1167                 :  cleanup_status_mu:
    1168               3 :   NaClXMutexUnlock(&nap->mu);
    1169               3 :   return (int) status;
    1170                 : }
    1171                 : 
    1172               3 : int NaClAppDescQuotaSetup(struct NaClApp                 *nap,
    1173                 :                           struct NaClDescQuotaInterface  *quota_itf) {
    1174               3 :   NaClErrorCode status = LOAD_OK;
    1175                 : 
    1176               3 :   NaClLog(4,
    1177                 :           ("Entered NaClAppDescQuotaSetup, nap 0x%"NACL_PRIxPTR","
    1178                 :            " quota_itf 0x%"NACL_PRIxPTR"\n"),
    1179                 :           (uintptr_t) nap, (uintptr_t) quota_itf);
    1180                 : 
    1181               3 :   NaClXMutexLock(&nap->mu);
    1182               3 :   if (nap->module_initialization_state > NACL_MODULE_STARTING) {
    1183               0 :     NaClLog(LOG_ERROR, "NaClAppDescQuotaSetup: too late\n");
    1184               0 :     status = LOAD_INTERNAL;
    1185               0 :     goto cleanup_status_mu;
    1186                 :   }
    1187                 : 
    1188               3 :   nap->desc_quota_interface = (struct NaClDescQuotaInterface *)
    1189               3 :     NaClRefCountRef((struct NaClRefCount *) quota_itf);
    1190                 : 
    1191                 :  cleanup_status_mu:
    1192               3 :   NaClXMutexUnlock(&nap->mu);
    1193               3 :   return (int) status;
    1194                 : }
    1195                 : 
    1196             280 : void NaClAppStartModule(struct NaClApp  *nap,
    1197                 :                         void            (*start_cb)(void *instance_data,
    1198                 :                                                     NaClErrorCode status),
    1199                 :                         void            *instance_data) {
    1200                 :   NaClErrorCode status;
    1201                 : 
    1202             280 :   NaClLog(4,
    1203                 :           ("Entered NaClAppStartModule, nap 0x%"NACL_PRIxPTR","
    1204                 :            " start_cb 0x%"NACL_PRIxPTR", instance_data 0x%"NACL_PRIxPTR"\n"),
    1205                 :           (uintptr_t) nap, (uintptr_t) start_cb, (uintptr_t) instance_data);
    1206                 : 
    1207                 :   /*
    1208                 :    * When module is loading, we have to block and wait till it is
    1209                 :    * fully loaded before we can proceed with start module.
    1210                 :    */
    1211             280 :   NaClXMutexLock(&nap->mu);
    1212             280 :   if (NACL_MODULE_LOADING == nap->module_initialization_state) {
    1213               0 :     while (NACL_MODULE_LOADED != nap->module_initialization_state) {
    1214               0 :       NaClXCondVarWait(&nap->cv, &nap->mu);
    1215                 :     }
    1216                 :   }
    1217             280 :   if (nap->module_initialization_state != NACL_MODULE_LOADED) {
    1218              11 :     if (NACL_MODULE_ERROR == nap->module_initialization_state) {
    1219              10 :       NaClLog(LOG_ERROR, "NaClAppStartModule: error loading module\n");
    1220              10 :       status = nap->module_load_status;
    1221               1 :     } else if (nap->module_initialization_state > NACL_MODULE_LOADED) {
    1222               0 :       NaClLog(LOG_ERROR, "NaClAppStartModule: repeated invocation\n");
    1223               0 :       status = LOAD_DUP_START_MODULE;
    1224               1 :     } else if (nap->module_initialization_state < NACL_MODULE_LOADED) {
    1225               1 :       NaClLog(LOG_ERROR, "NaClAppStartModule: module not loaded\n");
    1226               1 :       status = LOAD_INTERNAL;
    1227                 :     }
    1228              11 :     NaClXMutexUnlock(&nap->mu);
    1229              11 :     if (NULL != start_cb) {
    1230               0 :       (*start_cb)(instance_data, status);
    1231                 :     }
    1232             291 :     return;
    1233                 :   }
    1234             269 :   status = nap->module_load_status;
    1235             269 :   nap->module_initialization_state = NACL_MODULE_STARTING;
    1236             269 :   NaClXCondVarBroadcast(&nap->cv);
    1237             269 :   NaClXMutexUnlock(&nap->mu);
    1238                 : 
    1239             269 :   NaClLog(4, "NaClSecureChannelStartModule: load status %d\n", status);
    1240                 : 
    1241                 :   /*
    1242                 :    * We need to invoke the callback now, before we signal the main thread
    1243                 :    * to possibly start by setting the state to NACL_MODULE_STARTED, since
    1244                 :    * in the case of failure the main thread may quickly exit; if the main
    1245                 :    * thread does this before we sent the reply, than the plugin (or any
    1246                 :    * other runtime host interface) will be left without an aswer. The
    1247                 :    * NACL_MODULE_STARTING state is used as an intermediate state to prevent
    1248                 :    * double invocations violating the protocol.
    1249                 :    */
    1250             269 :   if (NULL != start_cb) {
    1251               9 :     (*start_cb)(instance_data, status);
    1252                 :   }
    1253                 : 
    1254             269 :   NaClXMutexLock(&nap->mu);
    1255             269 :   nap->module_initialization_state = NACL_MODULE_STARTED;
    1256             269 :   NaClXCondVarBroadcast(&nap->cv);
    1257             269 :   NaClXMutexUnlock(&nap->mu);
    1258                 : }
    1259                 : 
    1260               5 : void NaClAppShutdown(struct NaClApp     *nap,
    1261                 :                      int                exit_status) {
    1262               5 :   NaClLog(4, "NaClAppShutdown: nap 0x%"NACL_PRIxPTR
    1263                 :           ", exit_status %d\n", (uintptr_t) nap, exit_status);
    1264                 : 
    1265               5 :   NaClXMutexLock(&nap->mu);
    1266               5 :   nap->exit_status = exit_status;
    1267               5 :   NaClXMutexUnlock(&nap->mu);
    1268               5 :   if (NULL != nap->debug_stub_callbacks) {
    1269               0 :     nap->debug_stub_callbacks->process_exit_hook();
    1270                 :   }
    1271               5 :   NaClExit(0);
    1272               0 : }
    1273                 : 
    1274                 : /*
    1275                 :  * It is fine to have multiple I/O operations read from memory in Write
    1276                 :  * or SendMsg like operations.
    1277                 :  */
    1278           91579 : void NaClVmIoWillStart(struct NaClApp *nap,
    1279                 :                        uint32_t addr_first_usr,
    1280                 :                        uint32_t addr_last_usr) {
    1281           91579 :   NaClXMutexLock(&nap->mu);
    1282           91580 :   (*nap->mem_io_regions->vtbl->AddInterval)(nap->mem_io_regions,
    1283                 :                                             addr_first_usr,
    1284                 :                                             addr_last_usr);
    1285           91580 :   NaClXMutexUnlock(&nap->mu);
    1286           91580 : }
    1287                 : 
    1288                 : 
    1289           91543 : void NaClVmIoHasEnded(struct NaClApp *nap,
    1290                 :                       uint32_t addr_first_usr,
    1291                 :                       uint32_t addr_last_usr) {
    1292           91543 :   NaClXMutexLock(&nap->mu);
    1293           91578 :   (*nap->mem_io_regions->vtbl->RemoveInterval)(nap->mem_io_regions,
    1294                 :                                                addr_first_usr,
    1295                 :                                                addr_last_usr);
    1296           91578 :   NaClXMutexUnlock(&nap->mu);
    1297           91578 : }
    1298                 : 
    1299           94647 : void NaClVmIoPendingCheck_mu(struct NaClApp *nap,
    1300                 :                              uint32_t addr_first_usr,
    1301                 :                              uint32_t addr_last_usr) {
    1302           94647 :   if ((*nap->mem_io_regions->vtbl->OverlapsWith)(nap->mem_io_regions,
    1303                 :                                                  addr_first_usr,
    1304                 :                                                  addr_last_usr)) {
    1305               2 :     NaClLog(LOG_FATAL,
    1306                 :             "NaClVmIoWillStart: program mem write race detected. ABORTING\n");
    1307                 :   }
    1308           94645 : }
    1309                 : 
    1310                 : /*
    1311                 :  * GDB's canonical overlay managment routine.
    1312                 :  * We need its symbol in the symbol table so don't inline it.
    1313                 :  * TODO(dje): add some explanation for the non-GDB person.
    1314                 :  */
    1315                 : #if NACL_WINDOWS
    1316                 : __declspec(dllexport noinline)
    1317                 : #endif
    1318                 : #ifdef __GNUC__
    1319                 : __attribute__((noinline))
    1320                 : #endif
    1321             280 : void _ovly_debug_event (void) {
    1322                 : #ifdef __GNUC__
    1323                 :   /*
    1324                 :    * The asm volatile is here as instructed by the GCC docs.
    1325                 :    * It's not enough to declare a function noinline.
    1326                 :    * GCC will still look inside the function to see if it's worth calling.
    1327                 :    */
    1328             280 :   __asm__ volatile ("");
    1329                 : #elif NACL_WINDOWS
    1330                 :   /*
    1331                 :    * Visual Studio inlines empty functions even with noinline attribute,
    1332                 :    * so we need a compile memory barrier to make this function not to be
    1333                 :    * inlined. Also, it guarantees that nacl_global_xlate_base initialization
    1334                 :    * is not reordered. This is important for gdb since it sets breakpoint on
    1335                 :    * this function and reads nacl_global_xlate_base value.
    1336                 :    */
    1337                 :   _ReadWriteBarrier();
    1338                 : #endif
    1339             280 : }
    1340                 : 
    1341             280 : static void StopForDebuggerInit (uintptr_t mem_start) {
    1342                 :   /* Put xlate_base in a place where gdb can find it.  */
    1343             280 :   nacl_global_xlate_base = mem_start;
    1344                 : 
    1345             280 :   NaClSandboxMemoryStartForValgrind(mem_start);
    1346                 : 
    1347             280 :   _ovly_debug_event();
    1348             280 : }
    1349                 : 
    1350             280 : void NaClGdbHook(struct NaClApp const *nap) {
    1351             280 :   StopForDebuggerInit(nap->mem_start);
    1352             280 : }

Generated by: LCOV version 1.7