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

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

Generated by: LCOV version 1.7