Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: src/trusted/service_runtime/elf_util.c

Issue 8161004: Handle ELFCLASS32 files for x86-64 (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: rebased; binary testdata committed separately Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/trusted/service_runtime/build.scons ('k') | src/trusted/service_runtime/nacl_error_code.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/trusted/service_runtime/build.scons ('k') | src/trusted/service_runtime/nacl_error_code.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698