| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2008 The Native Client Authors. All rights reserved. | 2 * Copyright 2008 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 /* | 7 /* |
| 8 * NaCl Simple/secure ELF loader (NaCl SEL). | 8 * NaCl Simple/secure ELF loader (NaCl SEL). |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "native_client/src/trusted/service_runtime/sel_addrspace.h" | 37 #include "native_client/src/trusted/service_runtime/sel_addrspace.h" |
| 38 #include "native_client/src/trusted/service_runtime/win/mman.h" | 38 #include "native_client/src/trusted/service_runtime/win/mman.h" |
| 39 | 39 |
| 40 #if !defined(SIZE_T_MAX) | 40 #if !defined(SIZE_T_MAX) |
| 41 # define SIZE_T_MAX (~(size_t) 0) | 41 # define SIZE_T_MAX (~(size_t) 0) |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 | 44 |
| 45 /* | 45 /* |
| 46 * Fill from static_text_end to end of that page with halt | 46 * Fill from static_text_end to end of that page with halt |
| 47 * instruction, which is NACL_HALT_LEN in size. Does not touch | 47 * instruction, which is at least NACL_HALT_LEN in size when no |
| 48 * dynamic text region, which should be pre-filled with HLTs. | 48 * dynamic text is present. Does not touch dynamic text region, which |
| 49 * should be pre-filled with HLTs. |
| 50 * |
| 51 * By adding NACL_HALT_SLED_SIZE, we ensure that the code region ends |
| 52 * with HLTs, just in case the CPU has a bug in which it fails to |
| 53 * check for running off the end of the x86 code segment. |
| 49 */ | 54 */ |
| 50 void NaClFillEndOfTextRegion(struct NaClApp *nap) { | 55 void NaClFillEndOfTextRegion(struct NaClApp *nap) { |
| 51 size_t page_pad; | 56 size_t page_pad; |
| 52 | 57 |
| 53 /* | 58 /* |
| 54 * By adding NACL_HALT_SLED_SIZE, we ensure that the code region | 59 * NOTE: make sure we are not silently overwriting data. It is the |
| 55 * ends with HLTs, just in case the CPU has a bug in which it fails | 60 * toolchain's responsibility to ensure that a NACL_HALT_SLED_SIZE |
| 56 * to check for running off the end of the x86 code segment. | 61 * gap exists. |
| 57 */ | 62 */ |
| 58 page_pad = (NaClRoundAllocPage(nap->static_text_end + NACL_HALT_SLED_SIZE) | |
| 59 - nap->static_text_end); | |
| 60 | |
| 61 /* NOTE: make sure we are not silently overwriting data */ | |
| 62 if (0 != nap->data_start && | 63 if (0 != nap->data_start && |
| 63 nap->static_text_end + NACL_HALT_SLED_SIZE > nap->data_start) { | 64 nap->static_text_end + NACL_HALT_SLED_SIZE > nap->data_start) { |
| 64 NaClLog(LOG_FATAL, "Missing gap between text and data for halt_sled"); | 65 NaClLog(LOG_FATAL, "Missing gap between text and data for halt_sled\n"); |
| 65 } | 66 } |
| 66 if (0 != nap->rodata_start && | 67 if (0 != nap->rodata_start && |
| 67 nap->static_text_end + NACL_HALT_SLED_SIZE > nap->rodata_start) { | 68 nap->static_text_end + NACL_HALT_SLED_SIZE > nap->rodata_start) { |
| 68 NaClLog(LOG_FATAL, "Missing gap between text and rodata for halt_sled"); | 69 NaClLog(LOG_FATAL, "Missing gap between text and rodata for halt_sled\n"); |
| 69 } | 70 } |
| 70 | 71 |
| 71 CHECK(page_pad >= NACL_HALT_SLED_SIZE); | 72 if (NULL == nap->text_shm) { |
| 72 CHECK(page_pad < NACL_MAP_PAGESIZE + NACL_HALT_SLED_SIZE); | 73 /* |
| 74 * No dynamic text exists. Space for NACL_HALT_SLED_SIZE must |
| 75 * exist. |
| 76 */ |
| 77 page_pad = (NaClRoundAllocPage(nap->static_text_end + NACL_HALT_SLED_SIZE) |
| 78 - nap->static_text_end); |
| 79 CHECK(page_pad >= NACL_HALT_SLED_SIZE); |
| 80 CHECK(page_pad < NACL_MAP_PAGESIZE + NACL_HALT_SLED_SIZE); |
| 81 } else { |
| 82 /* |
| 83 * Dynamic text exists; the halt sled resides in the dynamic text |
| 84 * region, so all we need to do here is to round out the last |
| 85 * static text page with HLT instructions. It doesn't matter if |
| 86 * the size of this region is smaller than NACL_HALT_SLED_SIZE -- |
| 87 * this is just to fully initialize the page, rather than (later) |
| 88 * decoding/validating zero-filled memory as instructions. |
| 89 */ |
| 90 page_pad = NaClRoundAllocPage(nap->static_text_end) - nap->static_text_end; |
| 91 } |
| 73 | 92 |
| 74 NaClLog(4, | 93 NaClLog(4, |
| 75 "Filling with halts: %08"NACL_PRIxPTR", %08"NACL_PRIxS" bytes\n", | 94 "Filling with halts: %08"NACL_PRIxPTR", %08"NACL_PRIxS" bytes\n", |
| 76 nap->mem_start + nap->static_text_end, | 95 nap->mem_start + nap->static_text_end, |
| 77 page_pad); | 96 page_pad); |
| 78 | 97 |
| 79 NaClFillMemoryRegionWithHalt((void *)(nap->mem_start + nap->static_text_end), | 98 NaClFillMemoryRegionWithHalt((void *)(nap->mem_start + nap->static_text_end), |
| 80 page_pad); | 99 page_pad); |
| 81 | 100 |
| 82 nap->static_text_end += page_pad; | 101 nap->static_text_end += page_pad; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 &nap->rodata_start, | 150 &nap->rodata_start, |
| 132 &rodata_end, | 151 &rodata_end, |
| 133 &nap->data_start, | 152 &nap->data_start, |
| 134 &data_end, | 153 &data_end, |
| 135 &max_vaddr); | 154 &max_vaddr); |
| 136 if (LOAD_OK != subret) { | 155 if (LOAD_OK != subret) { |
| 137 ret = subret; | 156 ret = subret; |
| 138 goto done; | 157 goto done; |
| 139 } | 158 } |
| 140 | 159 |
| 160 if (0 == nap->data_start) { |
| 161 if (0 == nap->rodata_start) { |
| 162 if (NaClRoundAllocPage(max_vaddr) - max_vaddr < NACL_HALT_SLED_SIZE) { |
| 163 /* |
| 164 * if no rodata and no data, we make sure that there is space for |
| 165 * the halt sled. |
| 166 */ |
| 167 max_vaddr += NACL_MAP_PAGESIZE; |
| 168 } |
| 169 } else { |
| 170 /* |
| 171 * no data, but there is rodata. this means max_vaddr is just |
| 172 * where rodata ends. this might not be at an allocation |
| 173 * boundary, and in this the page would not be writable. round |
| 174 * max_vaddr up to the next allocation boundary so that bss will |
| 175 * be at the next writable region. |
| 176 */ |
| 177 ; |
| 178 } |
| 179 max_vaddr = NaClRoundAllocPage(max_vaddr); |
| 180 } |
| 181 /* |
| 182 * max_vaddr -- the break or the boundary between data (initialized |
| 183 * and bss) and the address space hole -- does not have to be at a |
| 184 * page boundary. |
| 185 */ |
| 141 nap->break_addr = max_vaddr; | 186 nap->break_addr = max_vaddr; |
| 142 nap->data_end = max_vaddr; | 187 nap->data_end = max_vaddr; |
| 143 | 188 |
| 144 NaClLog(4, "rodata_end = %08"NACL_PRIxPTR"\n", rodata_end); | 189 NaClLog(4, "Values from NaClElfImageValidateProgramHeaders:\n"); |
| 145 NaClLog(4, "data_start = %08"NACL_PRIxPTR"\n", nap->data_start); | 190 NaClLog(4, "rodata_start = 0x%08"NACL_PRIxPTR"\n", nap->rodata_start); |
| 146 NaClLog(4, "data_end = %08"NACL_PRIxPTR"\n", data_end); | 191 NaClLog(4, "rodata_end = 0x%08"NACL_PRIxPTR"\n", rodata_end); |
| 147 NaClLog(4, "max_vaddr = %08"NACL_PRIxPTR"\n", max_vaddr); | 192 NaClLog(4, "data_start = 0x%08"NACL_PRIxPTR"\n", nap->data_start); |
| 193 NaClLog(4, "data_end = 0x%08"NACL_PRIxPTR"\n", data_end); |
| 194 NaClLog(4, "max_vaddr = 0x%08"NACL_PRIxPTR"\n", max_vaddr); |
| 148 | 195 |
| 149 #if 0 == NACL_DANGEROUS_DEBUG_MODE_DISABLE_INNER_SANDBOX | 196 #if 0 == NACL_DANGEROUS_DEBUG_MODE_DISABLE_INNER_SANDBOX |
| 150 nap->bundle_size = NaClElfImageGetBundleSize(image); | 197 nap->bundle_size = NaClElfImageGetBundleSize(image); |
| 151 if (nap->bundle_size == 0) { | 198 if (nap->bundle_size == 0) { |
| 152 ret = LOAD_BAD_ABI; | 199 ret = LOAD_BAD_ABI; |
| 153 goto done; | 200 goto done; |
| 154 } | 201 } |
| 155 #else | 202 #else |
| 156 /* pick some reasonable default for an un-sandboxed nexe */ | 203 /* pick some reasonable default for an un-sandboxed nexe */ |
| 157 nap->bundle_size = 32; | 204 nap->bundle_size = 32; |
| 158 #endif | 205 #endif |
| 159 nap->entry_pt = NaClElfImageGetEntryPoint(image); | 206 nap->entry_pt = NaClElfImageGetEntryPoint(image); |
| 160 | 207 |
| 161 NaClLog(2, | 208 NaClLog(2, |
| 162 "static_text_end: 0x%016"NACL_PRIxPTR" " | 209 "NaClApp addr space layout:\n"); |
| 163 "break_add: 0x%016"NACL_PRIxPTR" " | 210 NaClLog(2, |
| 164 "data_end: 0x%016"NACL_PRIxPTR" " | 211 "nap->static_text_end = 0x%016"NACL_PRIxPTR"\n", |
| 165 "entry_pt: 0x%016"NACL_PRIxPTR" " | 212 nap->static_text_end); |
| 166 "bundle_size: 0x%x\n", | 213 NaClLog(2, |
| 167 nap->static_text_end, | 214 "nap->dynamic_text_start = 0x%016"NACL_PRIxPTR"\n", |
| 168 nap->break_addr, | 215 nap->dynamic_text_start); |
| 169 nap->data_end, | 216 NaClLog(2, |
| 170 nap->entry_pt, | 217 "nap->dynamic_text_end = 0x%016"NACL_PRIxPTR"\n", |
| 218 nap->dynamic_text_end); |
| 219 NaClLog(2, |
| 220 "nap->rodata_start = 0x%016"NACL_PRIxPTR"\n", |
| 221 nap->rodata_start); |
| 222 NaClLog(2, |
| 223 "nap->data_start = 0x%016"NACL_PRIxPTR"\n", |
| 224 nap->data_start); |
| 225 NaClLog(2, |
| 226 "nap->data_end = 0x%016"NACL_PRIxPTR"\n", |
| 227 nap->data_end); |
| 228 NaClLog(2, |
| 229 "nap->break_addr = 0x%016"NACL_PRIxPTR"\n", |
| 230 nap->break_addr); |
| 231 NaClLog(2, |
| 232 "nap->entry_pt = 0x%016"NACL_PRIxPTR"\n", |
| 233 nap->entry_pt); |
| 234 NaClLog(2, |
| 235 "nap->bundle_size = 0x%x\n", |
| 171 nap->bundle_size); | 236 nap->bundle_size); |
| 172 | 237 |
| 173 if (!NaClAddrIsValidEntryPt(nap, nap->entry_pt)) { | 238 if (!NaClAddrIsValidEntryPt(nap, nap->entry_pt)) { |
| 174 ret = LOAD_BAD_ENTRY; | 239 ret = LOAD_BAD_ENTRY; |
| 175 goto done; | 240 goto done; |
| 176 } | 241 } |
| 177 | 242 |
| 178 /* | 243 /* |
| 179 * Basic address space layout sanity check. | 244 * Basic address space layout sanity check. |
| 180 */ | 245 */ |
| 181 if (0 != nap->data_start) { | 246 if (0 != nap->data_start) { |
| 182 if (data_end != max_vaddr) { | 247 if (data_end != max_vaddr) { |
| 183 NaClLog(LOG_INFO, "data segment is not last\n"); | 248 NaClLog(LOG_INFO, "data segment is not last\n"); |
| 184 ret = LOAD_DATA_NOT_LAST_SEGMENT; | 249 ret = LOAD_DATA_NOT_LAST_SEGMENT; |
| 185 goto done; | 250 goto done; |
| 186 } | 251 } |
| 187 } else if (0 != nap->rodata_start) { | 252 } else if (0 != nap->rodata_start) { |
| 188 if (rodata_end != max_vaddr) { | 253 if (NaClRoundAllocPage(rodata_end) != max_vaddr) { |
| 189 /* | 254 /* |
| 190 * This should be unreachable, but we include it just for | 255 * This should be unreachable, but we include it just for |
| 191 * completeness. | 256 * completeness. |
| 192 * | 257 * |
| 193 * Here is why it is unreachable: | 258 * Here is why it is unreachable: |
| 194 * | 259 * |
| 195 * NaClPhdrChecks checks the test segment starting address. The | 260 * NaClPhdrChecks checks the test segment starting address. The |
| 196 * only allowed loaded segments are text, data, and rodata. | 261 * only allowed loaded segments are text, data, and rodata. |
| 197 * Thus unless the rodata is in the trampoline region, it must | 262 * Thus unless the rodata is in the trampoline region, it must |
| 198 * be after the text. And NaClElfImageValidateProgramHeaders | 263 * be after the text. And NaClElfImageValidateProgramHeaders |
| (...skipping 16 matching lines...) Expand all Loading... |
| 215 ret = LOAD_TEXT_OVERLAPS_RODATA; | 280 ret = LOAD_TEXT_OVERLAPS_RODATA; |
| 216 goto done; | 281 goto done; |
| 217 } | 282 } |
| 218 } else if (0 != nap->data_start) { | 283 } else if (0 != nap->data_start) { |
| 219 if (NaClRoundAllocPage(NaClEndOfStaticText(nap)) > nap->data_start) { | 284 if (NaClRoundAllocPage(NaClEndOfStaticText(nap)) > nap->data_start) { |
| 220 ret = LOAD_TEXT_OVERLAPS_DATA; | 285 ret = LOAD_TEXT_OVERLAPS_DATA; |
| 221 goto done; | 286 goto done; |
| 222 } | 287 } |
| 223 } | 288 } |
| 224 | 289 |
| 290 if (0 != nap->rodata_start && |
| 291 NaClRoundAllocPage(nap->rodata_start) != nap->rodata_start) { |
| 292 NaClLog(LOG_INFO, "rodata_start not a multiple of allocation size\n"); |
| 293 ret = LOAD_BAD_RODATA_ALIGNMENT; |
| 294 goto done; |
| 295 } |
| 296 if (0 != nap->data_start && |
| 297 NaClRoundAllocPage(nap->data_start) != nap->data_start) { |
| 298 NaClLog(LOG_INFO, "data_start not a multiple of allocation size\n"); |
| 299 ret = LOAD_BAD_DATA_ALIGNMENT; |
| 300 goto done; |
| 301 } |
| 302 |
| 225 NaClLog(2, "Allocating address space\n"); | 303 NaClLog(2, "Allocating address space\n"); |
| 226 subret = NaClAllocAddrSpace(nap); | 304 subret = NaClAllocAddrSpace(nap); |
| 227 if (LOAD_OK != subret) { | 305 if (LOAD_OK != subret) { |
| 228 ret = subret; | 306 ret = subret; |
| 229 goto done; | 307 goto done; |
| 230 } | 308 } |
| 231 | 309 |
| 232 /* | 310 /* |
| 233 * NB: mem_map object has been initialized, but is empty. | 311 * NB: mem_map object has been initialized, but is empty. |
| 234 * NaClMakeDynamicTextShared does not touch it. | 312 * NaClMakeDynamicTextShared does not touch it. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 * about the memory pages and their current protection value. | 385 * about the memory pages and their current protection value. |
| 308 * | 386 * |
| 309 * The contents of the dynamic text region will get remapped as | 387 * The contents of the dynamic text region will get remapped as |
| 310 * non-writable. | 388 * non-writable. |
| 311 */ | 389 */ |
| 312 subret = NaClMemoryProtection(nap); | 390 subret = NaClMemoryProtection(nap); |
| 313 if (LOAD_OK != subret) { | 391 if (LOAD_OK != subret) { |
| 314 ret = subret; | 392 ret = subret; |
| 315 goto done; | 393 goto done; |
| 316 } | 394 } |
| 395 NaClLog(2, |
| 396 "NaClAppLoadFile done; addr space layout:\n"); |
| 397 NaClLog(2, |
| 398 "nap->static_text_end = 0x%016"NACL_PRIxPTR"\n", |
| 399 nap->static_text_end); |
| 400 NaClLog(2, |
| 401 "nap->dynamic_text_start = 0x%016"NACL_PRIxPTR"\n", |
| 402 nap->dynamic_text_start); |
| 403 NaClLog(2, |
| 404 "nap->dynamic_text_end = 0x%016"NACL_PRIxPTR"\n", |
| 405 nap->dynamic_text_end); |
| 406 NaClLog(2, |
| 407 "nap->rodata_start = 0x%016"NACL_PRIxPTR"\n", |
| 408 nap->rodata_start); |
| 409 NaClLog(2, |
| 410 "nap->data_start = 0x%016"NACL_PRIxPTR"\n", |
| 411 nap->data_start); |
| 412 NaClLog(2, |
| 413 "nap->data_end = 0x%016"NACL_PRIxPTR"\n", |
| 414 nap->data_end); |
| 415 NaClLog(2, |
| 416 "nap->break_addr = 0x%016"NACL_PRIxPTR"\n", |
| 417 nap->break_addr); |
| 418 NaClLog(2, |
| 419 "nap->entry_pt = 0x%016"NACL_PRIxPTR"\n", |
| 420 nap->entry_pt); |
| 421 NaClLog(2, |
| 422 "nap->bundle_size = 0x%x\n", |
| 423 nap->bundle_size); |
| 317 | 424 |
| 318 ret = LOAD_OK; | 425 ret = LOAD_OK; |
| 319 done: | 426 done: |
| 320 NaClElfImageDelete(image); | 427 NaClElfImageDelete(image); |
| 321 return ret; | 428 return ret; |
| 322 } | 429 } |
| 323 | 430 |
| 324 int NaClAddrIsValidEntryPt(struct NaClApp *nap, | 431 int NaClAddrIsValidEntryPt(struct NaClApp *nap, |
| 325 uintptr_t addr) { | 432 uintptr_t addr) { |
| 326 if (0 != (addr & (nap->bundle_size - 1))) { | 433 if (0 != (addr & (nap->bundle_size - 1))) { |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 sys_tdb, | 703 sys_tdb, |
| 597 tdb_size)) { | 704 tdb_size)) { |
| 598 NaClLog(LOG_WARNING, | 705 NaClLog(LOG_WARNING, |
| 599 ("NaClCreateAdditionalThread: could not allocate thread index." | 706 ("NaClCreateAdditionalThread: could not allocate thread index." |
| 600 " Returning EAGAIN per POSIX specs.\n")); | 707 " Returning EAGAIN per POSIX specs.\n")); |
| 601 free(natp); | 708 free(natp); |
| 602 return -NACL_ABI_EAGAIN; | 709 return -NACL_ABI_EAGAIN; |
| 603 } | 710 } |
| 604 return 0; | 711 return 0; |
| 605 } | 712 } |
| OLD | NEW |