LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_ldr.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 681 241 35.4 %
Date: 2012-02-16 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_io.h"
      13                 : #include "native_client/src/include/portability_string.h"
      14                 : #include "native_client/src/include/nacl_macros.h"
      15                 : 
      16                 : #include "native_client/src/shared/gio/gio.h"
      17                 : #include "native_client/src/shared/platform/nacl_check.h"
      18                 : #include "native_client/src/shared/platform/nacl_exit.h"
      19                 : #include "native_client/src/shared/platform/nacl_log.h"
      20                 : #include "native_client/src/shared/platform/nacl_sync.h"
      21                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      22                 : #include "native_client/src/shared/platform/nacl_time.h"
      23                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      24                 : 
      25                 : 
      26                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      27                 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
      28                 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
      29                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      30                 : #include "native_client/src/trusted/desc/nrd_xfer.h"
      31                 : 
      32                 : #include "native_client/src/trusted/fault_injection/fault_injection.h"
      33                 : 
      34                 : #include "native_client/src/trusted/handle_pass/ldr_handle.h"
      35                 : 
      36                 : #include "native_client/src/trusted/gio/gio_nacl_desc.h"
      37                 : #include "native_client/src/trusted/gio/gio_shm.h"
      38                 : #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
      39                 : #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
      40                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      41                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      42                 : #include "native_client/src/trusted/service_runtime/include/sys/time.h"
      43                 : #include "native_client/src/trusted/service_runtime/nacl_app.h"
      44                 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
      45                 : #include "native_client/src/trusted/service_runtime/nacl_desc_effector_ldr.h"
      46                 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
      47                 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
      48                 : #include "native_client/src/trusted/service_runtime/nacl_reverse_quota_interface.h"
      49                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
      50                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
      51                 : #include "native_client/src/trusted/service_runtime/nacl_valgrind_hooks.h"
      52                 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
      53                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      54                 : #include "native_client/src/trusted/service_runtime/sel_memory.h"
      55                 : 
      56                 : #include "native_client/src/trusted/service_runtime/name_service/default_name_service.h"
      57                 : #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
      58                 : 
      59                 : #include "native_client/src/trusted/service_runtime/sel_ldr_thread_interface.h"
      60                 : #include "native_client/src/trusted/threading/nacl_thread_interface.h"
      61                 : 
      62                 : #include "native_client/src/trusted/simple_service/nacl_simple_rservice.h"
      63                 : #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
      64                 : 
      65                 : #include "native_client/src/trusted/threading/nacl_thread_interface.h"
      66                 : 
      67              38 : static int IsEnvironmentVariableSet(char const *env_name) {
      68              38 :   return NULL != getenv(env_name);
      69                 : }
      70                 : 
      71              19 : static int ShouldEnableDynamicLoading() {
      72              19 :   return !IsEnvironmentVariableSet("NACL_DISABLE_DYNAMIC_LOADING");
      73                 : }
      74                 : 
      75                 : int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
      76              19 :                                 struct NaClSyscallTableEntry *table) {
      77                 :   struct NaClDescEffectorLdr  *effp;
      78                 : 
      79                 :   /* Get the set of features that the CPU we're running on supports. */
      80              19 :   NaClGetCurrentCPUFeatures(&nap->cpu_features);
      81                 : 
      82              19 :   nap->addr_bits = NACL_MAX_ADDR_BITS;
      83                 : 
      84              19 :   nap->stack_size = NACL_DEFAULT_STACK_MAX;
      85                 : 
      86              19 :   nap->aux_info = NULL;
      87                 : 
      88              19 :   nap->mem_start = 0;
      89                 : 
      90                 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
      91                 :      && NACL_BUILD_SUBARCH == 32 && __PIC__)
      92              19 :   nap->pcrel_thunk = 0;
      93                 : #endif
      94                 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
      95                 :      && NACL_BUILD_SUBARCH == 64)
      96                 :   nap->dispatch_thunk = 0;
      97                 :   nap->get_tls_fast_path = 0;
      98                 : #endif
      99                 : 
     100              19 :   nap->static_text_end = 0;
     101              19 :   nap->dynamic_text_start = 0;
     102              19 :   nap->dynamic_text_end = 0;
     103              19 :   nap->rodata_start = 0;
     104              19 :   nap->data_start = 0;
     105              19 :   nap->data_end = 0;
     106                 : 
     107              19 :   nap->initial_entry_pt = 0;
     108              19 :   nap->user_entry_pt = 0;
     109                 : 
     110              19 :   if (!DynArrayCtor(&nap->threads, 2)) {
     111               0 :     goto cleanup_none;
     112                 :   }
     113              19 :   if (!DynArrayCtor(&nap->desc_tbl, 2)) {
     114               0 :     goto cleanup_threads;
     115                 :   }
     116              19 :   if (!NaClVmmapCtor(&nap->mem_map)) {
     117               0 :     goto cleanup_desc_tbl;
     118                 :   }
     119                 : 
     120              19 :   effp = (struct NaClDescEffectorLdr *) malloc(sizeof *effp);
     121              19 :   if (NULL == effp) {
     122               0 :     goto cleanup_mem_map;
     123                 :   }
     124              19 :   if (!NaClDescEffectorLdrCtor(effp, nap)) {
     125               0 :     goto cleanup_effp_free;
     126                 :   }
     127              19 :   nap->effp = (struct NaClDescEffector *) effp;
     128                 : 
     129              19 :   nap->use_shm_for_dynamic_text = ShouldEnableDynamicLoading();
     130              19 :   nap->text_shm = NULL;
     131              19 :   if (!NaClMutexCtor(&nap->dynamic_load_mutex)) {
     132               0 :     goto cleanup_effp_dtor;
     133                 :   }
     134              19 :   nap->dynamic_page_bitmap = NULL;
     135                 : 
     136              19 :   nap->dynamic_regions = NULL;
     137              19 :   nap->num_dynamic_regions = 0;
     138              19 :   nap->dynamic_regions_allocated = 0;
     139              19 :   nap->dynamic_delete_generation = 0;
     140                 : 
     141              19 :   nap->dynamic_mapcache_offset = 0;
     142              19 :   nap->dynamic_mapcache_size = 0;
     143              19 :   nap->dynamic_mapcache_ret = 0;
     144                 : 
     145              19 :   nap->service_port = NULL;
     146              19 :   nap->service_address = NULL;
     147              19 :   nap->secure_service = NULL;
     148              19 :   nap->manifest_proxy = NULL;
     149              19 :   nap->kern_service = NULL;
     150              19 :   nap->resource_phase = NACL_RESOURCE_PHASE_START;
     151              19 :   if (!NaClResourceNaClAppInit(&nap->resources, nap)) {
     152               0 :     goto cleanup_dynamic_load_mutex;
     153                 :   }
     154              19 :   nap->reverse_client = NULL;
     155              19 :   nap->reverse_channel_initialization_state =
     156                 :       NACL_REVERSE_CHANNEL_UNINITIALIZED;
     157                 : 
     158              19 :   if (!NaClMutexCtor(&nap->mu)) {
     159               0 :     goto cleanup_dynamic_load_mutex;
     160                 :   }
     161              19 :   if (!NaClCondVarCtor(&nap->cv)) {
     162               0 :     goto cleanup_mu;
     163                 :   }
     164                 : 
     165              19 :   nap->vm_hole_may_exist = 0;
     166              19 :   nap->threads_launching = 0;
     167                 : 
     168              19 :   nap->syscall_table = table;
     169                 : 
     170              19 :   nap->module_load_status = LOAD_STATUS_UNKNOWN;
     171              19 :   nap->module_may_start = 0;  /* only when secure_service != NULL */
     172                 : 
     173              19 :   nap->name_service = (struct NaClNameService *) malloc(
     174                 :       sizeof *nap->name_service);
     175              19 :   if (NULL == nap->name_service) {
     176               0 :     goto cleanup_cv;
     177                 :   }
     178              19 :   if (!NaClNameServiceCtor(nap->name_service,
     179                 :                            NaClAddrSpSquattingThreadIfFactoryFunction,
     180                 :                            (void *) nap)) {
     181               0 :     free(nap->name_service);
     182               0 :     goto cleanup_cv;
     183                 :   }
     184              19 :   nap->name_service_conn_cap = NaClDescRef(nap->name_service->
     185                 :                                            base.base.bound_and_cap[1]);
     186              19 :   if (!NaClDefaultNameServiceInit(nap->name_service)) {
     187               0 :     goto cleanup_name_service;
     188                 :   }
     189                 : 
     190              19 :   nap->ignore_validator_result = 0;
     191              19 :   nap->skip_validator = 0;
     192              19 :   nap->validator_stub_out_mode = 0;
     193                 : 
     194              19 :   if (IsEnvironmentVariableSet("NACL_DANGEROUS_ENABLE_FILE_ACCESS")) {
     195               0 :     NaClInsecurelyBypassAllAclChecks();
     196               0 :     NaClLog(LOG_INFO, "DANGER: ENABLED FILE ACCESS\n");
     197                 :   }
     198                 : 
     199              19 :   if (!NaClMutexCtor(&nap->threads_mu)) {
     200               0 :     goto cleanup_name_service;
     201                 :   }
     202              19 :   if (!NaClCondVarCtor(&nap->threads_cv)) {
     203               0 :     goto cleanup_threads_mu;
     204                 :   }
     205              19 :   nap->num_threads = 0;
     206              19 :   if (!NaClMutexCtor(&nap->desc_mu)) {
     207               0 :     goto cleanup_threads_cv;
     208                 :   }
     209                 : 
     210              19 :   nap->running = 0;
     211              19 :   nap->exit_status = -1;
     212                 : 
     213                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     214              19 :   nap->code_seg_sel = 0;
     215              19 :   nap->data_seg_sel = 0;
     216                 : #endif
     217                 : 
     218              19 :   nap->enable_debug_stub = 0;
     219              19 :   nap->debug_stub_callbacks = NULL;
     220              19 :   nap->exception_handler = 0;
     221              19 :   if (!NaClMutexCtor(&nap->exception_mu)) {
     222               0 :     goto cleanup_desc_mu;
     223                 :   }
     224              19 :   nap->enable_exception_handling = 0;
     225                 : 
     226              19 :   return 1;
     227                 : 
     228               0 :  cleanup_desc_mu:
     229               0 :   NaClMutexDtor(&nap->desc_mu);
     230               0 :  cleanup_threads_cv:
     231               0 :   NaClCondVarDtor(&nap->threads_cv);
     232               0 :  cleanup_threads_mu:
     233               0 :   NaClMutexDtor(&nap->threads_mu);
     234               0 :  cleanup_name_service:
     235               0 :   NaClDescUnref(nap->name_service_conn_cap);
     236               0 :   NaClRefCountUnref((struct NaClRefCount *) nap->name_service);
     237               0 :  cleanup_cv:
     238               0 :   NaClCondVarDtor(&nap->cv);
     239               0 :  cleanup_mu:
     240               0 :   NaClMutexDtor(&nap->mu);
     241               0 :  cleanup_dynamic_load_mutex:
     242               0 :   NaClMutexDtor(&nap->dynamic_load_mutex);
     243               0 :  cleanup_effp_dtor:
     244               0 :   (*nap->effp->vtbl->Dtor)(nap->effp);
     245               0 :  cleanup_effp_free:
     246               0 :   free(nap->effp);
     247               0 :  cleanup_mem_map:
     248               0 :   NaClVmmapDtor(&nap->mem_map);
     249               0 :  cleanup_desc_tbl:
     250               0 :   DynArrayDtor(&nap->desc_tbl);
     251               0 :  cleanup_threads:
     252               0 :   DynArrayDtor(&nap->threads);
     253               0 :  cleanup_none:
     254               0 :   return 0;
     255                 : }
     256                 : 
     257              19 : int NaClAppCtor(struct NaClApp *nap) {
     258              19 :   return NaClAppWithSyscallTableCtor(nap, nacl_syscall);
     259                 : }
     260                 : 
     261               0 : size_t  NaClAlignPad(size_t val, size_t align) {
     262                 :   /* align is always a power of 2, but we do not depend on it */
     263               0 :   if (!align) {
     264               0 :     NaClLog(4,
     265                 :             "sel_ldr: NaClAlignPad, align == 0, at 0x%08"NACL_PRIxS"\n",
     266                 :             val);
     267               0 :     return 0;
     268                 :   }
     269               0 :   val = val % align;
     270               0 :   if (!val) return 0;
     271               0 :   return align - val;
     272                 : }
     273                 : 
     274                 : /*
     275                 :  * unaligned little-endian load.  precondition: nbytes should never be
     276                 :  * more than 8.
     277                 :  */
     278                 : static uint64_t NaClLoadMem(uintptr_t addr,
     279               3 :                             size_t    user_nbytes) {
     280               3 :   uint64_t      value = 0;
     281                 : 
     282               3 :   CHECK(0 != user_nbytes && user_nbytes <= 8);
     283                 : 
     284                 :   do {
     285              12 :     value = value << 8;
     286              12 :     value |= ((uint8_t *) addr)[--user_nbytes];
     287              12 :   } while (user_nbytes > 0);
     288               3 :   return value;
     289                 : }
     290                 : 
     291                 : #define GENERIC_LOAD(bits) \
     292                 :   static uint ## bits ## _t NaClLoad ## bits(uintptr_t addr) { \
     293                 :     return (uint ## bits ## _t) NaClLoadMem(addr, sizeof(uint ## bits ## _t)); \
     294                 :   }
     295                 : 
     296                 : #if NACL_TARGET_SUBARCH == 32
     297               3 : GENERIC_LOAD(32)
     298                 : #endif
     299               0 : GENERIC_LOAD(64)
     300                 : 
     301                 : #undef GENERIC_LOAD
     302                 : 
     303                 : /*
     304                 :  * unaligned little-endian store
     305                 :  */
     306                 : static void NaClStoreMem(uintptr_t  addr,
     307                 :                          size_t     nbytes,
     308           12291 :                          uint64_t   value) {
     309                 :   size_t i;
     310                 : 
     311           12291 :   CHECK(nbytes <= 8);
     312                 : 
     313           49179 :   for (i = 0; i < nbytes; ++i) {
     314           36888 :     ((uint8_t *) addr)[i] = (uint8_t) value;
     315           36888 :     value = value >> 8;
     316                 :   }
     317           12291 : }
     318                 : 
     319                 : #define GENERIC_STORE(bits) \
     320                 :   static void NaClStore ## bits(uintptr_t addr, \
     321                 :                                 uint ## bits ## _t v) { \
     322                 :     NaClStoreMem(addr, sizeof(uint ## bits ## _t), v); \
     323                 :   }
     324                 : 
     325            6138 : GENERIC_STORE(16)
     326            6153 : GENERIC_STORE(32)
     327               0 : GENERIC_STORE(64)
     328                 : 
     329                 : #undef GENERIC_STORE
     330                 : 
     331            6147 : struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self) {
     332            6147 :   if (NULL != self) {
     333            6147 :     memset(self, 0, sizeof *self);
     334                 :   }
     335            6147 :   return self;
     336                 : }
     337                 : 
     338                 : /*
     339                 :  * This function is called by NaClLoadTrampoline and NaClLoadSpringboard to
     340                 :  * patch a single memory location specified in NaClPatchInfo structure.
     341                 :  */
     342            6150 : void  NaClApplyPatchToMemory(struct NaClPatchInfo  *patch) {
     343                 :   size_t    i;
     344                 :   size_t    offset;
     345                 :   int64_t   reloc;
     346                 :   uintptr_t target_addr;
     347                 : 
     348            6150 :   memcpy((void *) patch->dst, (void *) patch->src, patch->nbytes);
     349                 : 
     350            6150 :   reloc = patch->dst - patch->src;
     351                 : 
     352                 : 
     353            6150 :   for (i = 0; i < patch->num_abs64; ++i) {
     354               0 :     offset = patch->abs64[i].target - patch->src;
     355               0 :     target_addr = patch->dst + offset;
     356               0 :     NaClStore64(target_addr, patch->abs64[i].value);
     357                 :   }
     358                 : 
     359           12300 :   for (i = 0; i < patch->num_abs32; ++i) {
     360            6150 :     offset = patch->abs32[i].target - patch->src;
     361            6150 :     target_addr = patch->dst + offset;
     362            6150 :     NaClStore32(target_addr, (uint32_t) patch->abs32[i].value);
     363                 :   }
     364                 : 
     365           12288 :   for (i = 0; i < patch->num_abs16; ++i) {
     366            6138 :     offset = patch->abs16[i].target - patch->src;
     367            6138 :     target_addr = patch->dst + offset;
     368            6138 :     NaClStore16(target_addr, (uint16_t) patch->abs16[i].value);
     369                 :   }
     370                 : 
     371            6150 :   for (i = 0; i < patch->num_rel64; ++i) {
     372               0 :     offset = patch->rel64[i] - patch->src;
     373               0 :     target_addr = patch->dst + offset;
     374               0 :     NaClStore64(target_addr, NaClLoad64(target_addr) - reloc);
     375                 :   }
     376                 : 
     377                 :   /*
     378                 :    * rel32 is only supported on 32-bit architectures. The range of a relative
     379                 :    * relocation in untrusted space is +/- 4GB. This can be represented as
     380                 :    * an unsigned 32-bit value mod 2^32, which is handy on a 32 bit system since
     381                 :    * all 32-bit pointer arithmetic is implicitly mod 2^32. On a 64 bit system,
     382                 :    * however, pointer arithmetic is implicitly modulo 2^64, which isn't as
     383                 :    * helpful for our purposes. We could simulate the 32-bit behavior by
     384                 :    * explicitly modding all relative addresses by 2^32, but that seems like an
     385                 :    * expensive way to save a few bytes per reloc.
     386                 :    */
     387                 : #if NACL_TARGET_SUBARCH == 32
     388            6153 :   for (i = 0; i < patch->num_rel32; ++i) {
     389               3 :     offset = patch->rel32[i] - patch->src;
     390               3 :     target_addr = patch->dst + offset;
     391               3 :     NaClStore32(target_addr,
     392                 :       (uint32_t) NaClLoad32(target_addr) - (int32_t) reloc);
     393                 :   }
     394                 : #endif
     395            6150 : }
     396                 : 
     397                 : 
     398                 : /*
     399                 :  * Install syscall trampolines at all possible well-formed entry
     400                 :  * points within the trampoline pages.  Many of these syscalls will
     401                 :  * correspond to unimplemented system calls and will just abort the
     402                 :  * program.
     403                 :  */
     404               3 : void  NaClLoadTrampoline(struct NaClApp *nap) {
     405                 :   int         num_syscalls;
     406                 :   int         i;
     407                 :   uintptr_t   addr;
     408                 : 
     409                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 && __PIC__
     410               3 :   if (!NaClMakePcrelThunk(nap)) {
     411               0 :     NaClLog(LOG_FATAL, "NaClMakePcrelThunk failed!\n");
     412                 :   }
     413                 : #endif
     414                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     415                 :   if (!NaClMakeDispatchThunk(nap)) {
     416                 :     NaClLog(LOG_FATAL, "NaClMakeDispatchThunk failed!\n");
     417                 :   }
     418                 : #endif
     419               3 :   NaClFillTrampolineRegion(nap);
     420                 : 
     421                 :   /*
     422                 :    * Do not bother to fill in the contents of page 0, since we make it
     423                 :    * inaccessible later (see sel_addrspace.c, NaClMemoryProtection)
     424                 :    * anyway to help detect NULL pointer errors, and we might as well
     425                 :    * not dirty the page.
     426                 :    *
     427                 :    * The last syscall entry point is used for springboard code.
     428                 :    */
     429               3 :   num_syscalls = ((NACL_TRAMPOLINE_END - NACL_SYSCALL_START_ADDR)
     430                 :                   / NACL_SYSCALL_BLOCK_SIZE) - 1;
     431                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     432                 :   /*
     433                 :    * Use one last entry to tell the debugger address of the nacl_user variable.
     434                 :    */
     435               3 :   num_syscalls--;
     436               3 :   NaClPatchDebuggerInfo(nap);
     437                 : #endif
     438                 : 
     439               3 :   NaClLog(2, "num_syscalls = %d (0x%x)\n", num_syscalls, num_syscalls);
     440                 : 
     441                 : #if defined(NACL_TARGET_ARM_THUMB2_MODE)
     442                 :   CHECK(0 != ((nap->user_entry_pt | nap->initial_entry_pt) & 0x1));
     443                 :   /*
     444                 :    * Thumb trampolines start 2 bytes before the aligned syscall address used
     445                 :    * by ordinary ARM.  We initialize this by adding 0xe to the start address
     446                 :    * of each trampoline.  Because the last start address would actually start
     447                 :    * into user code above, this allows one fewer trampolines than in ARM.
     448                 :    */
     449                 :   for (i = 0, addr = nap->mem_start + NACL_SYSCALL_START_ADDR + 0xe;
     450                 :        i < num_syscalls - 1;
     451                 :        ++i, addr += NACL_SYSCALL_BLOCK_SIZE) {
     452                 :     NaClPatchOneTrampoline(nap, addr);
     453                 :   }
     454                 : #else
     455               3 :   for (i = 0, addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
     456            6144 :        i < num_syscalls;
     457            6138 :        ++i, addr += NACL_SYSCALL_BLOCK_SIZE) {
     458            6138 :     NaClPatchOneTrampoline(nap, addr);
     459                 :   }
     460                 : #endif
     461                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     462                 :   NaClPatchOneTrampolineCall(nap->get_tls_fast_path,
     463                 :                              nap->mem_start + NACL_SYSCALL_START_ADDR
     464                 :                              + NACL_SYSCALL_BLOCK_SIZE * NACL_sys_tls_get);
     465                 : #endif
     466               3 : }
     467                 : 
     468                 : void  NaClMemRegionPrinter(void                   *state,
     469               0 :                            struct NaClVmmapEntry  *entry) {
     470               0 :   struct Gio *gp = (struct Gio *) state;
     471                 : 
     472               0 :   gprintf(gp, "\nPage   %"NACL_PRIdPTR" (0x%"NACL_PRIxPTR")\n",
     473                 :           entry->page_num, entry->page_num);
     474               0 :   gprintf(gp,   "npages %"NACL_PRIdS" (0x%"NACL_PRIxS")\n", entry->npages,
     475                 :           entry->npages);
     476               0 :   gprintf(gp,   "start vaddr 0x%"NACL_PRIxPTR"\n",
     477                 :           entry->page_num << NACL_PAGESHIFT);
     478               0 :   gprintf(gp,   "end vaddr   0x%"NACL_PRIxPTR"\n",
     479                 :           (entry->page_num + entry->npages) << NACL_PAGESHIFT);
     480               0 :   gprintf(gp,   "prot   0x%08x\n", entry->prot);
     481               0 :   gprintf(gp,   "%sshared/backed by a file\n",
     482                 :           (NULL == entry->nmop) ? "not " : "");
     483               0 : }
     484                 : 
     485                 : void  NaClAppPrintDetails(struct NaClApp  *nap,
     486               0 :                           struct Gio      *gp) {
     487               0 :   NaClXMutexLock(&nap->mu);
     488               0 :   gprintf(gp,
     489                 :           "NaClAppPrintDetails((struct NaClApp *) 0x%08"NACL_PRIxPTR","
     490                 :           "(struct Gio *) 0x%08"NACL_PRIxPTR")\n", (uintptr_t) nap,
     491                 :           (uintptr_t) gp);
     492               0 :   gprintf(gp, "addr space size:  2**%"NACL_PRId32"\n", nap->addr_bits);
     493               0 :   gprintf(gp, "stack size:       0x%08"NACL_PRIx32"\n", nap->stack_size);
     494                 : 
     495               0 :   gprintf(gp, "mem start addr:   0x%08"NACL_PRIxPTR"\n", nap->mem_start);
     496                 :   /*           123456789012345678901234567890 */
     497                 : 
     498               0 :   gprintf(gp, "static_text_end:   0x%08"NACL_PRIxPTR"\n", nap->static_text_end);
     499               0 :   gprintf(gp, "end-of-text:       0x%08"NACL_PRIxPTR"\n",
     500                 :           NaClEndOfStaticText(nap));
     501               0 :   gprintf(gp, "rodata:            0x%08"NACL_PRIxPTR"\n", nap->rodata_start);
     502               0 :   gprintf(gp, "data:              0x%08"NACL_PRIxPTR"\n", nap->data_start);
     503               0 :   gprintf(gp, "data_end:          0x%08"NACL_PRIxPTR"\n", nap->data_end);
     504               0 :   gprintf(gp, "break_addr:        0x%08"NACL_PRIxPTR"\n", nap->break_addr);
     505                 : 
     506               0 :   gprintf(gp, "ELF initial entry point:  0x%08x\n", nap->initial_entry_pt);
     507               0 :   gprintf(gp, "ELF user entry point:  0x%08x\n", nap->user_entry_pt);
     508               0 :   gprintf(gp, "memory map:\n");
     509               0 :   NaClVmmapVisit(&nap->mem_map,
     510                 :                  NaClMemRegionPrinter,
     511                 :                  gp);
     512               0 :   NaClXMutexUnlock(&nap->mu);
     513               0 : }
     514                 : 
     515                 : struct NaClDesc *NaClGetDescMu(struct NaClApp *nap,
     516             213 :                                int            d) {
     517                 :   struct NaClDesc *result;
     518                 : 
     519             213 :   result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
     520             213 :   if (NULL != result) {
     521             202 :     NaClDescRef(result);
     522                 :   }
     523                 : 
     524             213 :   return result;
     525                 : }
     526                 : 
     527                 : void NaClSetDescMu(struct NaClApp   *nap,
     528                 :                    int              d,
     529              76 :                    struct NaClDesc  *ndp) {
     530                 :   struct NaClDesc *result;
     531                 : 
     532              76 :   result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
     533              76 :   NaClDescSafeUnref(result);
     534                 : 
     535              76 :   if (!DynArraySet(&nap->desc_tbl, d, ndp)) {
     536               0 :     NaClLog(LOG_FATAL,
     537                 :             "NaClSetDesc: could not set descriptor %d to 0x%08"
     538                 :             NACL_PRIxPTR"\n",
     539                 :             d,
     540                 :             (uintptr_t) ndp);
     541                 :   }
     542              76 : }
     543                 : 
     544                 : int32_t NaClSetAvailMu(struct NaClApp  *nap,
     545              15 :                        struct NaClDesc *ndp) {
     546                 :   size_t pos;
     547                 : 
     548              15 :   pos = DynArrayFirstAvail(&nap->desc_tbl);
     549                 : 
     550              15 :   if (pos > INT32_MAX) {
     551               0 :     NaClLog(LOG_FATAL,
     552                 :             ("NaClSetAvailMu: DynArrayFirstAvail returned a value"
     553                 :              " that is greather than 2**31-1.\n"));
     554                 :   }
     555                 : 
     556              15 :   NaClSetDescMu(nap, (int) pos, ndp);
     557                 : 
     558              15 :   return (int32_t) pos;
     559                 : }
     560                 : 
     561                 : struct NaClDesc *NaClGetDesc(struct NaClApp *nap,
     562             187 :                              int            d) {
     563                 :   struct NaClDesc *res;
     564                 : 
     565             187 :   NaClXMutexLock(&nap->desc_mu);
     566             187 :   res = NaClGetDescMu(nap, d);
     567             187 :   NaClXMutexUnlock(&nap->desc_mu);
     568             187 :   return res;
     569                 : }
     570                 : 
     571                 : void NaClSetDesc(struct NaClApp   *nap,
     572                 :                  int              d,
     573              40 :                  struct NaClDesc  *ndp) {
     574              40 :   NaClXMutexLock(&nap->desc_mu);
     575              40 :   NaClSetDescMu(nap, d, ndp);
     576              40 :   NaClXMutexUnlock(&nap->desc_mu);
     577              40 : }
     578                 : 
     579                 : int32_t NaClSetAvail(struct NaClApp  *nap,
     580              15 :                      struct NaClDesc *ndp) {
     581                 :   int32_t pos;
     582                 : 
     583              15 :   NaClXMutexLock(&nap->desc_mu);
     584              15 :   pos = NaClSetAvailMu(nap, ndp);
     585              15 :   NaClXMutexUnlock(&nap->desc_mu);
     586                 : 
     587              15 :   return pos;
     588                 : }
     589                 : 
     590                 : int NaClAddThreadMu(struct NaClApp        *nap,
     591               8 :                     struct NaClAppThread  *natp) {
     592                 :   size_t pos;
     593                 : 
     594               8 :   pos = DynArrayFirstAvail(&nap->threads);
     595                 : 
     596               8 :   if (!DynArraySet(&nap->threads, pos, natp)) {
     597               0 :     NaClLog(LOG_FATAL,
     598                 :             "NaClAddThreadMu: DynArraySet at position %"NACL_PRIuS" failed\n",
     599                 :             pos);
     600                 :   }
     601               8 :   ++nap->num_threads;
     602               8 :   return (int) pos;
     603                 : }
     604                 : 
     605                 : int NaClAddThread(struct NaClApp        *nap,
     606               5 :                   struct NaClAppThread  *natp) {
     607                 :   int pos;
     608                 : 
     609               5 :   NaClXMutexLock(&nap->threads_mu);
     610               5 :   pos = NaClAddThreadMu(nap, natp);
     611               5 :   NaClXMutexUnlock(&nap->threads_mu);
     612                 : 
     613               5 :   return pos;
     614                 : }
     615                 : 
     616                 : void NaClRemoveThreadMu(struct NaClApp  *nap,
     617               6 :                         int             thread_num) {
     618               6 :   if (NULL == DynArrayGet(&nap->threads, thread_num)) {
     619               1 :     NaClLog(LOG_FATAL,
     620                 :             "NaClRemoveThreadMu:: thread to be removed is not in the table\n");
     621                 :   }
     622               5 :   if (nap->num_threads == 0) {
     623               0 :     NaClLog(LOG_FATAL,
     624                 :             "NaClRemoveThreadMu:: num_threads cannot be 0!!!\n");
     625                 :   }
     626               5 :   --nap->num_threads;
     627               5 :   if (!DynArraySet(&nap->threads, thread_num, (struct NaClAppThread *) NULL)) {
     628               0 :     NaClLog(LOG_FATAL,
     629                 :             "NaClRemoveThreadMu:: DynArraySet at position %d failed\n",
     630                 :             thread_num);
     631                 :   }
     632               5 : }
     633                 : 
     634                 : void NaClRemoveThread(struct NaClApp  *nap,
     635               3 :                       int             thread_num) {
     636               3 :   NaClXMutexLock(&nap->threads_mu);
     637               3 :   NaClRemoveThreadMu(nap, thread_num);
     638               2 :   NaClXCondVarBroadcast(&nap->threads_cv);
     639               2 :   NaClXMutexUnlock(&nap->threads_mu);
     640               2 : }
     641                 : 
     642                 : struct NaClAppThread *NaClGetThreadMu(struct NaClApp  *nap,
     643               7 :                                       int             thread_num) {
     644               7 :   return (struct NaClAppThread *) DynArrayGet(&nap->threads, thread_num);
     645                 : }
     646                 : 
     647                 : void NaClAddHostDescriptor(struct NaClApp *nap,
     648                 :                            int            host_os_desc,
     649                 :                            int            flag,
     650              36 :                            int            nacl_desc) {
     651                 :   struct NaClDescIoDesc *dp;
     652                 : 
     653              36 :   NaClLog(4,
     654                 :           "NaClAddHostDescriptor: host %d as nacl desc %d, flag 0x%x\n",
     655                 :           host_os_desc,
     656                 :           nacl_desc,
     657                 :           flag);
     658              36 :   dp = NaClDescIoDescMake(NaClHostDescPosixMake(host_os_desc, flag));
     659              36 :   if (NULL == dp) {
     660               0 :     NaClLog(LOG_FATAL, "NaClAddHostDescriptor: NaClDescIoDescMake failed\n");
     661                 :   }
     662              36 :   NaClSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
     663              36 : }
     664                 : 
     665                 : void NaClAddImcHandle(struct NaClApp  *nap,
     666                 :                       NaClHandle      h,
     667               0 :                       int             nacl_desc) {
     668                 :   struct NaClDescImcDesc  *dp;
     669                 : 
     670               0 :   NaClLog(4,
     671                 :           ("NaClAddImcHandle: importing NaClHandle %"NACL_PRIxPTR
     672                 :            " as nacl desc %d\n"),
     673                 :           (uintptr_t) h,
     674                 :           nacl_desc);
     675               0 :   dp = (struct NaClDescImcDesc *) malloc(sizeof *dp);
     676               0 :   if (NULL == dp) {
     677               0 :     NaClLog(LOG_FATAL, "NaClAddImcHandle: no memory\n");
     678                 :   }
     679               0 :   if (!NaClDescImcDescCtor(dp, h)) {
     680               0 :     NaClLog(LOG_FATAL, ("NaClAddImcHandle: cannot construct"
     681                 :                         " IMC descriptor object\n"));
     682                 :   }
     683               0 :   NaClSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
     684               0 : }
     685                 : 
     686                 : 
     687              12 : static void NaClProcessRedirControl(struct NaClApp *nap) {
     688                 :   static struct {
     689                 :     int         d;
     690                 :     char const  *env_name;
     691                 :     int         nacl_flags;
     692                 :     int         mode;
     693                 :   } redir_control[] = {
     694                 :     { 0, "NACL_EXE_STDIN",
     695                 :       NACL_ABI_O_RDONLY, 0, },
     696                 :     { 1, "NACL_EXE_STDOUT",
     697                 :       NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND | NACL_ABI_O_CREAT, 0777, },
     698                 :     { 2, "NACL_EXE_STDERR",
     699                 :       NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND | NACL_ABI_O_CREAT, 0777, },
     700                 :   };
     701                 : 
     702                 :   size_t          ix;
     703                 :   char const      *env;
     704                 :   struct NaClDesc *ndp;
     705                 : 
     706              48 :   for (ix = 0; ix < NACL_ARRAY_SIZE(redir_control); ++ix) {
     707              36 :     if (NULL != (env = getenv(redir_control[ix].env_name))) {
     708               0 :       NaClLog(4, "getenv(%s) -> %s\n", redir_control[ix].env_name, env);
     709               0 :       ndp = NaClResourceOpen((struct NaClResource *) &nap->resources,
     710                 :                              env,
     711                 :                              redir_control[ix].nacl_flags,
     712                 :                              redir_control[ix].mode);
     713               0 :       NaClLog(4, " NaClResourceOpen returned %"NACL_PRIxPTR"\n",
     714                 :               (uintptr_t) ndp);
     715               0 :       if (NULL != ndp) {
     716               0 :         NaClLog(4, "Setting descriptor %d\n", (int) ix);
     717               0 :         NaClSetDesc(nap, (int) ix, ndp);
     718               0 :         ndp = NULL;
     719                 :       }
     720              36 :     } else if (NACL_RESOURCE_PHASE_START == nap->resource_phase) {
     721                 :       /*
     722                 :        * Environment not set -- handle default inheritance.
     723                 :        */
     724              36 :       NaClAddHostDescriptor(nap, DUP(redir_control[ix].d),
     725                 :                             redir_control[ix].nacl_flags, (int) ix);
     726                 :     }
     727                 :   }
     728              12 : }
     729                 : 
     730                 : /*
     731                 :  * Process default descriptor inheritance.  This means dup'ing
     732                 :  * descriptors 0-2 and making them available to the NaCl App.
     733                 :  *
     734                 :  * When standard input is inherited, this could result in a NaCl
     735                 :  * module competing for input from the terminal; for graphical /
     736                 :  * browser plugin environments, this never is allowed to happen, and
     737                 :  * having this is useful for debugging, and for potential standalone
     738                 :  * text-mode applications of NaCl.
     739                 :  *
     740                 :  * TODO(bsy): consider whether default inheritance should occur only
     741                 :  * in debug mode.
     742                 :  */
     743              12 : void NaClAppInitialDescriptorHookup(struct NaClApp  *nap) {
     744                 : 
     745              12 :   NaClLog(4, "Processing I/O redirection/inheritance from environment\n");
     746              12 :   nap->resource_phase = NACL_RESOURCE_PHASE_START;
     747              12 :   NaClProcessRedirControl(nap);
     748              12 :   NaClLog(4, "... done.\n");
     749              12 : }
     750                 : 
     751                 : void NaClAppVmmapUpdate(struct NaClApp    *nap,
     752                 :                         uintptr_t         page_num,
     753                 :                         size_t            npages,
     754                 :                         int               prot,
     755                 :                         struct NaClMemObj *nmop,
     756               0 :                         int               remove) {
     757               0 :   NaClXMutexLock(&nap->mu);
     758               0 :   NaClVmmapUpdate(&nap->mem_map,
     759                 :                   page_num,
     760                 :                   npages,
     761                 :                   prot,
     762                 :                   nmop,
     763                 :                   remove);
     764               0 :   NaClXMutexUnlock(&nap->mu);
     765               0 : }
     766                 : 
     767                 : uintptr_t NaClAppVmmapFindSpace(struct NaClApp  *nap,
     768               0 :                                 int             num_pages) {
     769                 :   uintptr_t rv;
     770                 : 
     771               0 :   NaClXMutexLock(&nap->mu);
     772               0 :   rv = NaClVmmapFindSpace(&nap->mem_map,
     773                 :                           num_pages);
     774               0 :   NaClXMutexUnlock(&nap->mu);
     775               0 :   return rv;
     776                 : }
     777                 : 
     778                 : uintptr_t NaClAppVmmapFindMapSpace(struct NaClApp *nap,
     779               0 :                                    int            num_pages) {
     780                 :   uintptr_t rv;
     781                 : 
     782               0 :   NaClXMutexLock(&nap->mu);
     783               0 :   rv = NaClVmmapFindMapSpace(&nap->mem_map,
     784                 :                              num_pages);
     785               0 :   NaClXMutexUnlock(&nap->mu);
     786               0 :   return rv;
     787                 : }
     788                 : 
     789               1 : void NaClCreateServiceSocket(struct NaClApp *nap) {
     790                 :   struct NaClDesc *pair[2];
     791                 : 
     792               1 :   NaClLog(3, "Entered NaClCreateServiceSocket\n");
     793               1 :   if (0 != NaClCommonDescMakeBoundSock(pair)) {
     794               0 :     NaClLog(LOG_FATAL, "Cound not create service socket\n");
     795                 :   }
     796               1 :   NaClLog(4,
     797                 :           "got bound socket at 0x%08"NACL_PRIxPTR", "
     798                 :           "addr at 0x%08"NACL_PRIxPTR"\n",
     799                 :           (uintptr_t) pair[0],
     800                 :           (uintptr_t) pair[1]);
     801               1 :   NaClSetDesc(nap, NACL_SERVICE_PORT_DESCRIPTOR, pair[0]);
     802               1 :   NaClSetDesc(nap, NACL_SERVICE_ADDRESS_DESCRIPTOR, pair[1]);
     803                 : 
     804               1 :   NaClDescSafeUnref(nap->service_port);
     805                 : 
     806               1 :   nap->service_port = pair[0];
     807               1 :   NaClDescRef(nap->service_port);
     808                 : 
     809               1 :   NaClDescSafeUnref(nap->service_address);
     810                 : 
     811               1 :   nap->service_address = pair[1];
     812               1 :   NaClDescRef(nap->service_address);
     813               1 :   NaClLog(4, "Leaving NaClCreateServiceSocket\n");
     814               1 : }
     815                 : 
     816                 : void NaClSendServiceAddressTo(struct NaClApp  *nap,
     817               0 :                               int             desc) {
     818                 :   struct NaClDesc             *channel;
     819                 :   struct NaClImcTypedMsgHdr   hdr;
     820                 :   ssize_t                     rv;
     821                 : 
     822               0 :   NaClLog(4,
     823                 :           "NaClSendServiceAddressTo(0x%08"NACL_PRIxPTR", %d)\n",
     824                 :           (uintptr_t) nap,
     825                 :           desc);
     826                 : 
     827               0 :   channel = NaClGetDesc(nap, desc);
     828               0 :   if (NULL == channel) {
     829               0 :     NaClLog(LOG_FATAL,
     830                 :             "NaClSendServiceAddressTo: descriptor %d not in open file table\n",
     831                 :             desc);
     832               0 :     return;
     833                 :   }
     834               0 :   if (NULL == nap->service_address) {
     835               0 :     NaClLog(LOG_FATAL,
     836                 :             "NaClSendServiceAddressTo: service address not set\n");
     837               0 :     return;
     838                 :   }
     839                 :   /*
     840                 :    * service_address and service_port are set together.
     841                 :    */
     842                 : 
     843               0 :   hdr.iov = (struct NaClImcMsgIoVec *) NULL;
     844               0 :   hdr.iov_length = 0;
     845               0 :   hdr.ndescv = &nap->service_address;
     846               0 :   hdr.ndesc_length = 1;
     847                 : 
     848               0 :   rv = NaClImcSendTypedMessage(channel, &hdr, 0);
     849                 : 
     850               0 :   NaClDescUnref(channel);
     851               0 :   channel = NULL;
     852                 : 
     853               0 :   NaClLog(1,
     854                 :           "NaClSendServiceAddressTo: descriptor %d, error %"NACL_PRIdS"\n",
     855                 :           desc,
     856                 :           rv);
     857                 : }
     858                 : 
     859                 : static void NaClSecureChannelShutdownRpc(
     860                 :     struct NaClSrpcRpc      *rpc,
     861                 :     struct NaClSrpcArg      **in_args,
     862                 :     struct NaClSrpcArg      **out_args,
     863               0 :     struct NaClSrpcClosure  *done) {
     864                 :   UNREFERENCED_PARAMETER(rpc);
     865                 :   UNREFERENCED_PARAMETER(in_args);
     866                 :   UNREFERENCED_PARAMETER(out_args);
     867                 :   UNREFERENCED_PARAMETER(done);
     868                 : 
     869               0 :   NaClLog(4, "NaClSecureChannelShutdownRpc (hard_shutdown), exiting\n");
     870               0 :   NaClExit(0);
     871                 :   /* Return is never reached, so no need to invoke (*done->Run)(done). */
     872               0 : }
     873                 : 
     874                 : /*
     875                 :  * This RPC is invoked by the plugin when the nexe is downloaded as a
     876                 :  * stream and not as a file. The only arguments are a handle to a
     877                 :  * shared memory object that contains the nexe.
     878                 :  */
     879                 : static void NaClLoadModuleRpc(struct NaClSrpcRpc      *rpc,
     880                 :                               struct NaClSrpcArg      **in_args,
     881                 :                               struct NaClSrpcArg      **out_args,
     882               0 :                               struct NaClSrpcClosure  *done) {
     883                 :   struct NaClApp          *nap =
     884               0 :       (struct NaClApp *) rpc->channel->server_instance_data;
     885               0 :   struct NaClDesc         *nexe_binary = in_args[0]->u.hval;
     886                 :   struct NaClGioShm       gio_shm;
     887                 :   struct NaClGioNaClDesc  gio_desc;
     888               0 :   struct Gio              *load_src = NULL;
     889                 :   struct nacl_abi_stat    stbuf;
     890                 :   char                    *aux;
     891                 :   int                     rval;
     892               0 :   NaClErrorCode           suberr = LOAD_INTERNAL;
     893                 :   size_t                  rounded_size;
     894                 : 
     895                 :   UNREFERENCED_PARAMETER(out_args);
     896                 : 
     897               0 :   NaClLog(4, "NaClLoadModuleRpc: entered\n");
     898                 : 
     899               0 :   rpc->result = NACL_SRPC_RESULT_INTERNAL;
     900                 : 
     901               0 :   aux = strdup(in_args[1]->arrays.str);
     902               0 :   if (NULL == aux) {
     903               0 :     rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
     904               0 :     goto cleanup;
     905                 :   }
     906               0 :   NaClLog(4, "Received aux_info: %s\n", aux);
     907                 : 
     908               0 :   switch (NACL_VTBL(NaClDesc, nexe_binary)->typeTag) {
     909                 :     case NACL_DESC_SHM:
     910                 :       /*
     911                 :        * We don't know the actual size of the nexe, but it should not
     912                 :        * matter.  The shared memory object's size is rounded up to at
     913                 :        * least 4K, and we can map it in with uninitialized data (should be
     914                 :        * zero filled) at the end.
     915                 :        */
     916               0 :       NaClLog(4, "NaClLoadModuleRpc: finding shm size\n");
     917                 : 
     918               0 :       rval = (*NACL_VTBL(NaClDesc, nexe_binary)->
     919                 :               Fstat)(nexe_binary, &stbuf);
     920               0 :       if (0 != rval) {
     921               0 :         goto cleanup;
     922                 :       }
     923                 : 
     924               0 :       rounded_size = (size_t) stbuf.nacl_abi_st_size;
     925                 : 
     926               0 :       NaClLog(4, "NaClLoadModuleRpc: shm size 0x%"NACL_PRIxS"\n", rounded_size);
     927                 : 
     928               0 :       if (!NaClGioShmCtor(&gio_shm, nexe_binary, rounded_size)) {
     929               0 :         rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
     930               0 :         goto cleanup;
     931                 :       }
     932               0 :       load_src = (struct Gio *) &gio_shm;
     933               0 :       break;
     934                 : 
     935                 :     case NACL_DESC_HOST_IO:
     936               0 :       NaClLog(4, "NaClLoadModuleRpc: creating Gio from NaClDescHostDesc\n");
     937                 : 
     938               0 :       if (!NaClGioNaClDescCtor(&gio_desc, nexe_binary)) {
     939               0 :         rpc->result = NACL_SRPC_RESULT_NO_MEMORY;
     940               0 :         goto cleanup;
     941                 :       }
     942               0 :       load_src = (struct Gio *) &gio_desc;
     943               0 :       break;
     944                 : 
     945                 :     case NACL_DESC_INVALID:
     946                 :     case NACL_DESC_DIR:
     947                 :     case NACL_DESC_CONN_CAP:
     948                 :     case NACL_DESC_CONN_CAP_FD:
     949                 :     case NACL_DESC_BOUND_SOCKET:
     950                 :     case NACL_DESC_CONNECTED_SOCKET:
     951                 :     case NACL_DESC_SYSV_SHM:
     952                 :     case NACL_DESC_MUTEX:
     953                 :     case NACL_DESC_CONDVAR:
     954                 :     case NACL_DESC_SEMAPHORE:
     955                 :     case NACL_DESC_SYNC_SOCKET:
     956                 :     case NACL_DESC_TRANSFERABLE_DATA_SOCKET:
     957                 :     case NACL_DESC_IMC_SOCKET:
     958                 :     case NACL_DESC_QUOTA:
     959                 :     case NACL_DESC_DEVICE_RNG:
     960                 :     case NACL_DESC_DEVICE_POSTMESSAGE:
     961                 :       /* Unsupported stuff */
     962               0 :       rpc->result = NACL_SRPC_RESULT_APP_ERROR;
     963               0 :       goto cleanup;
     964                 :   }
     965                 : 
     966                 :   /*
     967                 :    * do not use default case label, to make sure that the compiler
     968                 :    * will generate a warning with -Wswitch-enum for new entries in
     969                 :    * NaClDescTypeTag introduced in nacl_desc_base.h for which there is no
     970                 :    * corresponding entry here.  instead, we pretend that fall-through
     971                 :    * from the switch is possible.
     972                 :    */
     973               0 :   if (NULL == load_src) {
     974               0 :     NaClLog(LOG_FATAL, "nexe_binary's typeTag has unsupported value: %d\n",
     975                 :             NACL_VTBL(NaClDesc, nexe_binary)->typeTag);
     976                 :   }
     977                 : 
     978                 :   /*
     979                 :    * TODO(bsy): consider doing the processing below after sending the
     980                 :    * RPC reply to increase parallelism.
     981                 :    */
     982                 : 
     983               0 :   NaClXMutexLock(&nap->mu);
     984                 : 
     985               0 :   if (LOAD_STATUS_UNKNOWN != nap->module_load_status) {
     986               0 :     NaClLog(LOG_ERROR, "Repeated LoadModule RPC, or platform qual error?!?\n");
     987               0 :     if (LOAD_OK == nap->module_load_status) {
     988               0 :       NaClLog(LOG_ERROR, "LoadModule when module_load_status is LOAD_OK?!?\n");
     989               0 :       suberr = LOAD_DUP_LOAD_MODULE;
     990               0 :       nap->module_load_status = suberr;
     991                 :     } else {
     992               0 :       suberr = nap->module_load_status;
     993                 :     }
     994               0 :     rpc->result = NACL_SRPC_RESULT_OK;
     995               0 :     NaClXCondVarBroadcast(&nap->cv);
     996               0 :     goto cleanup_status_mu;
     997                 :   }
     998                 : 
     999               0 :   free(nap->aux_info);
    1000               0 :   nap->aux_info = aux;
    1001                 : 
    1002               0 :   suberr = NACL_FI_VAL("load_module", NaClErrorCode,
    1003                 :                        NaClAppLoadFile(load_src, nap));
    1004               0 :   (*NACL_VTBL(Gio, load_src)->Close)(load_src);
    1005               0 :   (*NACL_VTBL(Gio, load_src)->Dtor)(load_src);
    1006                 : 
    1007               0 :   if (LOAD_OK != suberr) {
    1008               0 :     nap->module_load_status = suberr;
    1009               0 :     rpc->result = NACL_SRPC_RESULT_OK;
    1010               0 :     NaClXCondVarBroadcast(&nap->cv);
    1011                 :   }
    1012                 : 
    1013               0 :  cleanup_status_mu:
    1014               0 :   NaClXMutexUnlock(&nap->mu);  /* NaClAppPrepareToLaunch takes mu */
    1015               0 :   if (LOAD_OK != suberr) {
    1016               0 :     goto cleanup;
    1017                 :   }
    1018                 : 
    1019                 :   /***************************************************************************
    1020                 :    * TODO(bsy): Remove/merge the code invoking NaClAppPrepareToLaunch
    1021                 :    * and NaClGdbHook below with sel_main's main function.  See comment
    1022                 :    * there.
    1023                 :    ***************************************************************************/
    1024                 : 
    1025                 :   /*
    1026                 :    * Finish setting up the NaCl App.
    1027                 :    */
    1028               0 :   suberr = NaClAppPrepareToLaunch(nap);
    1029                 : 
    1030               0 :   NaClXMutexLock(&nap->mu);
    1031                 : 
    1032               0 :   nap->module_load_status = suberr;
    1033               0 :   rpc->result = NACL_SRPC_RESULT_OK;
    1034                 : 
    1035               0 :   NaClXCondVarBroadcast(&nap->cv);
    1036               0 :   NaClXMutexUnlock(&nap->mu);
    1037                 : 
    1038                 :   /* Give debuggers a well known point at which xlate_base is known.  */
    1039               0 :   NaClGdbHook(nap);
    1040                 : 
    1041               0 :  cleanup:
    1042                 : 
    1043               0 :   NaClDescUnref(nexe_binary);
    1044               0 :   nexe_binary = NULL;
    1045               0 :   (*done->Run)(done);
    1046               0 : }
    1047                 : 
    1048                 : #if NACL_WINDOWS && !defined(NACL_STANDALONE)
    1049                 : /*
    1050                 :  * This RPC is invoked by the plugin as part of the initialization process and
    1051                 :  * provides the NaCl process with a socket address that can later be used for
    1052                 :  * pid to process handle mapping queries. This is required to enable IMC handle
    1053                 :  * passing inside the Chrome sandbox.
    1054                 :  */
    1055                 : static void NaClInitHandlePassingRpc(struct NaClSrpcRpc      *rpc,
    1056                 :                                      struct NaClSrpcArg      **in_args,
    1057                 :                                      struct NaClSrpcArg      **out_args,
    1058                 :                                      struct NaClSrpcClosure  *done) {
    1059                 :   struct NaClApp  *nap = (struct NaClApp *) rpc->channel->server_instance_data;
    1060                 :   NaClSrpcImcDescType handle_passing_socket_address = in_args[0]->u.hval;
    1061                 :   DWORD renderer_pid = in_args[1]->u.ival;
    1062                 :   NaClHandle renderer_handle = (NaClHandle)in_args[2]->u.ival;
    1063                 :   UNREFERENCED_PARAMETER(out_args);
    1064                 :   if (!NaClHandlePassLdrCtor(handle_passing_socket_address,
    1065                 :                              renderer_pid,
    1066                 :                              renderer_handle)) {
    1067                 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
    1068                 :   } else {
    1069                 :     rpc->result = NACL_SRPC_RESULT_OK;
    1070                 :   }
    1071                 :   (*done->Run)(done);
    1072                 : }
    1073                 : #endif
    1074                 : 
    1075               0 : NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) {
    1076                 :   NaClErrorCode status;
    1077                 : 
    1078               0 :   NaClXMutexLock(&nap->mu);
    1079               0 :   while (LOAD_STATUS_UNKNOWN == (status = nap->module_load_status)) {
    1080               0 :     NaClXCondVarWait(&nap->cv, &nap->mu);
    1081                 :   }
    1082               0 :   NaClXMutexUnlock(&nap->mu);
    1083               0 :   return status;
    1084                 : }
    1085                 : 
    1086                 : static void NaClSecureChannelStartModuleRpc(struct NaClSrpcRpc     *rpc,
    1087                 :                                             struct NaClSrpcArg     **in_args,
    1088                 :                                             struct NaClSrpcArg     **out_args,
    1089               0 :                                             struct NaClSrpcClosure *done) {
    1090                 :   /*
    1091                 :    * let module start if module is okay; otherwise report error (e.g.,
    1092                 :    * ABI version mismatch).
    1093                 :    */
    1094               0 :   struct NaClApp  *nap = (struct NaClApp *) rpc->channel->server_instance_data;
    1095                 :   NaClErrorCode   status;
    1096                 : 
    1097                 :   UNREFERENCED_PARAMETER(in_args);
    1098                 : 
    1099               0 :   NaClLog(4,
    1100                 :           "NaClSecureChannelStartModuleRpc started, nap 0x%"NACL_PRIxPTR"\n",
    1101                 :           (uintptr_t) nap);
    1102                 : 
    1103               0 :   status = NaClWaitForLoadModuleStatus(nap);
    1104                 : 
    1105               0 :   NaClLog(4, "NaClSecureChannelStartModuleRpc: load status %d\n", status);
    1106                 : 
    1107               0 :   out_args[0]->u.ival = status;
    1108               0 :   rpc->result = NACL_SRPC_RESULT_OK;
    1109                 : 
    1110               0 :   NaClLog(4, "NaClSecureChannelStartModuleRpc running closure\n");
    1111               0 :   (*done->Run)(done);
    1112                 :   /*
    1113                 :    * The RPC reply is now sent.  This has to occur before we signal
    1114                 :    * the main thread to possibly start, since in the case of a failure
    1115                 :    * the main thread may quickly exit.  If the main thread does this
    1116                 :    * before we sent the RPC reply, then the plugin will be left
    1117                 :    * without an answer.
    1118                 :    */
    1119                 : 
    1120               0 :   NaClXMutexLock(&nap->mu);
    1121               0 :   if (nap->module_may_start) {
    1122               0 :     NaClLog(LOG_ERROR, "Duplicate StartModule RPC?!?\n");
    1123               0 :     status = LOAD_DUP_START_MODULE;
    1124                 :   } else {
    1125               0 :     nap->module_may_start = 1;
    1126                 :   }
    1127               0 :   NaClLog(4, "NaClSecureChannelStartModuleRpc: broadcasting\n");
    1128               0 :   NaClXCondVarBroadcast(&nap->cv);
    1129               0 :   NaClXMutexUnlock(&nap->mu);
    1130                 : 
    1131               0 :   NaClLog(4, "NaClSecureChannelStartModuleRpc exiting\n");
    1132               0 : }
    1133                 : 
    1134                 : static void NaClSecureChannelLog(struct NaClSrpcRpc      *rpc,
    1135                 :                                  struct NaClSrpcArg      **in_args,
    1136                 :                                  struct NaClSrpcArg      **out_args,
    1137               0 :                                  struct NaClSrpcClosure  *done) {
    1138               0 :   int severity = in_args[0]->u.ival;
    1139               0 :   char *msg = in_args[1]->arrays.str;
    1140                 : 
    1141                 :   UNREFERENCED_PARAMETER(out_args);
    1142                 : 
    1143               0 :   NaClLog(5, "NaClSecureChannelLog started\n");
    1144               0 :   NaClLog(severity, "%s\n", msg);
    1145               0 :   NaClLog(5, "NaClSecureChannelLog finished\n");
    1146               0 :   rpc->result = NACL_SRPC_RESULT_OK;
    1147               0 :   (*done->Run)(done);
    1148               0 : }
    1149                 : 
    1150               0 : NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) {
    1151                 :   NaClErrorCode status;
    1152                 : 
    1153               0 :   NaClLog(4, "NaClWaitForStartModuleCommand started\n");
    1154               0 :   NaClXMutexLock(&nap->mu);
    1155               0 :   while (!nap->module_may_start) {
    1156               0 :     NaClXCondVarWait(&nap->cv, &nap->mu);
    1157               0 :     NaClLog(4,
    1158                 :             "NaClWaitForStartModuleCommand: awaken, module_may_start %d\n",
    1159                 :             nap->module_may_start);
    1160                 :   }
    1161               0 :   status = nap->module_load_status;
    1162               0 :   NaClXMutexUnlock(&nap->mu);
    1163               0 :   NaClLog(4, "NaClWaitForStartModuleCommand finished\n");
    1164                 : 
    1165               0 :   return status;
    1166                 : }
    1167                 : 
    1168               8 : void NaClBlockIfCommandChannelExists(struct NaClApp *nap) {
    1169               8 :   if (NULL != nap->secure_service) {
    1170                 :     for (;;) {
    1171                 :       struct nacl_abi_timespec req;
    1172               0 :       req.tv_sec = 1000;
    1173               0 :       req.tv_nsec = 0;
    1174               0 :       NaClNanosleep(&req, (struct nacl_abi_timespec *) NULL);
    1175               0 :     }
    1176                 :   }
    1177               8 : }
    1178                 : 
    1179                 : 
    1180                 : /*
    1181                 :  * Secure command channels.
    1182                 :  */
    1183                 : 
    1184                 : struct NaClSecureService {
    1185                 :   struct NaClSimpleService      base;
    1186                 :   struct NaClApp                *nap;
    1187                 : };
    1188                 : 
    1189                 : struct NaClSimpleServiceVtbl const kNaClSecureServiceVtbl;
    1190                 : 
    1191                 : 
    1192                 : struct NaClConnectionHandler {
    1193                 :   struct NaClConnectionHandler  *next;
    1194                 : 
    1195                 :   /* used by NaClSimpleRevServiceClient's ClientCallback fn */
    1196                 :   void                          (*handler)(
    1197                 :       void                        *state,
    1198                 :       struct NaClThreadInterface  *tif,
    1199                 :       struct NaClDesc             *conn);
    1200                 :   void                          *state;
    1201                 : };
    1202                 : 
    1203                 : struct NaClSecureReverseClient {
    1204                 :   struct NaClSimpleRevClient        base;
    1205                 :   struct NaClApp                    *nap;
    1206                 : 
    1207                 :   struct NaClMutex                  mu;
    1208                 : 
    1209                 :   struct NaClConnectionHandler      *queue_head;
    1210                 :   struct NaClConnectionHandler      **queue_insert;
    1211                 : };
    1212                 : 
    1213                 : struct NaClSimpleRevClientVtbl const kNaClSecureReverseClientVtbl;
    1214                 : 
    1215                 : 
    1216                 : int NaClSecureServiceCtor(struct NaClSecureService          *self,
    1217                 :                           struct NaClSrpcHandlerDesc const  *srpc_handlers,
    1218               0 :                           struct NaClApp                    *nap) {
    1219               0 :   NaClLog(4,
    1220                 :           "Entered NaClSecureServiceCtor: self 0x%"NACL_PRIxPTR"\n",
    1221                 :           (uintptr_t) self);
    1222               0 :   if (!NaClSimpleServiceWithSocketCtor(&self->base,
    1223                 :                                        srpc_handlers,
    1224                 :                                        NaClThreadInterfaceThreadFactory,
    1225                 :                                        (void *) NULL,
    1226                 :                                        nap->service_port,
    1227                 :                                        nap->service_address)) {
    1228               0 :     goto failure_simple_ctor;
    1229                 :   }
    1230               0 :   self->nap = nap;
    1231                 : 
    1232               0 :   NACL_VTBL(NaClRefCount, self) =
    1233                 :       (struct NaClRefCountVtbl *) &kNaClSecureServiceVtbl;
    1234               0 :   return 1;
    1235               0 :  failure_simple_ctor:
    1236               0 :   return 0;
    1237                 : }
    1238                 : 
    1239               0 : void NaClSecureServiceDtor(struct NaClRefCount *vself) {
    1240               0 :   struct NaClSecureService *self = (struct NaClSecureService *) vself;
    1241                 : 
    1242               0 :   NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
    1243                 :       &kNaClSimpleServiceVtbl;
    1244               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
    1245               0 : }
    1246                 : 
    1247                 : /*
    1248                 :  * The first connection is performed by this callback handler.  This
    1249                 :  * spawns a client thread that will bootstrap the other connections by
    1250                 :  * stashing the connection represented by |conn| to make reverse RPCs
    1251                 :  * to ask the peer to connect to us.  No thread is spawned; we just
    1252                 :  * wrap access to the connection with a lock.
    1253                 :  *
    1254                 :  * Subsequent connection callbacks will pass the connection to the
    1255                 :  * actual thread that made the connection request using |conn|
    1256                 :  * received in the first connection.
    1257                 :  */
    1258                 : static void NaClSecureReverseClientCallback(
    1259                 :     void                        *state,
    1260                 :     struct NaClThreadInterface  *tif,
    1261               0 :     struct NaClDesc             *new_conn) {
    1262                 :   struct NaClSecureReverseClient *self =
    1263               0 :       (struct NaClSecureReverseClient *) state;
    1264               0 :   struct NaClApp *nap = self->nap;
    1265                 : 
    1266                 :   UNREFERENCED_PARAMETER(tif);
    1267                 : 
    1268               0 :   NaClLog(4, "Entered NaClSecureReverseClientCallback\n");
    1269                 : 
    1270               0 :   NaClLog(4, " self=0x%"NACL_PRIxPTR"\n", (uintptr_t) self);
    1271               0 :   NaClLog(4, " nap=0x%"NACL_PRIxPTR"\n", (uintptr_t) nap);
    1272               0 :   NaClXMutexLock(&nap->mu);
    1273                 : 
    1274               0 :   if (NACL_REVERSE_CHANNEL_INITIALIZATION_STARTED !=
    1275                 :       nap->reverse_channel_initialization_state) {
    1276                 :     /*
    1277                 :      * The reverse channel connection capability is used to make the
    1278                 :      * RPC that invokes this callback (this callback is invoked on a
    1279                 :      * reverse channel connect), so the plugin wants to initialize the
    1280                 :      * reverse channel and in particular the state must be either be
    1281                 :      * in-progress or finished.
    1282                 :      */
    1283               0 :     NaClLog(LOG_FATAL, "Reverse channel already initialized\n");
    1284                 :   }
    1285               0 :   if (!NaClSrpcClientCtor(&nap->reverse_channel, new_conn)) {
    1286               0 :     NaClLog(LOG_FATAL, "Reverse channel SRPC Client Ctor failed\n");
    1287                 :   }
    1288               0 :   nap->reverse_quota_interface = (struct NaClReverseQuotaInterface *)
    1289                 :       malloc(sizeof *nap->reverse_quota_interface);
    1290               0 :   if (NULL == nap->reverse_quota_interface ||
    1291                 :       !NaClReverseQuotaInterfaceCtor(nap->reverse_quota_interface, nap)) {
    1292               0 :     NaClLog(LOG_FATAL, "Reverse quota interface Ctor failed\n");
    1293                 :   }
    1294               0 :   nap->reverse_channel_initialization_state = NACL_REVERSE_CHANNEL_INITIALIZED;
    1295                 : 
    1296               0 :   NaClXCondVarBroadcast(&nap->cv);
    1297               0 :   NaClXMutexUnlock(&nap->mu);
    1298                 : 
    1299               0 :   NaClLog(4, "Leaving NaClSecureReverseClientCallback\n");
    1300               0 : }
    1301                 : 
    1302                 : /* fwd */
    1303                 : int NaClSecureReverseClientCtor(
    1304                 :     struct NaClSecureReverseClient *self,
    1305                 :     void                            (*client_callback)(
    1306                 :         void *, struct NaClThreadInterface *, struct NaClDesc *),
    1307                 :     void                            *state,
    1308                 :     struct NaClApp                  *nap);
    1309                 : 
    1310                 : static void NaClSecureReverseClientSetup(struct NaClSrpcRpc     *rpc,
    1311                 :                                          struct NaClSrpcArg     **in_args,
    1312                 :                                          struct NaClSrpcArg     **out_args,
    1313               0 :                                          struct NaClSrpcClosure *done) {
    1314                 :   struct NaClApp                  *nap =
    1315               0 :       (struct NaClApp *) rpc->channel->server_instance_data;
    1316                 :   struct NaClSecureReverseClient  *rev;
    1317                 : 
    1318                 :   UNREFERENCED_PARAMETER(in_args);
    1319               0 :   NaClLog(4, "Entered NaClSecureReverseClientSetup\n");
    1320                 : 
    1321               0 :   NaClXMutexLock(&nap->mu);
    1322               0 :   if (NULL != nap->reverse_client) {
    1323               0 :     NaClLog(LOG_FATAL, "Double reverse setup RPC\n");
    1324                 :   }
    1325               0 :   if (NACL_REVERSE_CHANNEL_UNINITIALIZED !=
    1326                 :       nap->reverse_channel_initialization_state) {
    1327               0 :     NaClLog(LOG_FATAL,
    1328                 :             "Reverse channel initialization state not uninitialized\n");
    1329                 :   }
    1330               0 :   nap->reverse_channel_initialization_state =
    1331                 :       NACL_REVERSE_CHANNEL_INITIALIZATION_STARTED;
    1332                 :   /* the reverse connection is still coming */
    1333               0 :   rev = (struct NaClSecureReverseClient *) malloc(sizeof *rev);
    1334               0 :   if (NULL == rev) {
    1335               0 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
    1336               0 :     goto done;
    1337                 :   }
    1338               0 :   NaClLog(4,
    1339                 :           "NaClSecureReverseClientSetup: invoking"
    1340                 :           " NaClSecureReverseClientCtor\n");
    1341               0 :   if (!NaClSecureReverseClientCtor(rev,
    1342                 :                                    NaClSecureReverseClientCallback,
    1343                 :                                    (void *) rev,
    1344                 :                                    nap)) {
    1345               0 :     free(rev);
    1346               0 :     rpc->result = NACL_SRPC_RESULT_APP_ERROR;
    1347               0 :     goto done;
    1348                 :   }
    1349               0 :   nap->reverse_client = (struct NaClSecureReverseClient *) NaClRefCountRef(
    1350                 :       (struct NaClRefCount *) rev);
    1351               0 :   out_args[0]->u.hval = NaClDescRef(rev->base.bound_and_cap[1]);
    1352               0 :   rpc->result = NACL_SRPC_RESULT_OK;
    1353                 : 
    1354                 :   /*
    1355                 :    * Hook up reverse-channel enabled resources, e.g.,
    1356                 :    * DEBUG_ONLY:dev://postmessage.  NB: Resources specified by
    1357                 :    * file:path should have been taken care of earlier, in
    1358                 :    * NaClAppInitialDescriptorHookup.
    1359                 :    */
    1360               0 :   nap->resource_phase = NACL_RESOURCE_PHASE_REV_CHAN;
    1361               0 :   NaClLog(4, "Processing dev I/O redirection/inheritance from environment\n");
    1362               0 :   NaClProcessRedirControl(nap);
    1363               0 :   NaClLog(4, "... done.\n");
    1364                 : 
    1365                 :   /*
    1366                 :    * Service thread takes the reference rev.
    1367                 :    */
    1368               0 :   if (!NaClSimpleRevClientStartServiceThread(&rev->base)) {
    1369               0 :     NaClLog(LOG_FATAL, "Could not start reverse service thread\n");
    1370                 :   }
    1371                 : 
    1372               0 : done:
    1373               0 :   NaClXMutexUnlock(&nap->mu);
    1374               0 :   (*done->Run)(done);
    1375               0 :   NaClLog(4, "Leaving NaClSecureReverseClientSetup\n");
    1376               0 : }
    1377                 : 
    1378                 : /*
    1379                 :  * Only called at startup and thereafter by the reverse secure
    1380                 :  * channel, with |self| locked.
    1381                 :  */
    1382                 : static
    1383                 : int NaClSecureReverseClientInsertHandler_mu(
    1384                 :     struct NaClSecureReverseClient  *self,
    1385                 :     void                            (*h)(void *,
    1386                 :                                          struct NaClThreadInterface *,
    1387                 :                                          struct NaClDesc *),
    1388               0 :     void                            *d) {
    1389                 :   struct NaClConnectionHandler *entry;
    1390                 : 
    1391               0 :   NaClLog(4,
    1392                 :           ("NaClSecureReverseClientInsertHandler_mu: h 0x%"NACL_PRIxPTR","
    1393                 :            " d 0x%"NACL_PRIxPTR"\n"),
    1394                 :           (uintptr_t) h,
    1395                 :           (uintptr_t) d);
    1396               0 :   entry = (struct NaClConnectionHandler *) malloc(sizeof *entry);
    1397               0 :   if (NULL == entry) {
    1398               0 :     return 0;
    1399                 :   }
    1400               0 :   entry->handler = h;
    1401               0 :   entry->state = d;
    1402               0 :   entry->next = (struct NaClConnectionHandler *) NULL;
    1403               0 :   *self->queue_insert = entry;
    1404               0 :   self->queue_insert = &entry->next;
    1405                 : 
    1406               0 :   return 1;
    1407                 : }
    1408                 : 
    1409                 : /*
    1410                 :  * Caller must set up handler before issuing connection request RPC on
    1411                 :  * nap->reverse_channel, since otherwise the connection handler queue
    1412                 :  * may be empty and the connect code would abort.  Because the connect
    1413                 :  * doesn't wait for a handler, we don't need a condvar.
    1414                 :  *
    1415                 :  * We do not need to serialize on the handlers, since the
    1416                 :  * RPC-server/IMC-client implementation should not distinguish one
    1417                 :  * connection from another: it is okay for two handlers to be
    1418                 :  * inserted, and two connection request RPCs to be preformed
    1419                 :  * (sequentially, since they are over a single channel), and have the
    1420                 :  * server side spawn threads that asynchronously connect twice, in the
    1421                 :  * "incorrect" order, etc.
    1422                 :  */
    1423                 : int NaClSecureReverseClientInsertHandler(
    1424                 :     struct NaClSecureReverseClient *self,
    1425                 :     void                            (*handler)(
    1426                 :         void                        *handlr_state,
    1427                 :         struct NaClThreadInterface  *thread_if,
    1428                 :         struct NaClDesc             *new_conn),
    1429               0 :     void                            *handler_state) {
    1430                 :   int retval;
    1431                 : 
    1432               0 :   NaClXMutexLock(&self->mu);
    1433               0 :   retval = NaClSecureReverseClientInsertHandler_mu(self,
    1434                 :                                                    handler, handler_state);
    1435               0 :   NaClXMutexUnlock(&self->mu);
    1436               0 :   return retval;
    1437                 : }
    1438                 : 
    1439                 : static
    1440                 : struct NaClConnectionHandler *NaClSecureReverseClientPopHandler(
    1441               0 :     struct NaClSecureReverseClient *self) {
    1442                 :   struct NaClConnectionHandler *head;
    1443                 : 
    1444               0 :   NaClLog(4, "Entered NaClSecureReverseClientPopHandler, acquiring lock\n");
    1445               0 :   NaClXMutexLock(&self->mu);
    1446               0 :   NaClLog(4, "NaClSecureReverseClientPopHandler, got lock\n");
    1447               0 :   head = self->queue_head;
    1448               0 :   if (NULL == head) {
    1449               0 :     NaClLog(LOG_FATAL,
    1450                 :             "NaClSecureReverseClientPopHandler:  empty handler queue\n");
    1451                 :   }
    1452               0 :   if (NULL == (self->queue_head = head->next)) {
    1453               0 :     NaClLog(4, "NaClSecureReverseClientPopHandler, last elt patch up\n");
    1454               0 :     self->queue_insert = &self->queue_head;
    1455                 :   }
    1456               0 :   NaClLog(4, "NaClSecureReverseClientPopHandler, unlocking\n");
    1457               0 :   NaClXMutexUnlock(&self->mu);
    1458                 : 
    1459               0 :   head->next = NULL;
    1460               0 :   NaClLog(4,
    1461                 :           ("Leaving NaClSecureReverseClientPopHandler:"
    1462                 :            " returning %"NACL_PRIxPTR"\n"),
    1463                 :           (uintptr_t) head);
    1464               0 :   return head;
    1465                 : }
    1466                 : 
    1467                 : static
    1468                 : void NaClSecureReverseClientInternalCallback(
    1469                 :     void                        *state,
    1470                 :     struct NaClThreadInterface  *tif,
    1471               0 :     struct NaClDesc             *conn) {
    1472                 :   struct NaClSecureReverseClient *self =
    1473               0 :       (struct NaClSecureReverseClient *) state;
    1474                 :   struct NaClConnectionHandler *hand_ptr;
    1475                 : 
    1476                 :   UNREFERENCED_PARAMETER(tif);
    1477               0 :   NaClLog(4, "Entered NaClSecureReverseClientInternalCallback\n");
    1478               0 :   hand_ptr = NaClSecureReverseClientPopHandler(self);
    1479               0 :   NaClLog(4, " got callback object %"NACL_PRIxPTR"\n", (uintptr_t) hand_ptr);
    1480               0 :   NaClLog(4,
    1481                 :           " callback:0x%"NACL_PRIxPTR"(0x%"NACL_PRIxPTR",0x%"NACL_PRIxPTR")\n",
    1482                 :           (uintptr_t) hand_ptr->handler,
    1483                 :           (uintptr_t) hand_ptr->state,
    1484                 :           (uintptr_t) conn);
    1485               0 :   (*hand_ptr->handler)(hand_ptr->state, tif, conn);
    1486               0 :   NaClLog(4, "NaClSecureReverseClientInternalCallback: freeing memory\n");
    1487               0 :   free(hand_ptr);
    1488               0 :   NaClLog(4, "Leaving NaClSecureReverseClientInternalCallback\n");
    1489               0 : }
    1490                 : 
    1491                 : /*
    1492                 :  * Require an initial connection handler in the Ctor, so that it's
    1493                 :  * obvious that a reverse client needs to accept an IMC connection
    1494                 :  * from the server to get things bootstrapped.
    1495                 :  */
    1496                 : int NaClSecureReverseClientCtor(
    1497                 :     struct NaClSecureReverseClient  *self,
    1498                 :     void                            (*client_callback)(
    1499                 :         void *, struct NaClThreadInterface*, struct NaClDesc *),
    1500                 :     void                            *state,
    1501               0 :     struct NaClApp                  *nap) {
    1502               0 :   NaClLog(4,
    1503                 :           ("Entered NaClSecureReverseClientCtor, self 0x%"NACL_PRIxPTR","
    1504                 :            " nap 0x%"NACL_PRIxPTR"\n"),
    1505                 :           (uintptr_t) self,
    1506                 :           (uintptr_t) nap);
    1507               0 :   if (!NaClSimpleRevClientCtor(&self->base,
    1508                 :                                NaClSecureReverseClientInternalCallback,
    1509                 :                                (void *) self,
    1510                 :                                NaClThreadInterfaceThreadFactory,
    1511                 :                                (void *) NULL)) {
    1512               0 :     goto failure_simple_ctor;
    1513                 :   }
    1514               0 :   NaClLog(4, "NaClSecureReverseClientCtor: Mutex\n");
    1515               0 :   if (!NaClMutexCtor(&self->mu)) {
    1516               0 :     goto failure_mutex_ctor;
    1517                 :   }
    1518               0 :   self->nap = nap;
    1519               0 :   self->queue_head = (struct NaClConnectionHandler *) NULL;
    1520               0 :   self->queue_insert = &self->queue_head;
    1521                 : 
    1522               0 :   NACL_VTBL(NaClRefCount, self) =
    1523                 :       (struct NaClRefCountVtbl *) &kNaClSecureReverseClientVtbl;
    1524                 : 
    1525               0 :   NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler\n");
    1526               0 :   if (!NaClSecureReverseClientInsertHandler(self,
    1527                 :                                             client_callback,
    1528                 :                                             state)) {
    1529               0 :     goto failure_handler_insert;
    1530                 :   }
    1531                 : 
    1532               0 :   NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
    1533               0 :   return 1;
    1534                 : 
    1535               0 :  failure_handler_insert:
    1536               0 :   NaClLog(4, "NaClSecureReverseClientCtor: InsertHandler failed\n");
    1537               0 :   NACL_VTBL(NaClRefCount, self) =
    1538                 :       (struct NaClRefCountVtbl *) &kNaClSimpleRevClientVtbl;
    1539                 : 
    1540               0 :   self->nap = NULL;
    1541               0 :   self->queue_insert = (struct NaClConnectionHandler **) NULL;
    1542               0 :   NaClMutexDtor(&self->mu);
    1543                 : 
    1544               0 :  failure_mutex_ctor:
    1545               0 :   NaClLog(4, "NaClSecureReverseClientCtor: Mutex failed\n");
    1546               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
    1547               0 :  failure_simple_ctor:
    1548               0 :   NaClLog(4, "Leaving NaClSecureReverseClientCtor\n");
    1549               0 :   return 0;
    1550                 : }
    1551                 : 
    1552               0 : void NaClSecureReverseClientDtor(struct NaClRefCount *vself) {
    1553                 :   struct NaClSecureReverseClient *self =
    1554               0 :       (struct NaClSecureReverseClient *) vself;
    1555                 : 
    1556                 :   struct NaClConnectionHandler  *entry;
    1557                 :   struct NaClConnectionHandler  *next;
    1558                 : 
    1559               0 :   for (entry = self->queue_head; NULL != entry; entry = next) {
    1560               0 :     next = entry->next;
    1561               0 :     free(entry);
    1562                 :   }
    1563               0 :   NaClMutexDtor(&self->mu);
    1564                 : 
    1565               0 :   NACL_VTBL(NaClRefCount, self) = (struct NaClRefCountVtbl const *)
    1566                 :       &kNaClSimpleRevClientVtbl;
    1567               0 :   (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
    1568               0 : }
    1569                 : 
    1570                 : int NaClSecureServiceConnectionFactory(
    1571                 :     struct NaClSimpleService            *vself,
    1572                 :     struct NaClDesc                     *conn,
    1573               0 :     struct NaClSimpleServiceConnection  **out) {
    1574                 :   struct NaClSecureService *self =
    1575               0 :       (struct NaClSecureService *) vself;
    1576                 : 
    1577                 :   /* our instance_data is not connection specific */
    1578               0 :   return NaClSimpleServiceConnectionFactoryWithInstanceData(
    1579                 :       vself, conn, (void *) self->nap, out);
    1580                 : }
    1581                 : 
    1582               0 : int NaClSecureServiceAcceptAndSpawnHandler(struct NaClSimpleService *vself) {
    1583                 :   int rv;
    1584                 : 
    1585               0 :   NaClLog(4,
    1586                 :           "NaClSecureServiceAcceptAndSpawnHandler: invoking base class vfn\n");
    1587               0 :   rv = (*kNaClSimpleServiceVtbl.AcceptAndSpawnHandler)(vself);
    1588               0 :   if (0 != rv) {
    1589               0 :     NaClLog(LOG_FATAL,
    1590                 :             "Secure channel AcceptAndSpawnHandler returned %d\n",
    1591                 :             rv);
    1592                 :   }
    1593               0 :   NaClThreadExit(0);
    1594                 :   /*
    1595                 :    * NOTREACHED The port is now to be used by untrusted code: all
    1596                 :    * subsequent connections are handled there.
    1597                 :    */
    1598               0 :   return rv;
    1599                 : }
    1600                 : 
    1601                 : void NaClSecureServiceRpcHandler(struct NaClSimpleService           *vself,
    1602               0 :                                  struct NaClSimpleServiceConnection *vconn) {
    1603                 : 
    1604               0 :   NaClLog(4, "NaClSecureChannelThread started\n");
    1605               0 :   (*kNaClSimpleServiceVtbl.RpcHandler)(vself, vconn);
    1606               0 :   NaClLog(4, "NaClSecureChannelThread: channel closed, exiting.\n");
    1607               0 :   NaClExit(0);
    1608               0 : }
    1609                 : 
    1610                 : struct NaClSimpleServiceVtbl const kNaClSecureServiceVtbl = {
    1611                 :   {
    1612                 :     NaClSecureServiceDtor,
    1613                 :   },
    1614                 :   NaClSecureServiceConnectionFactory,
    1615                 :   NaClSimpleServiceAcceptConnection,
    1616                 :   NaClSecureServiceAcceptAndSpawnHandler,
    1617                 :   NaClSecureServiceRpcHandler,
    1618                 : };
    1619                 : 
    1620                 : struct NaClSimpleRevClientVtbl const kNaClSecureReverseClientVtbl = {
    1621                 :   {
    1622                 :     NaClSecureReverseClientDtor,
    1623                 :   },
    1624                 : };
    1625                 : 
    1626                 : 
    1627               0 : void NaClSecureCommandChannel(struct NaClApp *nap) {
    1628                 :   struct NaClSecureService *secure_command_server;
    1629                 : 
    1630                 :   static struct NaClSrpcHandlerDesc const secure_handlers[] = {
    1631                 :     { "hard_shutdown::", NaClSecureChannelShutdownRpc, },
    1632                 :     { "start_module::i", NaClSecureChannelStartModuleRpc, },
    1633                 :     { "log:is:", NaClSecureChannelLog, },
    1634                 :     { "load_module:hs:", NaClLoadModuleRpc, },
    1635                 : #if NACL_WINDOWS && !defined(NACL_STANDALONE)
    1636                 :     { "init_handle_passing:hii:", NaClInitHandlePassingRpc, },
    1637                 : #endif
    1638                 :     { "reverse_setup::h", NaClSecureReverseClientSetup, },
    1639                 :     /* add additional calls here.  upcall set up?  start module signal? */
    1640                 :     { (char const *) NULL, (NaClSrpcMethod) NULL, },
    1641                 :   };
    1642                 : 
    1643               0 :   NaClLog(4, "Entered NaClSecureCommandChannel\n");
    1644                 : 
    1645               0 :   secure_command_server = (struct NaClSecureService *) malloc(
    1646                 :       sizeof *secure_command_server);
    1647               0 :   if (NULL == secure_command_server) {
    1648               0 :     NaClLog(LOG_FATAL, "Out of memory for secure command channel\n");
    1649                 :   }
    1650               0 :   if (!NaClSecureServiceCtor(secure_command_server, secure_handlers, nap)) {
    1651               0 :     NaClLog(LOG_FATAL, "NaClSecureServiceCtor failed\n");
    1652                 :   }
    1653               0 :   nap->secure_service = secure_command_server;
    1654                 : 
    1655               0 :   NaClLog(4, "NaClSecureCommandChannel: starting service thread\n");
    1656               0 :   if (!NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
    1657                 :                                            secure_command_server)) {
    1658               0 :     NaClLog(LOG_FATAL,
    1659                 :             "Could not start secure command channel service thread\n");
    1660                 :   }
    1661                 : 
    1662               0 :   NaClLog(4, "Leaving NaClSecureCommandChannel\n");
    1663               0 : }
    1664                 : 
    1665                 : 
    1666               9 : void NaClVmHoleWaitToStartThread(struct NaClApp *nap) {
    1667               9 :   NaClXMutexLock(&nap->mu);
    1668                 : 
    1669                 :   /* ensure no virtual memory hole may appear */
    1670              18 :   while (nap->vm_hole_may_exist) {
    1671               0 :     NaClXCondVarWait(&nap->cv, &nap->mu);
    1672                 :   }
    1673                 : 
    1674               9 :   ++nap->threads_launching;
    1675               9 :   NaClXMutexUnlock(&nap->mu);
    1676                 :   /*
    1677                 :    * NB: Dropped lock, so many threads launching can starve VM
    1678                 :    * operations.  If this becomes a problem in practice, we can use a
    1679                 :    * reader/writer lock so that a waiting writer will block new
    1680                 :    * readers.
    1681                 :    */
    1682               9 : }
    1683                 : 
    1684               9 : void NaClVmHoleThreadStackIsSafe(struct NaClApp *nap) {
    1685               9 :   NaClXMutexLock(&nap->mu);
    1686                 : 
    1687               9 :   if (0 == --nap->threads_launching) {
    1688                 :     /*
    1689                 :      * Wake up the threads waiting to do VM operations.
    1690                 :      */
    1691               6 :     NaClXCondVarBroadcast(&nap->cv);
    1692                 :   }
    1693                 : 
    1694               9 :   NaClXMutexUnlock(&nap->mu);
    1695               9 : }
    1696                 : 
    1697                 : /*
    1698                 :  * GDB's canonical overlay managment routine.
    1699                 :  * We need its symbol in the symbol table so don't inline it.
    1700                 :  * TODO(dje): add some explanation for the non-GDB person.
    1701                 :  */
    1702                 : #if NACL_WINDOWS
    1703                 : __declspec(dllexport,noinline)
    1704                 : #endif
    1705                 : #ifdef __GNUC__
    1706                 : __attribute__((noinline))
    1707                 : #endif
    1708              11 : void _ovly_debug_event (void) {
    1709                 : #ifdef __GNUC__
    1710                 :   /*
    1711                 :    * The asm volatile is here as instructed by the GCC docs.
    1712                 :    * It's not enough to declare a function noinline.
    1713                 :    * GCC will still look inside the function to see if it's worth calling.
    1714                 :    */
    1715              11 :   __asm__ volatile ("");
    1716                 : #elif NACL_WINDOWS
    1717                 :   /*
    1718                 :    * Visual Studio inlines empty functions even with noinline attribute,
    1719                 :    * so we need a compile memory barrier to make this function not to be
    1720                 :    * inlined. Also, it guarantees that nacl_global_xlate_base initialization
    1721                 :    * is not reordered. This is important for gdb since it sets breakpoint on
    1722                 :    * this function and reads nacl_global_xlate_base value.
    1723                 :    */
    1724                 :   _ReadWriteBarrier();
    1725                 : #endif
    1726              11 : }
    1727                 : 
    1728              11 : static void StopForDebuggerInit (uintptr_t mem_start) {
    1729                 :   /* Put xlate_base in a place where gdb can find it.  */
    1730              11 :   nacl_global_xlate_base = mem_start;
    1731                 : 
    1732              11 :   NaClSandboxMemoryStartForValgrind(mem_start);
    1733                 : 
    1734              11 :   _ovly_debug_event();
    1735              11 : }
    1736                 : 
    1737              11 : void NaClGdbHook(struct NaClApp const *nap) {
    1738              11 :   StopForDebuggerInit(nap->mem_start);
    1739              11 : }

Generated by: LCOV version 1.7