Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / sel_ldr.c
index b66fbb3..ade3634 100644 (file)
 #include "native_client/src/include/portability_string.h"
 #include "native_client/src/include/nacl_macros.h"
 
+#include "native_client/src/public/desc_metadata_types.h"
+#include "native_client/src/public/nacl_app.h"
+#include "native_client/src/public/secure_service.h"
+
 #include "native_client/src/shared/gio/gio.h"
 #include "native_client/src/shared/platform/nacl_check.h"
 #include "native_client/src/shared/platform/nacl_exit.h"
 #include "native_client/src/trusted/desc/nacl_desc_imc.h"
 #include "native_client/src/trusted/desc/nacl_desc_io.h"
 #include "native_client/src/trusted/desc/nrd_xfer.h"
+#include "native_client/src/trusted/desc_cacheability/desc_cacheability.h"
 #include "native_client/src/trusted/fault_injection/fault_injection.h"
 #include "native_client/src/trusted/fault_injection/test_injection.h"
-#include "native_client/src/trusted/gio/gio_nacl_desc.h"
-#include "native_client/src/trusted/gio/gio_shm.h"
 #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree_intern.h"
 #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
 #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
@@ -47,7 +50,6 @@
 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
 #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
 #include "native_client/src/trusted/service_runtime/nacl_valgrind_hooks.h"
-#include "native_client/src/trusted/service_runtime/name_service/default_name_service.h"
 #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
 #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
@@ -56,6 +58,8 @@
 #include "native_client/src/trusted/simple_service/nacl_simple_rservice.h"
 #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
 #include "native_client/src/trusted/threading/nacl_thread_interface.h"
+#include "native_client/src/trusted/validator/rich_file_info.h"
+#include "native_client/src/trusted/validator/validation_cache.h"
 
 static int IsEnvironmentVariableSet(char const *env_name) {
   return NULL != getenv(env_name);
@@ -73,6 +77,9 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
                                 struct NaClSyscallTableEntry *table) {
   struct NaClDescEffectorLdr  *effp;
 
+  /* Zero-initialize in case we miss any fields below. */
+  memset(nap, 0, sizeof(*nap));
+
   /* The validation cache will be injected later, if it exists. */
   nap->validation_cache = NULL;
 
@@ -93,8 +100,6 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
   nap->stack_size = NACL_DEFAULT_STACK_MAX;
   nap->initial_nexe_max_code_bytes = 0;
 
-  nap->aux_info = NULL;
-
   nap->mem_start = 0;
 
 #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
@@ -174,7 +179,6 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
   nap->secure_service_address = NULL;
   nap->bootstrap_channel = NULL;
   nap->secure_service = NULL;
-  nap->irt_loaded = 0;
   nap->main_exe_prevalidated = 0;
 
   nap->kernel_service = NULL;
@@ -201,7 +205,7 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
   nap->desc_quota_interface = NULL;
 
   nap->module_initialization_state = NACL_MODULE_UNINITIALIZED;
-  nap->module_load_status = LOAD_STATUS_UNKNOWN;
+  nap->module_load_status = LOAD_OK;
 
   nap->name_service = (struct NaClNameService *) malloc(
       sizeof *nap->name_service);
@@ -216,9 +220,6 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
   }
   nap->name_service_conn_cap = NaClDescRef(nap->name_service->
                                            base.base.bound_and_cap[1]);
-  if (!NaClDefaultNameServiceInit(nap->name_service)) {
-    goto cleanup_name_service;
-  }
 
   nap->ignore_validator_result = 0;
   nap->skip_validator = 0;
@@ -238,6 +239,7 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
     NaClLog(LOG_INFO, "DANGER: ENABLED LIST_MAPPINGS\n");
     nap->enable_list_mappings = 1;
   }
+  nap->pnacl_mode = 0;
 
   if (!NaClMutexCtor(&nap->threads_mu)) {
     goto cleanup_name_service;
@@ -256,6 +258,12 @@ int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
 #endif
 
   nap->debug_stub_callbacks = NULL;
+#if NACL_WINDOWS
+  nap->debug_stub_port = 0;
+#endif
+  nap->main_nexe_desc = NULL;
+  nap->irt_nexe_desc = NULL;
+
   nap->exception_handler = 0;
   if (!NaClMutexCtor(&nap->exception_mu)) {
     goto cleanup_desc_mu;
@@ -330,6 +338,15 @@ int NaClAppCtor(struct NaClApp *nap) {
   return NaClAppWithSyscallTableCtor(nap, nacl_syscall);
 }
 
+struct NaClApp *NaClAppCreate(void) {
+  struct NaClApp *nap = malloc(sizeof(struct NaClApp));
+  if (nap == NULL)
+    NaClLog(LOG_FATAL, "Failed to allocate NaClApp\n");
+  if (!NaClAppCtor(nap))
+    NaClLog(LOG_FATAL, "NaClAppCtor() failed\n");
+  return nap;
+}
+
 /*
  * unaligned little-endian load.  precondition: nbytes should never be
  * more than 8.
@@ -460,15 +477,17 @@ void  NaClApplyPatchToMemory(struct NaClPatchInfo  *patch) {
  * correspond to unimplemented system calls and will just abort the
  * program.
  */
-void  NaClLoadTrampoline(struct NaClApp *nap) {
+void  NaClLoadTrampoline(struct NaClApp *nap, enum NaClAslrMode aslr_mode) {
   int         num_syscalls;
   int         i;
   uintptr_t   addr;
 
 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
-  if (!NaClMakePcrelThunk(nap)) {
+  if (!NaClMakePcrelThunk(nap, aslr_mode)) {
     NaClLog(LOG_FATAL, "NaClMakePcrelThunk failed!\n");
   }
+#else
+  UNREFERENCED_PARAMETER(aslr_mode);
 #endif
 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
   if (!NaClMakeDispatchAddrs(nap)) {
@@ -490,26 +509,11 @@ void  NaClLoadTrampoline(struct NaClApp *nap) {
 
   NaClLog(2, "num_syscalls = %d (0x%x)\n", num_syscalls, num_syscalls);
 
-#if defined(NACL_TARGET_ARM_THUMB2_MODE)
-  CHECK(0 != ((nap->user_entry_pt | nap->initial_entry_pt) & 0x1));
-  /*
-   * Thumb trampolines start 2 bytes before the aligned syscall address used
-   * by ordinary ARM.  We initialize this by adding 0xe to the start address
-   * of each trampoline.  Because the last start address would actually start
-   * into user code above, this allows one fewer trampolines than in ARM.
-   */
-  for (i = 0, addr = nap->mem_start + NACL_SYSCALL_START_ADDR + 0xe;
-       i < num_syscalls - 1;
-       ++i, addr += NACL_SYSCALL_BLOCK_SIZE) {
-    NaClPatchOneTrampoline(nap, addr);
-  }
-#else
   for (i = 0, addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
        i < num_syscalls;
        ++i, addr += NACL_SYSCALL_BLOCK_SIZE) {
     NaClPatchOneTrampoline(nap, addr);
   }
-#endif
 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
   NaClPatchOneTrampolineCall(nap->get_tls_fast_path1_addr,
                              nap->mem_start + NACL_SYSCALL_START_ADDR
@@ -523,55 +527,8 @@ void  NaClLoadTrampoline(struct NaClApp *nap) {
   NACL_TEST_INJECTION(ChangeTrampolines, (nap));
 }
 
-void  NaClMemRegionPrinter(void                   *state,
-                           struct NaClVmmapEntry  *entry) {
-  struct Gio *gp = (struct Gio *) state;
-
-  gprintf(gp, "\nPage   %"NACL_PRIdPTR" (0x%"NACL_PRIxPTR")\n",
-          entry->page_num, entry->page_num);
-  gprintf(gp,   "npages %"NACL_PRIdS" (0x%"NACL_PRIxS")\n", entry->npages,
-          entry->npages);
-  gprintf(gp,   "start vaddr 0x%"NACL_PRIxPTR"\n",
-          entry->page_num << NACL_PAGESHIFT);
-  gprintf(gp,   "end vaddr   0x%"NACL_PRIxPTR"\n",
-          (entry->page_num + entry->npages) << NACL_PAGESHIFT);
-  gprintf(gp,   "prot   0x%08x\n", entry->prot);
-  gprintf(gp,   "%sshared/backed by a file\n",
-          (NULL == entry->desc) ? "not " : "");
-}
-
-void  NaClAppPrintDetails(struct NaClApp  *nap,
-                          struct Gio      *gp) {
-  NaClXMutexLock(&nap->mu);
-  gprintf(gp,
-          "NaClAppPrintDetails((struct NaClApp *) 0x%08"NACL_PRIxPTR","
-          "(struct Gio *) 0x%08"NACL_PRIxPTR")\n", (uintptr_t) nap,
-          (uintptr_t) gp);
-  gprintf(gp, "addr space size:  2**%"NACL_PRId32"\n", nap->addr_bits);
-  gprintf(gp, "stack size:       0x%08"NACL_PRIx32"\n", nap->stack_size);
-
-  gprintf(gp, "mem start addr:   0x%08"NACL_PRIxPTR"\n", nap->mem_start);
-  /*           123456789012345678901234567890 */
-
-  gprintf(gp, "static_text_end:   0x%08"NACL_PRIxPTR"\n", nap->static_text_end);
-  gprintf(gp, "end-of-text:       0x%08"NACL_PRIxPTR"\n",
-          NaClEndOfStaticText(nap));
-  gprintf(gp, "rodata:            0x%08"NACL_PRIxPTR"\n", nap->rodata_start);
-  gprintf(gp, "data:              0x%08"NACL_PRIxPTR"\n", nap->data_start);
-  gprintf(gp, "data_end:          0x%08"NACL_PRIxPTR"\n", nap->data_end);
-  gprintf(gp, "break_addr:        0x%08"NACL_PRIxPTR"\n", nap->break_addr);
-
-  gprintf(gp, "ELF initial entry point:  0x%08x\n", nap->initial_entry_pt);
-  gprintf(gp, "ELF user entry point:  0x%08x\n", nap->user_entry_pt);
-  gprintf(gp, "memory map:\n");
-  NaClVmmapVisit(&nap->mem_map,
-                 NaClMemRegionPrinter,
-                 gp);
-  NaClXMutexUnlock(&nap->mu);
-}
-
-struct NaClDesc *NaClGetDescMu(struct NaClApp *nap,
-                               int            d) {
+struct NaClDesc *NaClAppGetDescMu(struct NaClApp *nap,
+                                  int            d) {
   struct NaClDesc *result;
 
   result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
@@ -582,9 +539,9 @@ struct NaClDesc *NaClGetDescMu(struct NaClApp *nap,
   return result;
 }
 
-void NaClSetDescMu(struct NaClApp   *nap,
-                   int              d,
-                   struct NaClDesc  *ndp) {
+void NaClAppSetDescMu(struct NaClApp   *nap,
+                      int              d,
+                      struct NaClDesc  *ndp) {
   struct NaClDesc *result;
 
   result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
@@ -592,54 +549,54 @@ void NaClSetDescMu(struct NaClApp   *nap,
 
   if (!DynArraySet(&nap->desc_tbl, d, ndp)) {
     NaClLog(LOG_FATAL,
-            "NaClSetDesc: could not set descriptor %d to 0x%08"
+            "NaClAppSetDesc: could not set descriptor %d to 0x%08"
             NACL_PRIxPTR"\n",
             d,
             (uintptr_t) ndp);
   }
 }
 
-int32_t NaClSetAvailMu(struct NaClApp  *nap,
-                       struct NaClDesc *ndp) {
+int32_t NaClAppSetDescAvailMu(struct NaClApp  *nap,
+                              struct NaClDesc *ndp) {
   size_t pos;
 
   pos = DynArrayFirstAvail(&nap->desc_tbl);
 
   if (pos > INT32_MAX) {
     NaClLog(LOG_FATAL,
-            ("NaClSetAvailMu: DynArrayFirstAvail returned a value"
+            ("NaClAppSetDescAvailMu: DynArrayFirstAvail returned a value"
              " that is greather than 2**31-1.\n"));
   }
 
-  NaClSetDescMu(nap, (int) pos, ndp);
+  NaClAppSetDescMu(nap, (int) pos, ndp);
 
   return (int32_t) pos;
 }
 
-struct NaClDesc *NaClGetDesc(struct NaClApp *nap,
-                             int            d) {
+struct NaClDesc *NaClAppGetDesc(struct NaClApp *nap,
+                                int            d) {
   struct NaClDesc *res;
 
   NaClFastMutexLock(&nap->desc_mu);
-  res = NaClGetDescMu(nap, d);
+  res = NaClAppGetDescMu(nap, d);
   NaClFastMutexUnlock(&nap->desc_mu);
   return res;
 }
 
-void NaClSetDesc(struct NaClApp   *nap,
-                 int              d,
-                 struct NaClDesc  *ndp) {
+void NaClAppSetDesc(struct NaClApp   *nap,
+                    int              d,
+                    struct NaClDesc  *ndp) {
   NaClFastMutexLock(&nap->desc_mu);
-  NaClSetDescMu(nap, d, ndp);
+  NaClAppSetDescMu(nap, d, ndp);
   NaClFastMutexUnlock(&nap->desc_mu);
 }
 
-int32_t NaClSetAvail(struct NaClApp  *nap,
-                     struct NaClDesc *ndp) {
+int32_t NaClAppSetDescAvail(struct NaClApp  *nap,
+                            struct NaClDesc *ndp) {
   int32_t pos;
 
   NaClFastMutexLock(&nap->desc_mu);
-  pos = NaClSetAvailMu(nap, ndp);
+  pos = NaClAppSetDescAvailMu(nap, ndp);
   NaClFastMutexUnlock(&nap->desc_mu);
 
   return pos;
@@ -716,7 +673,7 @@ void NaClAddHostDescriptor(struct NaClApp *nap,
   if (NULL == dp) {
     NaClLog(LOG_FATAL, "NaClAddHostDescriptor: NaClDescIoDescMake failed\n");
   }
-  NaClSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
+  NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
 }
 
 void NaClAddImcHandle(struct NaClApp  *nap,
@@ -738,7 +695,7 @@ void NaClAddImcHandle(struct NaClApp  *nap,
     NaClLog(LOG_FATAL, ("NaClAddImcHandle: cannot construct"
                         " IMC descriptor object\n"));
   }
-  NaClSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
+  NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
 }
 
 
@@ -791,7 +748,7 @@ static void NaClProcessRedirControl(struct NaClApp *nap) {
 
     if (NULL != ndp) {
       NaClLog(4, "Setting descriptor %d\n", (int) ix);
-      NaClSetDesc(nap, (int) ix, ndp);
+      NaClAppSetDesc(nap, (int) ix, ndp);
     } else if (NACL_RESOURCE_PHASE_START == nap->resource_phase) {
       /*
        * Environment not set or redirect failed -- handle default inheritance.
@@ -854,8 +811,8 @@ void NaClCreateServiceSocket(struct NaClApp *nap) {
           "addr at 0x%08"NACL_PRIxPTR"\n",
           (uintptr_t) pair[0],
           (uintptr_t) pair[1]);
-  NaClSetDesc(nap, NACL_SERVICE_PORT_DESCRIPTOR, pair[0]);
-  NaClSetDesc(nap, NACL_SERVICE_ADDRESS_DESCRIPTOR, pair[1]);
+  NaClAppSetDesc(nap, NACL_SERVICE_PORT_DESCRIPTOR, pair[0]);
+  NaClAppSetDesc(nap, NACL_SERVICE_ADDRESS_DESCRIPTOR, pair[1]);
 
   NaClDescSafeUnref(nap->service_port);
 
@@ -942,6 +899,24 @@ void NaClSetUpBootstrapChannel(struct NaClApp  *nap,
   }
 }
 
+enum NaClModuleInitializationState NaClGetInitState(struct NaClApp *nap) {
+  enum NaClModuleInitializationState state;
+  NaClXMutexLock(&nap->mu);
+  state = nap->module_initialization_state;
+  NaClXMutexUnlock(&nap->mu);
+  return state;
+}
+
+void NaClSetInitState(struct NaClApp *nap,
+                      enum NaClModuleInitializationState state) {
+  NaClXMutexLock(&nap->mu);
+  /* The initialization state should be increasing monotonically. */
+  CHECK(state > nap->module_initialization_state);
+  nap->module_initialization_state = state;
+  NaClXCondVarBroadcast(&nap->cv);
+  NaClXMutexUnlock(&nap->mu);
+}
+
 NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) {
   NaClErrorCode status;
 
@@ -957,17 +932,21 @@ NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) {
   return status;
 }
 
-NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) {
-  NaClErrorCode status;
-
-  NaClLog(4, "NaClWaitForLoadModuleStatus started\n");
+void NaClRememberLoadStatus(struct NaClApp *nap, NaClErrorCode status) {
   NaClXMutexLock(&nap->mu);
-  while (LOAD_STATUS_UNKNOWN == (status = nap->module_load_status)) {
-    NaClXCondVarWait(&nap->cv, &nap->mu);
+  /* Remember the first error we encountered. */
+  if (nap->module_load_status == LOAD_OK) {
+    nap->module_load_status = status;
   }
   NaClXMutexUnlock(&nap->mu);
-  NaClLog(4, "NaClWaitForLoadModuleStatus finished\n");
+}
 
+
+NaClErrorCode NaClGetLoadStatus(struct NaClApp *nap) {
+  NaClErrorCode status;
+  NaClXMutexLock(&nap->mu);
+  status = nap->module_load_status;
+  NaClXMutexUnlock(&nap->mu);
   return status;
 }
 
@@ -1029,63 +1008,69 @@ void NaClSecureCommandChannel(struct NaClApp *nap) {
   NaClLog(4, "Leaving NaClSecureCommandChannel\n");
 }
 
+
 void NaClAppLoadModule(struct NaClApp   *nap,
                        struct NaClDesc  *nexe,
-                       char             *aux_info,
                        void             (*load_cb)(void *instance_data,
                                                    NaClErrorCode status),
                        void             *instance_data) {
   NaClErrorCode status = LOAD_OK;
+  int is_double_init = NaClGetInitState(nap) != NACL_MODULE_UNINITIALIZED;
 
   NaClLog(4,
           ("Entered NaClAppLoadModule: nap 0x%"NACL_PRIxPTR","
-           " nexe 0x%"NACL_PRIxPTR", aux_info \"%s\"\n"),
-          (uintptr_t) nap, (uintptr_t) nexe, aux_info);
+           " nexe 0x%"NACL_PRIxPTR"\n"),
+          (uintptr_t) nap, (uintptr_t) nexe);
 
-  /*
-   * TODO(bsy): consider doing the processing below after sending the
-   * RPC reply to increase parallelism.
-   */
-  NaClXMutexLock(&nap->mu);
-  if (nap->module_initialization_state != NACL_MODULE_UNINITIALIZED) {
-    NaClLog(LOG_ERROR, "NaClAppLoadModule: repeated invocation\n");
-    status = LOAD_DUP_LOAD_MODULE;
-    NaClXMutexUnlock(&nap->mu);
-    if (NULL != load_cb) {
-      (*load_cb)(instance_data, status);
+  if (NULL != load_cb) {
+    NaClErrorCode cb_status;
+    if (is_double_init) {
+      cb_status = LOAD_DUP_LOAD_MODULE;
+    } else {
+      cb_status = LOAD_OK;
     }
-    return;
+    (*load_cb)(instance_data, cb_status);
   }
-  nap->module_initialization_state = NACL_MODULE_LOADING;
-  NaClXCondVarBroadcast(&nap->cv);
-  NaClXMutexUnlock(&nap->mu);
 
-  if (NULL != load_cb) {
-    (*load_cb)(instance_data, status);
+  if (is_double_init) {
+    NaClLog(LOG_ERROR, "NaClAppLoadModule: repeated invocation\n");
+    return;
   }
 
+  NaClSetInitState(nap, NACL_MODULE_LOADING);
+
+  /*
+   * Ref was passed by value into |nexe| parameter, so up the refcount.
+   * Be sure to unref when the parameter's copy goes out of scope
+   * (when returning).
+   */
+  NaClDescRef(nexe);
+
   NaClXMutexLock(&nap->mu);
-  free(nap->aux_info);
-  nap->aux_info = aux_info;
 
   /*
-   * Check / Mark the nexe binary as OK to attempt memory mapping.
-   *
-   * TODO(bsy): change needed to get NaClFileToken and resolve to file
-   * path information, set NaClRichFileInfo, and stash via
-   * NaClSetFileOriginInfo, then set NACL_DESC_FLAGS_MMAP_EXEC_OK.
+   * TODO(teravest): Remove this when file tokens are no longer used in |nexe|.
    */
+  NaClReplaceDescIfValidationCacheAssertsMappable(&nexe,
+                                                  nap->validation_cache);
+
+  /* Transfer ownership from nexe to nap->main_nexe_desc. */
+  CHECK(nap->main_nexe_desc == NULL);
+  nap->main_nexe_desc = nexe;
+  nexe = NULL;
 
   status = NACL_FI_VAL("load_module", NaClErrorCode,
-                       NaClAppLoadFile(nexe, nap));
+                       NaClAppLoadFile(nap->main_nexe_desc, nap));
 
   if (LOAD_OK != status) {
-    nap->module_load_status = status;
-    nap->module_initialization_state = NACL_MODULE_ERROR;
-    NaClXCondVarBroadcast(&nap->cv);
+    NaClDescUnref(nap->main_nexe_desc);
+    nap->main_nexe_desc = NULL;
   }
   NaClXMutexUnlock(&nap->mu);  /* NaClAppPrepareToLaunch takes mu */
+
   if (LOAD_OK != status) {
+    NaClRememberLoadStatus(nap, status);
+    NaClSetInitState(nap, NACL_MODULE_ERROR);
     return;
   }
 
@@ -1099,12 +1084,8 @@ void NaClAppLoadModule(struct NaClApp   *nap,
    * Finish setting up the NaCl App.
    */
   status = NaClAppPrepareToLaunch(nap);
-
-  NaClXMutexLock(&nap->mu);
-  nap->module_load_status = status;
-  nap->module_initialization_state = NACL_MODULE_LOADED;
-  NaClXCondVarBroadcast(&nap->cv);
-  NaClXMutexUnlock(&nap->mu);
+  NaClRememberLoadStatus(nap, status);
+  NaClSetInitState(nap, NACL_MODULE_LOADED);
 
   /* Give debuggers a well known point at which xlate_base is known.  */
   NaClGdbHook(nap);
@@ -1186,14 +1167,14 @@ void NaClAppStartModule(struct NaClApp  *nap,
    */
   NaClXMutexLock(&nap->mu);
   if (NACL_MODULE_LOADING == nap->module_initialization_state) {
-    while (NACL_MODULE_LOADED != nap->module_initialization_state) {
+    while (NACL_MODULE_LOADING == nap->module_initialization_state) {
       NaClXCondVarWait(&nap->cv, &nap->mu);
     }
   }
+  status = nap->module_load_status;
   if (nap->module_initialization_state != NACL_MODULE_LOADED) {
     if (NACL_MODULE_ERROR == nap->module_initialization_state) {
       NaClLog(LOG_ERROR, "NaClAppStartModule: error loading module\n");
-      status = nap->module_load_status;
     } else if (nap->module_initialization_state > NACL_MODULE_LOADED) {
       NaClLog(LOG_ERROR, "NaClAppStartModule: repeated invocation\n");
       status = LOAD_DUP_START_MODULE;
@@ -1207,11 +1188,10 @@ void NaClAppStartModule(struct NaClApp  *nap,
     }
     return;
   }
-  status = nap->module_load_status;
-  nap->module_initialization_state = NACL_MODULE_STARTING;
-  NaClXCondVarBroadcast(&nap->cv);
   NaClXMutexUnlock(&nap->mu);
 
+  NaClSetInitState(nap, NACL_MODULE_STARTING);
+
   NaClLog(4, "NaClSecureChannelStartModule: load status %d\n", status);
 
   /*
@@ -1227,10 +1207,7 @@ void NaClAppStartModule(struct NaClApp  *nap,
     (*start_cb)(instance_data, status);
   }
 
-  NaClXMutexLock(&nap->mu);
-  nap->module_initialization_state = NACL_MODULE_STARTED;
-  NaClXCondVarBroadcast(&nap->cv);
-  NaClXMutexUnlock(&nap->mu);
+  NaClSetInitState(nap, NACL_MODULE_STARTED);
 }
 
 void NaClAppShutdown(struct NaClApp     *nap,