Chromium Code Reviews| Index: src/trusted/service_runtime/arch/x86_32/sel_addrspace_x86_32.c |
| diff --git a/src/trusted/service_runtime/arch/x86_32/sel_addrspace_x86_32.c b/src/trusted/service_runtime/arch/x86_32/sel_addrspace_x86_32.c |
| index 8cd92a7f65ac7e0af13ff80f6d0f496e22f41e84..5d753a3999a669e9903b0fd434881cbf28de42c4 100644 |
| --- a/src/trusted/service_runtime/arch/x86_32/sel_addrspace_x86_32.c |
| +++ b/src/trusted/service_runtime/arch/x86_32/sel_addrspace_x86_32.c |
| @@ -4,29 +4,63 @@ |
| * be found in the LICENSE file. |
| */ |
| +#if NACL_LINUX |
| +#include <errno.h> |
| +#include <sys/mman.h> |
| +#endif |
| + |
| #include "native_client/src/include/nacl_platform.h" |
| #include "native_client/src/shared/platform/nacl_check.h" |
| +#include "native_client/src/trusted/service_runtime/include/sys/errno.h" |
| #include "native_client/src/trusted/service_runtime/sel_memory.h" |
| #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) { |
| +#if NACL_LINUX |
| + const void *ONE_MEGABYTE = (void *)(1024*1024); |
| +#endif |
| int result; |
| CHECK(NULL != mem); |
| -#ifdef NACL_SANDBOX_FIXED_AT_ZERO |
| +#if NACL_LINUX |
| /* |
| - * When creating a zero-based sandbox, we do not allocate the first 64K of |
| - * pages beneath the trampolines, because -- on Linux at least -- we cannot. |
| - * Instead, we allocate starting at the trampolines, and then coerce the |
| - * out parameter. |
| + * 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 pre-reserved block and if found, pass its address to the |
| + * page allocation function. |
| */ |
| - addrsp_size -= NACL_TRAMPOLINE_START; |
| - *mem = (void *) NACL_TRAMPOLINE_START; |
| - result = NaCl_page_alloc_at_addr(mem, addrsp_size); |
| - *mem = 0; |
| -#elif NACL_WINDOWS && NACL_BUILD_SUBARCH == 32 |
| + if (NaCl_find_prereserved_sandbox_memory(mem, addrsp_size)) { |
| + /* Sanity check zero sandbox base address. |
| + * It should be within a few pages above the 64KB boundary. See |
| + * chrome/nacl/nacl_helper_bootstrap.c in the Chromium repository |
| + * for more details. |
| + */ |
| + if (0 == *mem || ONE_MEGABYTE < *mem) { |
| + NaClLog(LOG_ERROR, "NaClAllocateSpace:" |
| + "Can't handle sandbox at high address" |
|
bsy
2011/08/23 21:34:20
ditto
Brad Chen
2011/08/23 22:29:52
Done.
|
| + "0x%08"NACL_PRIxPTR"\n", |
| + (uintptr_t)*mem); |
| + return LOAD_NO_MEMORY; |
| + } |
| + |
| + /* |
| + * When creating a zero-based sandbox, we do not allocate the first 64K of |
| + * pages beneath the trampolines, because -- on Linux at least -- we cannot. |
| + * Instead, we allocate starting at the trampolines, and then coerce the |
| + * "mem" out parameter. |
| + */ |
| + addrsp_size -= NACL_TRAMPOLINE_START; |
| + *mem = (void *) NACL_TRAMPOLINE_START; |
| + result = NaCl_page_alloc_at_addr(mem, addrsp_size); |
| + *mem = 0; |
| + } else { |
| + /* Zero-based sandbox not pre-reserved. 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 |
| @@ -60,6 +94,10 @@ NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) { |
| NaClErrorCode NaClMprotectGuards(struct NaClApp *nap) { |
| uintptr_t start_addr; |
| int err; |
| +#if NACL_LINUX |
| + uintptr_t page_addr; |
| + void *mmap_rval; |
| +#endif |
| start_addr = nap->mem_start; |
| @@ -68,16 +106,53 @@ NaClErrorCode NaClMprotectGuards(struct NaClApp *nap) { |
| "size 0x%08x, end 0x%08"NACL_PRIxPTR"\n"), |
| start_addr, NACL_SYSCALL_START_ADDR, |
| start_addr + NACL_SYSCALL_START_ADDR); |
| - if ((err = NaCl_mprotect((void *) start_addr, |
| - NACL_SYSCALL_START_ADDR, |
| - PROT_NONE)) != 0) { |
| - NaClLog(LOG_ERROR, ("NaClMemoryProtection: " |
| - "NaCl_mprotect(0x%08"NACL_PRIxPTR", " |
| - "0x%08x, 0x%x) failed, " |
| - "error %d (NULL pointer guard page)\n"), |
| - start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE, |
| - err); |
| - return LOAD_MPROTECT_FAIL; |
| + if (0 == start_addr) { |
| +#if !NACL_LINUX |
| + NaClLog(LOG_FATAL, ("NaClMprotectGuards: zero-based sandbox is" |
| + " supported on Linux only.\n")); |
| +#else |
| + /* Attempt to protect one page at a time. It is normal for |
|
bsy
2011/08/23 21:34:20
maybe update to something along the lines of:
Att
Brad Chen
2011/08/23 22:29:52
Done.
|
| + * these attempts to fail if the page is in the reserved low |
| + * part of the address space. Note the 0 page can never be |
| + * protected so start at NACL_PAGESIZE. |
| + */ |
| + for (page_addr = NACL_PAGESIZE; |
| + page_addr < NACL_SYSCALL_START_ADDR; |
| + page_addr += NACL_PAGESIZE) { |
| + mmap_rval = mmap((void *)page_addr, |
| + NACL_SYSCALL_START_ADDR - page_addr, |
| + PROT_NONE, |
| + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS | MAP_NORESERVE, |
| + -1, 0); |
| + if (page_addr == (uintptr_t)mmap_rval) { |
| + /* Success; the page is now protected. */ |
|
bsy
2011/08/23 21:34:20
pages are
Brad Chen
2011/08/23 22:29:52
Done.
|
| + break; |
| + } else if (MAP_FAILED == mmap_rval && EPERM == errno) { |
| + /* Normal; this is an invalid page for this process and |
| + * doesn't need to be protected. Keep checking by page. |
| + */ |
| + } else { |
| + NaClLog(LOG_ERROR, ("NaClMemoryProtection: " |
| + "mmap(0x%08"NACL_PRIxPTR") failed, " |
| + "error %d (NULL pointer guard page)\n"), |
| + page_addr, errno); |
| + return LOAD_MPROTECT_FAIL; |
| + } |
| + } |
| +#endif |
| + } else { |
| + err = NaCl_mprotect((void *) start_addr, |
| + NACL_SYSCALL_START_ADDR, |
| + PROT_NONE); |
| + if (err != 0) { |
| + NaClLog(LOG_ERROR, ("NaClMemoryProtection: " |
| + "NaCl_mprotect(0x%08"NACL_PRIxPTR", " |
| + "0x%08x, 0x%x) failed, " |
| + "error %d (NULL pointer guard page)\n"), |
| + start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE, |
| + err); |
| + return LOAD_MPROTECT_FAIL; |
| + } |
| } |
| if (!NaClVmmapAdd(&nap->mem_map, |
| (start_addr - nap->mem_start) >> NACL_PAGESHIFT, |