Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2009 The Native Client Authors. All rights reserved. | 2 * Copyright 2009 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can | 3 * Use of this source code is governed by a BSD-style license that can |
| 4 * be found in the LICENSE file. | 4 * be found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #if NACL_LINUX | |
| 8 #include <errno.h> | |
| 9 #include <sys/mman.h> | |
| 10 #endif | |
| 11 | |
| 7 #include "native_client/src/include/nacl_platform.h" | 12 #include "native_client/src/include/nacl_platform.h" |
| 8 #include "native_client/src/shared/platform/nacl_check.h" | 13 #include "native_client/src/shared/platform/nacl_check.h" |
| 14 #include "native_client/src/trusted/service_runtime/include/sys/errno.h" | |
| 9 #include "native_client/src/trusted/service_runtime/sel_memory.h" | 15 #include "native_client/src/trusted/service_runtime/sel_memory.h" |
| 10 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 16 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| 11 | 17 |
| 12 | 18 |
| 13 NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) { | 19 NaClErrorCode NaClAllocateSpace(void **mem, size_t addrsp_size) { |
| 20 #if NACL_LINUX | |
| 21 const void *ONE_MEGABYTE = (void *)(1024*1024); | |
| 22 #endif | |
| 14 int result; | 23 int result; |
| 15 | 24 |
| 16 CHECK(NULL != mem); | 25 CHECK(NULL != mem); |
| 17 | 26 |
| 18 #ifdef NACL_SANDBOX_FIXED_AT_ZERO | 27 #if NACL_LINUX |
| 19 /* | 28 /* |
| 20 * When creating a zero-based sandbox, we do not allocate the first 64K of | 29 * On 32 bit Linux, a 1 gigabyte block of address space may be reserved at |
| 21 * pages beneath the trampolines, because -- on Linux at least -- we cannot. | 30 * the zero-end of the address space during process creation, to address |
| 22 * Instead, we allocate starting at the trampolines, and then coerce the | 31 * sandbox layout requirements on ARM and performance issues on Intel ATOM. |
| 23 * out parameter. | 32 * Look for this pre-reserved block and if found, pass its address to the |
| 33 * page allocation function. | |
| 24 */ | 34 */ |
| 25 addrsp_size -= NACL_TRAMPOLINE_START; | 35 if (NaCl_find_prereserved_sandbox_memory(mem, addrsp_size)) { |
| 26 *mem = (void *) NACL_TRAMPOLINE_START; | 36 /* Sanity check zero sandbox base address. |
| 27 result = NaCl_page_alloc_at_addr(mem, addrsp_size); | 37 * It should be within a few pages above the 64KB boundary. See |
| 28 *mem = 0; | 38 * chrome/nacl/nacl_helper_bootstrap.c in the Chromium repository |
| 29 #elif NACL_WINDOWS && NACL_BUILD_SUBARCH == 32 | 39 * for more details. |
| 40 */ | |
| 41 if (0 == *mem || ONE_MEGABYTE < *mem) { | |
| 42 NaClLog(LOG_ERROR, "NaClAllocateSpace:" | |
| 43 "Can't handle sandbox at high address" | |
|
bsy
2011/08/23 21:34:20
ditto
Brad Chen
2011/08/23 22:29:52
Done.
| |
| 44 "0x%08"NACL_PRIxPTR"\n", | |
| 45 (uintptr_t)*mem); | |
| 46 return LOAD_NO_MEMORY; | |
| 47 } | |
| 48 | |
| 49 /* | |
| 50 * When creating a zero-based sandbox, we do not allocate the first 64K of | |
| 51 * pages beneath the trampolines, because -- on Linux at least -- we cannot. | |
| 52 * Instead, we allocate starting at the trampolines, and then coerce the | |
| 53 * "mem" out parameter. | |
| 54 */ | |
| 55 addrsp_size -= NACL_TRAMPOLINE_START; | |
| 56 *mem = (void *) NACL_TRAMPOLINE_START; | |
| 57 result = NaCl_page_alloc_at_addr(mem, addrsp_size); | |
| 58 *mem = 0; | |
| 59 } else { | |
| 60 /* Zero-based sandbox not pre-reserved. Attempt to allocate anyway. */ | |
| 61 result = NaCl_page_alloc(mem, addrsp_size); | |
| 62 } | |
| 63 #elif NACL_WINDOWS | |
| 30 /* | 64 /* |
| 31 * On 32 bit Windows, a 1 gigabyte block of address space is reserved before | 65 * On 32 bit Windows, a 1 gigabyte block of address space is reserved before |
| 32 * starting up this process to make sure we can create the sandbox. Look for | 66 * starting up this process to make sure we can create the sandbox. Look for |
| 33 * this pre-reserved block and if found, pass its address to the page | 67 * this pre-reserved block and if found, pass its address to the page |
| 34 * allocation function. | 68 * allocation function. |
| 35 */ | 69 */ |
| 36 if (0 == NaCl_find_prereserved_sandbox_memory(mem, addrsp_size)) { | 70 if (0 == NaCl_find_prereserved_sandbox_memory(mem, addrsp_size)) { |
| 37 result = NaCl_page_alloc_at_addr(mem, addrsp_size); | 71 result = NaCl_page_alloc_at_addr(mem, addrsp_size); |
| 38 } else { | 72 } else { |
| 39 result = NaCl_page_alloc(mem, addrsp_size); | 73 result = NaCl_page_alloc(mem, addrsp_size); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 53 (uintptr_t) *mem, | 87 (uintptr_t) *mem, |
| 54 addrsp_size); | 88 addrsp_size); |
| 55 | 89 |
| 56 return LOAD_OK; | 90 return LOAD_OK; |
| 57 } | 91 } |
| 58 | 92 |
| 59 | 93 |
| 60 NaClErrorCode NaClMprotectGuards(struct NaClApp *nap) { | 94 NaClErrorCode NaClMprotectGuards(struct NaClApp *nap) { |
| 61 uintptr_t start_addr; | 95 uintptr_t start_addr; |
| 62 int err; | 96 int err; |
| 97 #if NACL_LINUX | |
| 98 uintptr_t page_addr; | |
| 99 void *mmap_rval; | |
| 100 #endif | |
| 63 | 101 |
| 64 start_addr = nap->mem_start; | 102 start_addr = nap->mem_start; |
| 65 | 103 |
| 66 NaClLog(3, | 104 NaClLog(3, |
| 67 ("NULL detection region start 0x%08"NACL_PRIxPTR", " | 105 ("NULL detection region start 0x%08"NACL_PRIxPTR", " |
| 68 "size 0x%08x, end 0x%08"NACL_PRIxPTR"\n"), | 106 "size 0x%08x, end 0x%08"NACL_PRIxPTR"\n"), |
| 69 start_addr, NACL_SYSCALL_START_ADDR, | 107 start_addr, NACL_SYSCALL_START_ADDR, |
| 70 start_addr + NACL_SYSCALL_START_ADDR); | 108 start_addr + NACL_SYSCALL_START_ADDR); |
| 71 if ((err = NaCl_mprotect((void *) start_addr, | 109 if (0 == start_addr) { |
| 72 NACL_SYSCALL_START_ADDR, | 110 #if !NACL_LINUX |
| 73 PROT_NONE)) != 0) { | 111 NaClLog(LOG_FATAL, ("NaClMprotectGuards: zero-based sandbox is" |
| 74 NaClLog(LOG_ERROR, ("NaClMemoryProtection: " | 112 " supported on Linux only.\n")); |
| 75 "NaCl_mprotect(0x%08"NACL_PRIxPTR", " | 113 #else |
| 76 "0x%08x, 0x%x) failed, " | 114 /* 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.
| |
| 77 "error %d (NULL pointer guard page)\n"), | 115 * these attempts to fail if the page is in the reserved low |
| 78 start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE, | 116 * part of the address space. Note the 0 page can never be |
| 79 err); | 117 * protected so start at NACL_PAGESIZE. |
| 80 return LOAD_MPROTECT_FAIL; | 118 */ |
| 119 for (page_addr = NACL_PAGESIZE; | |
| 120 page_addr < NACL_SYSCALL_START_ADDR; | |
| 121 page_addr += NACL_PAGESIZE) { | |
| 122 mmap_rval = mmap((void *)page_addr, | |
| 123 NACL_SYSCALL_START_ADDR - page_addr, | |
| 124 PROT_NONE, | |
| 125 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS | MAP_NORESERVE, | |
| 126 -1, 0); | |
| 127 if (page_addr == (uintptr_t)mmap_rval) { | |
| 128 /* Success; the page is now protected. */ | |
|
bsy
2011/08/23 21:34:20
pages are
Brad Chen
2011/08/23 22:29:52
Done.
| |
| 129 break; | |
| 130 } else if (MAP_FAILED == mmap_rval && EPERM == errno) { | |
| 131 /* Normal; this is an invalid page for this process and | |
| 132 * doesn't need to be protected. Keep checking by page. | |
| 133 */ | |
| 134 } else { | |
| 135 NaClLog(LOG_ERROR, ("NaClMemoryProtection: " | |
| 136 "mmap(0x%08"NACL_PRIxPTR") failed, " | |
| 137 "error %d (NULL pointer guard page)\n"), | |
| 138 page_addr, errno); | |
| 139 return LOAD_MPROTECT_FAIL; | |
| 140 } | |
| 141 } | |
| 142 #endif | |
| 143 } else { | |
| 144 err = NaCl_mprotect((void *) start_addr, | |
| 145 NACL_SYSCALL_START_ADDR, | |
| 146 PROT_NONE); | |
| 147 if (err != 0) { | |
| 148 NaClLog(LOG_ERROR, ("NaClMemoryProtection: " | |
| 149 "NaCl_mprotect(0x%08"NACL_PRIxPTR", " | |
| 150 "0x%08x, 0x%x) failed, " | |
| 151 "error %d (NULL pointer guard page)\n"), | |
| 152 start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE, | |
| 153 err); | |
| 154 return LOAD_MPROTECT_FAIL; | |
| 155 } | |
| 81 } | 156 } |
| 82 if (!NaClVmmapAdd(&nap->mem_map, | 157 if (!NaClVmmapAdd(&nap->mem_map, |
| 83 (start_addr - nap->mem_start) >> NACL_PAGESHIFT, | 158 (start_addr - nap->mem_start) >> NACL_PAGESHIFT, |
| 84 NACL_SYSCALL_START_ADDR >> NACL_PAGESHIFT, | 159 NACL_SYSCALL_START_ADDR >> NACL_PAGESHIFT, |
| 85 PROT_NONE, | 160 PROT_NONE, |
| 86 (struct NaClMemObj *) NULL)) { | 161 (struct NaClMemObj *) NULL)) { |
| 87 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed" | 162 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed" |
| 88 " (NULL pointer guard page)\n")); | 163 " (NULL pointer guard page)\n")); |
| 89 return LOAD_MPROTECT_FAIL; | 164 return LOAD_MPROTECT_FAIL; |
| 90 } | 165 } |
| 91 | 166 |
| 92 return LOAD_OK; | 167 return LOAD_OK; |
| 93 } | 168 } |
| OLD | NEW |