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 |