OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * NaCl helper functions to deal with elf images | 8 * NaCl helper functions to deal with elf images |
9 */ | 9 */ |
10 | 10 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 | 148 |
149 | 149 |
150 NaClErrorCode NaClElfImageValidateElfHeader(struct NaClElfImage *image) { | 150 NaClErrorCode NaClElfImageValidateElfHeader(struct NaClElfImage *image) { |
151 const Elf_Ehdr *hdr = &image->ehdr; | 151 const Elf_Ehdr *hdr = &image->ehdr; |
152 | 152 |
153 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG)) { | 153 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG)) { |
154 NaClLog(LOG_ERROR, "bad elf magic\n"); | 154 NaClLog(LOG_ERROR, "bad elf magic\n"); |
155 return LOAD_BAD_ELF_MAGIC; | 155 return LOAD_BAD_ELF_MAGIC; |
156 } | 156 } |
157 | 157 |
158 #if NACL_TARGET_SUBARCH == 64 | |
159 if (ELFCLASS64 != hdr->e_ident[EI_CLASS]) { | |
160 NaClLog(LOG_ERROR, "bad elf class\n"); | |
161 return LOAD_NOT_64_BIT; | |
162 } | |
163 #else | |
164 if (ELFCLASS32 != hdr->e_ident[EI_CLASS]) { | 158 if (ELFCLASS32 != hdr->e_ident[EI_CLASS]) { |
165 NaClLog(LOG_ERROR, "bad elf class\n"); | 159 NaClLog(LOG_ERROR, "bad elf class\n"); |
166 return LOAD_NOT_32_BIT; | 160 return LOAD_NOT_32_BIT; |
167 } | 161 } |
168 #endif | |
169 | 162 |
170 if (ET_EXEC != hdr->e_type) { | 163 if (ET_EXEC != hdr->e_type) { |
171 NaClLog(LOG_ERROR, "non executable\n"); | 164 NaClLog(LOG_ERROR, "non executable\n"); |
172 return LOAD_NOT_EXEC; | 165 return LOAD_NOT_EXEC; |
173 } | 166 } |
174 | 167 |
175 if (EM_EXPECTED_BY_NACL != hdr->e_machine) { | 168 if (EM_EXPECTED_BY_NACL != hdr->e_machine) { |
176 NaClLog(LOG_ERROR, "bad machine: %"NACL_PRIxElf_Half"\n", hdr->e_machine); | 169 NaClLog(LOG_ERROR, "bad machine: %"NACL_PRIxElf_Half"\n", hdr->e_machine); |
177 return LOAD_BAD_MACHINE; | 170 return LOAD_BAD_MACHINE; |
178 } | 171 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 } | 268 } |
276 if (php->p_vaddr < NACL_TRAMPOLINE_END) { | 269 if (php->p_vaddr < NACL_TRAMPOLINE_END) { |
277 NaClLog(2, | 270 NaClLog(2, |
278 ("Segment %d: virtual address (0x%08"NACL_PRIxElf_Addr | 271 ("Segment %d: virtual address (0x%08"NACL_PRIxElf_Addr |
279 ") too low\n"), | 272 ") too low\n"), |
280 segnum, | 273 segnum, |
281 php->p_vaddr); | 274 php->p_vaddr); |
282 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; | 275 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
283 } | 276 } |
284 /* | 277 /* |
285 * integer overflow? Elf_Addr and Elf_Word are uint32_t or | 278 * integer overflow? Elf_Addr and Elf_Word are always uint32_t, |
286 * uint64_t, so the addition/comparison is well defined. | 279 * so the addition/comparison is well defined but we need to do |
280 * a 64-bit comparison when addr_bits is 32. | |
287 */ | 281 */ |
288 if (php->p_vaddr + php->p_memsz < php->p_vaddr) { | 282 if (php->p_vaddr + php->p_memsz < php->p_vaddr) { |
289 NaClLog(2, | 283 NaClLog(2, |
290 "Segment %d: p_memsz caused integer overflow\n", | 284 "Segment %d: p_memsz caused integer overflow\n", |
291 segnum); | 285 segnum); |
292 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; | 286 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
293 } | 287 } |
294 if (php->p_vaddr + php->p_memsz >= ((Elf_Addr) 1U << addr_bits)) { | 288 if (php->p_vaddr + php->p_memsz >= ((uint64_t) 1U << addr_bits)) { |
bsy
2011/10/11 00:26:52
the sum can overflow since the add is done as uint
| |
295 NaClLog(2, | 289 NaClLog(2, |
296 "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n", | 290 "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n", |
297 segnum, | 291 segnum, |
298 php->p_vaddr + php->p_memsz); | 292 php->p_vaddr + php->p_memsz); |
299 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; | 293 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
300 } | 294 } |
301 if (php->p_filesz > php->p_memsz) { | 295 if (php->p_filesz > php->p_memsz) { |
302 NaClLog(2, | 296 NaClLog(2, |
303 ("Segment %d: file size 0x%08"NACL_PRIxElf_Xword" larger" | 297 ("Segment %d: file size 0x%08"NACL_PRIxElf_Xword" larger" |
304 " than memory size 0x%08"NACL_PRIxElf_Xword"\n"), | 298 " than memory size 0x%08"NACL_PRIxElf_Xword"\n"), |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 */ | 350 */ |
357 | 351 |
358 return LOAD_OK; | 352 return LOAD_OK; |
359 } | 353 } |
360 | 354 |
361 | 355 |
362 struct NaClElfImage *NaClElfImageNew(struct Gio *gp, | 356 struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
363 NaClErrorCode *err_code) { | 357 NaClErrorCode *err_code) { |
364 struct NaClElfImage *result; | 358 struct NaClElfImage *result; |
365 struct NaClElfImage image; | 359 struct NaClElfImage image; |
360 union { | |
361 Elf32_Ehdr ehdr32; | |
362 #if NACL_TARGET_SUBARCH == 64 | |
363 Elf64_Ehdr ehdr64; | |
364 #endif | |
365 } ehdr; | |
366 int cur_ph; | 366 int cur_ph; |
367 | 367 |
368 memset(image.loadable, 0, sizeof image.loadable); | 368 memset(image.loadable, 0, sizeof image.loadable); |
369 if (-1 == (*gp->vtbl->Seek)(gp, 0, 0)) { | 369 if (-1 == (*gp->vtbl->Seek)(gp, 0, 0)) { |
370 NaClLog(2, "could not seek to beginning of Gio object containing nexe\n"); | 370 NaClLog(2, "could not seek to beginning of Gio object containing nexe\n"); |
371 if (NULL != err_code) { | 371 if (NULL != err_code) { |
372 *err_code = LOAD_READ_ERROR; | 372 *err_code = LOAD_READ_ERROR; |
373 } | 373 } |
374 return 0; | 374 return 0; |
375 } | 375 } |
376 if ((*gp->vtbl->Read)(gp, | 376 if ((*gp->vtbl->Read)(gp, |
377 &image.ehdr, | 377 &ehdr, |
378 sizeof image.ehdr) | 378 sizeof ehdr) |
bsy
2011/10/11 00:26:52
maybe a comment here that reading the size of the
| |
379 != sizeof image.ehdr) { | 379 != sizeof ehdr) { |
380 if (NULL != err_code) { | 380 if (NULL != err_code) { |
381 *err_code = LOAD_READ_ERROR; | 381 *err_code = LOAD_READ_ERROR; |
382 } | 382 } |
383 NaClLog(2, "could not load elf headers\n"); | 383 NaClLog(2, "could not load elf headers\n"); |
384 return 0; | 384 return 0; |
385 } | 385 } |
386 | 386 |
387 #if NACL_TARGET_SUBARCH == 64 | |
388 if (ELFCLASS64 == ehdr.ehdr64.e_ident[EI_CLASS]) { | |
389 /* | |
390 * Convert ELFCLASS64 format to ELFCLASS32 format. | |
391 * The initial four fields are the same in both classes. | |
392 */ | |
393 memcpy(image.ehdr.e_ident, ehdr.ehdr64.e_ident, EI_NIDENT); | |
394 image.ehdr.e_ident[EI_CLASS] = ELFCLASS32; | |
395 image.ehdr.e_type = ehdr.ehdr64.e_type; | |
396 image.ehdr.e_machine = ehdr.ehdr64.e_machine; | |
397 image.ehdr.e_version = ehdr.ehdr64.e_version; | |
398 if (ehdr.ehdr64.e_entry > 0xffffffffU || | |
399 ehdr.ehdr64.e_phoff > 0xffffffffU || | |
400 ehdr.ehdr64.e_shoff > 0xffffffffU) { | |
401 if (NULL != err_code) { | |
402 *err_code = LOAD_EHDR_OVERFLOW; | |
403 } | |
404 NaClLog(2, "ELFCLASS64 file header fields overflow 32 bits\n"); | |
405 return 0; | |
406 } | |
407 image.ehdr.e_entry = (Elf32_Addr) ehdr.ehdr64.e_entry; | |
408 image.ehdr.e_phoff = (Elf32_Off) ehdr.ehdr64.e_phoff; | |
409 image.ehdr.e_shoff = (Elf32_Off) ehdr.ehdr64.e_shoff; | |
410 image.ehdr.e_flags = ehdr.ehdr64.e_flags; | |
411 if (ehdr.ehdr64.e_ehsize < sizeof(ehdr.ehdr64)) { | |
412 if (NULL != err_code) { | |
413 *err_code = LOAD_BAD_EHSIZE; | |
414 } | |
415 NaClLog(2, "ELFCLASS64 file e_ehsize != %d\n", (int) sizeof(ehdr.ehdr64)); | |
416 return 0; | |
417 } | |
418 image.ehdr.e_ehsize = sizeof(image.ehdr); | |
419 image.ehdr.e_phentsize = sizeof(image.phdrs[0]); | |
420 image.ehdr.e_phnum = ehdr.ehdr64.e_phnum; | |
421 image.ehdr.e_shentsize = ehdr.ehdr64.e_shentsize; | |
422 image.ehdr.e_shnum = ehdr.ehdr64.e_shnum; | |
423 image.ehdr.e_shstrndx = ehdr.ehdr64.e_shstrndx; | |
424 } else | |
425 #endif | |
426 { | |
427 image.ehdr = ehdr.ehdr32; | |
428 } | |
429 | |
387 NaClDumpElfHeader(2, &image.ehdr); | 430 NaClDumpElfHeader(2, &image.ehdr); |
388 | 431 |
389 /* read program headers */ | 432 /* read program headers */ |
390 if (image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) { | 433 if (image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) { |
391 if (NULL != err_code) | 434 if (NULL != err_code) |
392 *err_code = LOAD_TOO_MANY_PROG_HDRS; | 435 *err_code = LOAD_TOO_MANY_PROG_HDRS; |
393 NaClLog(2, "too many prog headers\n"); | 436 NaClLog(2, "too many prog headers\n"); |
394 return 0; | 437 return 0; |
395 } | 438 } |
396 | 439 |
397 if (image.ehdr.e_phentsize < sizeof image.phdrs[0]) { | |
398 if (NULL != err_code) { | |
399 *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; | |
400 } | |
401 NaClLog(2, "bad prog headers size\n"); | |
402 NaClLog(2, " image.ehdr.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", | |
403 image.ehdr.e_phentsize); | |
404 NaClLog(2, " sizeof image.phdrs[0] = 0x%"NACL_PRIxS"\n", | |
405 sizeof image.phdrs[0]); | |
406 return 0; | |
407 } | |
408 | |
409 /* | 440 /* |
410 * NB: cast from e_phoff to off_t may not be valid, since off_t can be | 441 * NB: cast from e_phoff to off_t may not be valid, since off_t can be |
411 * smaller than Elf64_off, but since invalid values will be rejected | 442 * smaller than Elf64_off, but since invalid values will be rejected |
412 * by Seek() the cast is safe (cf bsy) | 443 * by Seek() the cast is safe (cf bsy) |
413 */ | 444 */ |
414 if ((*gp->vtbl->Seek)(gp, | 445 if ((*gp->vtbl->Seek)(gp, |
415 (off_t) image.ehdr.e_phoff, | 446 (off_t) image.ehdr.e_phoff, |
416 SEEK_SET) == (off_t) -1) { | 447 SEEK_SET) == (off_t) -1) { |
417 if (NULL != err_code) { | 448 if (NULL != err_code) { |
418 *err_code = LOAD_READ_ERROR; | 449 *err_code = LOAD_READ_ERROR; |
419 } | 450 } |
420 NaClLog(2, "cannot seek tp prog headers\n"); | 451 NaClLog(2, "cannot seek tp prog headers\n"); |
421 return 0; | 452 return 0; |
422 } | 453 } |
423 | 454 |
424 if ((size_t) (*gp->vtbl->Read)(gp, | 455 #if NACL_TARGET_SUBARCH == 64 |
425 &image.phdrs[0], | 456 if (ELFCLASS64 == ehdr.ehdr64.e_ident[EI_CLASS]) { |
426 image.ehdr.e_phnum * sizeof image.phdrs[0]) | 457 /* |
427 != (image.ehdr.e_phnum * sizeof image.phdrs[0])) { | 458 * We'll load the 64-bit phdrs and convert them to 32-bit format. |
428 if (NULL != err_code) { | 459 */ |
429 *err_code = LOAD_READ_ERROR; | 460 Elf64_Phdr phdr64[NACL_MAX_PROGRAM_HEADERS]; |
461 | |
462 if (ehdr.ehdr64.e_phentsize < sizeof(Elf64_Phdr)) { | |
463 if (NULL != err_code) { | |
464 *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; | |
465 } | |
466 NaClLog(2, "bad prog headers size\n"); | |
467 NaClLog(2, " ehdr64.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", | |
468 ehdr.ehdr64.e_phentsize); | |
469 NaClLog(2, " sizeof(Elf64_Phdr) = 0x%"NACL_PRIxS"\n", | |
470 sizeof(Elf64_Phdr)); | |
471 return 0; | |
430 } | 472 } |
431 NaClLog(2, "cannot load tp prog headers\n"); | 473 |
432 return 0; | 474 if ((size_t) (*gp->vtbl->Read)(gp, |
475 &phdr64[0], | |
476 image.ehdr.e_phnum * sizeof phdr64[0]) | |
477 != (image.ehdr.e_phnum * sizeof phdr64[0])) { | |
478 if (NULL != err_code) { | |
479 *err_code = LOAD_READ_ERROR; | |
480 } | |
481 NaClLog(2, "cannot load tp prog headers\n"); | |
482 return 0; | |
483 } | |
484 | |
485 for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { | |
486 if (phdr64[cur_ph].p_offset > 0xffffffffU || | |
487 phdr64[cur_ph].p_vaddr > 0xffffffffU || | |
488 phdr64[cur_ph].p_paddr > 0xffffffffU || | |
489 phdr64[cur_ph].p_filesz > 0xffffffffU || | |
490 phdr64[cur_ph].p_memsz > 0xffffffffU || | |
491 phdr64[cur_ph].p_align > 0xffffffffU) { | |
492 if (NULL != err_code) { | |
493 *err_code = LOAD_PHDR_OVERFLOW; | |
494 } | |
495 NaClLog(2, "ELFCLASS64 program header fields overflow 32 bits\n"); | |
496 return 0; | |
497 } | |
498 image.phdrs[cur_ph].p_type = phdr64[cur_ph].p_type; | |
499 image.phdrs[cur_ph].p_offset = (Elf32_Off) phdr64[cur_ph].p_offset; | |
500 image.phdrs[cur_ph].p_vaddr = (Elf32_Addr) phdr64[cur_ph].p_vaddr; | |
501 image.phdrs[cur_ph].p_paddr = (Elf32_Addr) phdr64[cur_ph].p_paddr; | |
502 image.phdrs[cur_ph].p_filesz = (Elf32_Word) phdr64[cur_ph].p_filesz; | |
503 image.phdrs[cur_ph].p_memsz = (Elf32_Word) phdr64[cur_ph].p_memsz; | |
504 image.phdrs[cur_ph].p_flags = phdr64[cur_ph].p_flags; | |
505 image.phdrs[cur_ph].p_align = (Elf32_Word) phdr64[cur_ph].p_align; | |
506 } | |
507 } else | |
508 #endif | |
509 { | |
510 if (image.ehdr.e_phentsize < sizeof image.phdrs[0]) { | |
511 if (NULL != err_code) { | |
512 *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; | |
513 } | |
514 NaClLog(2, "bad prog headers size\n"); | |
515 NaClLog(2, " image.ehdr.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", | |
516 image.ehdr.e_phentsize); | |
517 NaClLog(2, " sizeof image.phdrs[0] = 0x%"NACL_PRIxS"\n", | |
518 sizeof image.phdrs[0]); | |
519 return 0; | |
520 } | |
521 | |
522 if ((size_t) (*gp->vtbl->Read)(gp, | |
523 &image.phdrs[0], | |
524 image.ehdr.e_phnum * sizeof image.phdrs[0]) | |
525 != (image.ehdr.e_phnum * sizeof image.phdrs[0])) { | |
526 if (NULL != err_code) { | |
527 *err_code = LOAD_READ_ERROR; | |
528 } | |
529 NaClLog(2, "cannot load tp prog headers\n"); | |
530 return 0; | |
531 } | |
433 } | 532 } |
434 | 533 |
435 NaClLog(2, "=================================================\n"); | 534 NaClLog(2, "=================================================\n"); |
436 NaClLog(2, "Elf Program headers\n"); | 535 NaClLog(2, "Elf Program headers\n"); |
437 NaClLog(2, "==================================================\n"); | 536 NaClLog(2, "==================================================\n"); |
438 for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { | 537 for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { |
439 NaClDumpElfProgramHeader(2, &image.phdrs[cur_ph]); | 538 NaClDumpElfProgramHeader(2, &image.phdrs[cur_ph]); |
440 } | 539 } |
441 | 540 |
442 /* we delay allocating till the end to avoid cleanup code */ | 541 /* we delay allocating till the end to avoid cleanup code */ |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
601 size_t mapping_size = NaClRoundAllocPage(php->p_memsz); | 700 size_t mapping_size = NaClRoundAllocPage(php->p_memsz); |
602 /* | 701 /* |
603 * Note that we do not used NACL_ABI_MAP_FIXED because we do not | 702 * Note that we do not used NACL_ABI_MAP_FIXED because we do not |
604 * want to silently overwrite any existing mappings, such as the | 703 * want to silently overwrite any existing mappings, such as the |
605 * user app's data segment or the stack. We detect overmapping | 704 * user app's data segment or the stack. We detect overmapping |
606 * when mmap chooses not to use the preferred address we supply. | 705 * when mmap chooses not to use the preferred address we supply. |
607 * (Ideally mmap would provide a MAP_EXCL option for this | 706 * (Ideally mmap would provide a MAP_EXCL option for this |
608 * instead.) | 707 * instead.) |
609 */ | 708 */ |
610 result = NaClCommonSysMmapIntern( | 709 result = NaClCommonSysMmapIntern( |
611 nap, (void *) php->p_vaddr, mapping_size, | 710 nap, (void *) (uintptr_t) php->p_vaddr, mapping_size, |
612 NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, | 711 NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, |
613 NACL_ABI_MAP_ANONYMOUS | NACL_ABI_MAP_PRIVATE, | 712 NACL_ABI_MAP_ANONYMOUS | NACL_ABI_MAP_PRIVATE, |
614 -1, 0); | 713 -1, 0); |
615 if ((int32_t) php->p_vaddr != result) { | 714 if ((int32_t) php->p_vaddr != result) { |
616 NaClLog(1, "NaClElfImageLoadDynamically: failed to map data segment\n"); | 715 NaClLog(1, "NaClElfImageLoadDynamically: failed to map data segment\n"); |
617 return LOAD_UNLOADABLE; | 716 return LOAD_UNLOADABLE; |
618 } | 717 } |
619 if ((Elf_Word) (*gfile->vtbl->Read)(gfile, paddr, php->p_filesz) | 718 if ((Elf_Word) (*gfile->vtbl->Read)(gfile, paddr, php->p_filesz) |
620 != php->p_filesz) { | 719 != php->p_filesz) { |
621 NaClLog(1, "NaClElfImageLoadDynamically: " | 720 NaClLog(1, "NaClElfImageLoadDynamically: " |
(...skipping 30 matching lines...) Expand all Loading... | |
652 | 751 |
653 | 752 |
654 void NaClElfImageDelete(struct NaClElfImage *image) { | 753 void NaClElfImageDelete(struct NaClElfImage *image) { |
655 free(image); | 754 free(image); |
656 } | 755 } |
657 | 756 |
658 | 757 |
659 uintptr_t NaClElfImageGetEntryPoint(struct NaClElfImage *image) { | 758 uintptr_t NaClElfImageGetEntryPoint(struct NaClElfImage *image) { |
660 return image->ehdr.e_entry; | 759 return image->ehdr.e_entry; |
661 } | 760 } |
OLD | NEW |