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 && NACL_BUILD_SUBARCH == 32 | |
|
Mark Seaborn
2011/08/23 18:26:36
You're already in the x86_32 file.
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 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 && NACL_BUILD_SUBARCH == 32 |
|
Mark Seaborn
2011/08/23 18:26:36
You're already in the x86_32 file.
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 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. */ |
|
Mark Seaborn
2011/08/23 18:26:36
Nit: Comment style is
/*
* blah
*/
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 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 */ |
| 39 /* for more details. */ | |
| 40 if (0 == *mem || ONE_MEGABYTE < *mem) { | |
| 41 NaClLog(LOG_ERROR, "NaClAllocateSpace:" | |
| 42 "Can't handle sandbox at high address" | |
| 43 "0x%08"NACL_PRIxPTR"\n", | |
| 44 (uintptr_t)*mem); | |
| 45 return LOAD_NO_MEMORY; | |
| 46 } | |
| 47 | |
| 48 /* | |
| 49 * When creating a zero-based sandbox, we do not allocate the first 64K of | |
| 50 * pages beneath the trampolines, because -- on Linux at least -- we cannot. | |
| 51 * Instead, we allocate starting at the trampolines, and then coerce the | |
| 52 * "mem" out parameter. | |
| 53 */ | |
| 54 addrsp_size -= NACL_TRAMPOLINE_START; | |
| 55 *mem = (void *) NACL_TRAMPOLINE_START; | |
| 56 result = NaCl_page_alloc_at_addr(mem, addrsp_size); | |
| 57 *mem = 0; | |
| 58 } else { | |
| 59 /* Zero-based sandbox not pre-reserved. Attempt to allocate anyway. */ | |
| 60 result = NaCl_page_alloc(mem, addrsp_size); | |
| 61 } | |
| 29 #elif NACL_WINDOWS && NACL_BUILD_SUBARCH == 32 | 62 #elif NACL_WINDOWS && NACL_BUILD_SUBARCH == 32 |
| 30 /* | 63 /* |
| 31 * On 32 bit Windows, a 1 gigabyte block of address space is reserved before | 64 * 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 | 65 * 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 | 66 * this pre-reserved block and if found, pass its address to the page |
| 34 * allocation function. | 67 * allocation function. |
| 35 */ | 68 */ |
| 36 if (0 == NaCl_find_prereserved_sandbox_memory(mem, addrsp_size)) { | 69 if (0 == NaCl_find_prereserved_sandbox_memory(mem, addrsp_size)) { |
| 37 result = NaCl_page_alloc_at_addr(mem, addrsp_size); | 70 result = NaCl_page_alloc_at_addr(mem, addrsp_size); |
| 38 } else { | 71 } else { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 53 (uintptr_t) *mem, | 86 (uintptr_t) *mem, |
| 54 addrsp_size); | 87 addrsp_size); |
| 55 | 88 |
| 56 return LOAD_OK; | 89 return LOAD_OK; |
| 57 } | 90 } |
| 58 | 91 |
| 59 | 92 |
| 60 NaClErrorCode NaClMprotectGuards(struct NaClApp *nap) { | 93 NaClErrorCode NaClMprotectGuards(struct NaClApp *nap) { |
| 61 uintptr_t start_addr; | 94 uintptr_t start_addr; |
| 62 int err; | 95 int err; |
| 96 #if NACL_LINUX | |
| 97 uintptr_t page_addr; | |
| 98 void *mmap_rval; | |
| 99 #endif | |
| 63 | 100 |
| 64 start_addr = nap->mem_start; | 101 start_addr = nap->mem_start; |
| 65 | 102 |
| 66 NaClLog(3, | 103 NaClLog(3, |
| 67 ("NULL detection region start 0x%08"NACL_PRIxPTR", " | 104 ("NULL detection region start 0x%08"NACL_PRIxPTR", " |
| 68 "size 0x%08x, end 0x%08"NACL_PRIxPTR"\n"), | 105 "size 0x%08x, end 0x%08"NACL_PRIxPTR"\n"), |
| 69 start_addr, NACL_SYSCALL_START_ADDR, | 106 start_addr, NACL_SYSCALL_START_ADDR, |
| 70 start_addr + NACL_SYSCALL_START_ADDR); | 107 start_addr + NACL_SYSCALL_START_ADDR); |
| 71 if ((err = NaCl_mprotect((void *) start_addr, | 108 if (0 == start_addr) { |
| 72 NACL_SYSCALL_START_ADDR, | 109 #if !NACL_LINUX |
| 73 PROT_NONE)) != 0) { | 110 NaClLog(LOG_FATAL, ("NaClMprotectGuards: zero-based sandbox is" |
| 74 NaClLog(LOG_ERROR, ("NaClMemoryProtection: " | 111 " supported on Linux only.\n")); |
| 75 "NaCl_mprotect(0x%08"NACL_PRIxPTR", " | 112 #else |
| 76 "0x%08x, 0x%x) failed, " | 113 /* Attempt to protect one page at a time. It is normal for |
|
Mark Seaborn
2011/08/23 18:26:36
Nit: Comment style is
/*
* blah
*/
bsy
2011/08/23 18:43:19
there's no reason to do it one page at a time. we
Brad Chen
2011/08/23 21:15:09
Done.
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 77 "error %d (NULL pointer guard page)\n"), | 114 * these attempts to fail if the page is in the reserved low |
| 78 start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE, | 115 * part of the address space. Note the 0 page can never be |
| 79 err); | 116 * protected so start at NACL_PAGESIZE. |
| 80 return LOAD_MPROTECT_FAIL; | 117 */ |
| 118 for (page_addr = NACL_PAGESIZE; page_addr < NACL_SYSCALL_START_ADDR; | |
|
Mark Seaborn
2011/08/23 18:26:36
I'd put each for() clause on a different line if t
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 119 page_addr += NACL_PAGESIZE) { | |
| 120 mmap_rval = mmap((void *)page_addr, NACL_PAGESIZE, PROT_NONE, | |
| 121 MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); | |
|
Mark Seaborn
2011/08/23 18:26:36
Maybe MAP_NORESERVE too, just in case?
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 122 if (page_addr == (uintptr_t)mmap_rval) { | |
| 123 /* Success; the page is now protected. */ | |
| 124 } else if (MAP_FAILED == mmap_rval && EPERM == errno) { | |
| 125 /* Normal; this is an invalid page for this process and */ | |
|
Mark Seaborn
2011/08/23 18:26:36
Comment style
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 126 /* doesn't need to be protected. */ | |
| 127 } else { | |
| 128 NaClLog(LOG_ERROR, ("NaClMemoryProtection: " | |
| 129 "mmap(0x%08"NACL_PRIxPTR") failed, " | |
| 130 "error %d (NULL pointer guard page)\n"), | |
| 131 page_addr, errno); | |
| 132 return LOAD_MPROTECT_FAIL; | |
| 133 } | |
| 134 } | |
| 135 #endif | |
| 136 } else { | |
|
bbudge
2011/08/23 18:50:21
You could move the 'if' statement here: else if ((
Brad Chen
2011/08/23 21:15:09
Done.
| |
| 137 if ((err = NaCl_mprotect((void *) start_addr, | |
| 138 NACL_SYSCALL_START_ADDR, | |
| 139 PROT_NONE)) != 0) { | |
| 140 NaClLog(LOG_ERROR, ("NaClMemoryProtection: " | |
| 141 "NaCl_mprotect(0x%08"NACL_PRIxPTR", " | |
| 142 "0x%08x, 0x%x) failed, " | |
| 143 "error %d (NULL pointer guard page)\n"), | |
| 144 start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE, | |
| 145 err); | |
| 146 return LOAD_MPROTECT_FAIL; | |
| 147 } | |
| 81 } | 148 } |
| 82 if (!NaClVmmapAdd(&nap->mem_map, | 149 if (!NaClVmmapAdd(&nap->mem_map, |
| 83 (start_addr - nap->mem_start) >> NACL_PAGESHIFT, | 150 (start_addr - nap->mem_start) >> NACL_PAGESHIFT, |
| 84 NACL_SYSCALL_START_ADDR >> NACL_PAGESHIFT, | 151 NACL_SYSCALL_START_ADDR >> NACL_PAGESHIFT, |
| 85 PROT_NONE, | 152 PROT_NONE, |
| 86 (struct NaClMemObj *) NULL)) { | 153 (struct NaClMemObj *) NULL)) { |
| 87 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed" | 154 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed" |
| 88 " (NULL pointer guard page)\n")); | 155 " (NULL pointer guard page)\n")); |
| 89 return LOAD_MPROTECT_FAIL; | 156 return LOAD_MPROTECT_FAIL; |
| 90 } | 157 } |
| 91 | 158 |
| 92 return LOAD_OK; | 159 return LOAD_OK; |
| 93 } | 160 } |
| OLD | NEW |