#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"
#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"
#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);
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;
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 \
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;
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);
}
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;
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;
#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;
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.
* 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)) {
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
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);
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);
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;
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,
NaClLog(LOG_FATAL, ("NaClAddImcHandle: cannot construct"
" IMC descriptor object\n"));
}
- NaClSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
+ NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
}
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.
"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);
}
}
+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;
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;
}
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;
}
* 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);
*/
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;
}
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);
/*
(*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,