NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) { int result; CHECK(NULL != mem); NaClAddrSpaceBeforeAlloc(addrsp_size); #if NACL_LINUX /* * On 32 bit Linux, a 1 gigabyte block of address space may be reserved at * the zero-end of the address space during process creation, to address * sandbox layout requirements on ARM and performance issues on Intel ATOM. * Look for this prereserved block and if found, pass its address to the * page allocation function. */ if (NaClFindPrereservedSandboxMemory(mem, addrsp_size)) { void *tmp_mem = (void *) NACL_TRAMPOLINE_START; CHECK(*mem == 0); addrsp_size -= NACL_TRAMPOLINE_START; result = NaCl_page_alloc_at_addr(&tmp_mem, addrsp_size); } else { /* Zero-based sandbox not prereserved. Attempt to allocate anyway. */ result = NaCl_page_alloc(mem, addrsp_size); } #elif NACL_WINDOWS /* * On 32 bit Windows, a 1 gigabyte block of address space is reserved before * starting up this process to make sure we can create the sandbox. Look for * this prereserved block and if found, pass its address to the page * allocation function. */ if (0 == NaClFindPrereservedSandboxMemory(mem, addrsp_size)) { result = NaCl_page_alloc_at_addr(mem, addrsp_size); } else { result = NaCl_page_alloc(mem, addrsp_size); } #else result = NaCl_page_alloc(mem, addrsp_size); #endif if (0 != result) { NaClLog(2, "NaClAllocateSpace: NaCl_page_alloc 0x%08"NACL_PRIxPTR " failed\n", (uintptr_t) *mem); return LOAD_NO_MEMORY; } NaClLog(4, "NaClAllocateSpace: %"NACL_PRIxPTR", %"NACL_PRIxS"\n", (uintptr_t) *mem, addrsp_size); return LOAD_OK; }
void TestDEPCheckFailurePath(void) { size_t size = NACL_PAGESIZE; void *page; CHECK(NaCl_page_alloc(&page, size) == 0); CHECK(NaCl_mprotect(page, size, PROT_READ | PROT_WRITE | PROT_EXEC) == 0); CHECK(!NaClAttemptToExecuteDataAtAddr(page, size)); /* DEP is not guaranteed to work on x86-32. */ if (!(NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32)) { CHECK(NaCl_mprotect(page, size, PROT_READ | PROT_WRITE) == 0); CHECK(NaClAttemptToExecuteDataAtAddr(page, size)); } NaCl_page_free(page, size); }
/* * Create thunk for use by syscall trampoline code. */ int NaClMakePcrelThunk(struct NaClApp *nap) { int retval = 0; /* fail */ int error; void *thunk_addr = NULL; struct NaClPatchInfo patch_info; uintptr_t patch_rel32[1]; /* NaClSyscallSeg */ struct NaClPatch patch_abs32[2]; /* ds, nacl_user */ /* idempotent */ nacl_pcrel_globals.user = nacl_user; nacl_pcrel_globals.sys = nacl_sys; if (0 != (error = NaCl_page_alloc(&thunk_addr, NACL_MAP_PAGESIZE))) { NaClLog(LOG_INFO, "NaClMakePcrelThunk::NaCl_page_alloc failed, errno %d\n", -error); retval = 0; goto cleanup; } patch_rel32[0] = ((uintptr_t) &NaClPcrelThunk_end) - 4; patch_abs32[0].target = ((uintptr_t) &NaClPcrelThunk_dseg_patch) - 4; patch_abs32[0].value = NaClGetGlobalDs(); patch_abs32[1].target = ((uintptr_t) &NaClPcrelThunk_globals_patch) - 4; patch_abs32[1].value = (uintptr_t) &nacl_pcrel_globals; NaClPatchInfoCtor(&patch_info); patch_info.rel32 = patch_rel32; patch_info.num_rel32 = NACL_ARRAY_SIZE(patch_rel32); patch_info.abs32 = patch_abs32; patch_info.num_abs32 = NACL_ARRAY_SIZE(patch_abs32); patch_info.dst = (uintptr_t) thunk_addr; patch_info.src = (uintptr_t) &NaClPcrelThunk; patch_info.nbytes = ((uintptr_t) &NaClPcrelThunk_end - (uintptr_t) &NaClPcrelThunk); NaClApplyPatchToMemory(&patch_info); if (0 != (error = NaCl_mprotect(thunk_addr, NACL_MAP_PAGESIZE, PROT_EXEC|PROT_READ))) { NaClLog(LOG_INFO, "NaClMakePcrelThunk::NaCl_mprotect failed, errno %d\n", -error); retval = 0; goto cleanup; } retval = 1; cleanup: if (0 == retval) { if (NULL != thunk_addr) { NaCl_page_free(thunk_addr, NACL_MAP_PAGESIZE); thunk_addr = NULL; } } else { nap->pcrel_thunk = (uintptr_t) thunk_addr; } return retval; }