Chromium Code Reviews| Index: src/trusted/service_runtime/elf_util.c |
| diff --git a/src/trusted/service_runtime/elf_util.c b/src/trusted/service_runtime/elf_util.c |
| index 2c4365ee7053aeee43fb0d2d263454b5c96f4a93..07a63722a8855dee5dd4c00ec3ff736c9f650e6e 100644 |
| --- a/src/trusted/service_runtime/elf_util.c |
| +++ b/src/trusted/service_runtime/elf_util.c |
| @@ -155,17 +155,10 @@ NaClErrorCode NaClElfImageValidateElfHeader(struct NaClElfImage *image) { |
| return LOAD_BAD_ELF_MAGIC; |
| } |
| -#if NACL_TARGET_SUBARCH == 64 |
| - if (ELFCLASS64 != hdr->e_ident[EI_CLASS]) { |
| - NaClLog(LOG_ERROR, "bad elf class\n"); |
| - return LOAD_NOT_64_BIT; |
| - } |
| -#else |
| if (ELFCLASS32 != hdr->e_ident[EI_CLASS]) { |
| NaClLog(LOG_ERROR, "bad elf class\n"); |
| return LOAD_NOT_32_BIT; |
| } |
| -#endif |
| if (ET_EXEC != hdr->e_type) { |
| NaClLog(LOG_ERROR, "non executable\n"); |
| @@ -282,8 +275,9 @@ NaClErrorCode NaClElfImageValidateProgramHeaders( |
| return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
| } |
| /* |
| - * integer overflow? Elf_Addr and Elf_Word are uint32_t or |
| - * uint64_t, so the addition/comparison is well defined. |
| + * integer overflow? Elf_Addr and Elf_Word are always uint32_t, |
| + * so the addition/comparison is well defined but we need to do |
| + * a 64-bit comparison when addr_bits is 32. |
| */ |
| if (php->p_vaddr + php->p_memsz < php->p_vaddr) { |
| NaClLog(2, |
| @@ -291,7 +285,7 @@ NaClErrorCode NaClElfImageValidateProgramHeaders( |
| segnum); |
| return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
| } |
| - if (php->p_vaddr + php->p_memsz >= ((Elf_Addr) 1U << addr_bits)) { |
| + 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
|
| NaClLog(2, |
| "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n", |
| segnum, |
| @@ -363,6 +357,12 @@ struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
| NaClErrorCode *err_code) { |
| struct NaClElfImage *result; |
| struct NaClElfImage image; |
| + union { |
| + Elf32_Ehdr ehdr32; |
| +#if NACL_TARGET_SUBARCH == 64 |
| + Elf64_Ehdr ehdr64; |
| +#endif |
| + } ehdr; |
| int cur_ph; |
| memset(image.loadable, 0, sizeof image.loadable); |
| @@ -374,9 +374,9 @@ struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
| return 0; |
| } |
| if ((*gp->vtbl->Read)(gp, |
| - &image.ehdr, |
| - sizeof image.ehdr) |
| - != sizeof image.ehdr) { |
| + &ehdr, |
| + sizeof ehdr) |
|
bsy
2011/10/11 00:26:52
maybe a comment here that reading the size of the
|
| + != sizeof ehdr) { |
| if (NULL != err_code) { |
| *err_code = LOAD_READ_ERROR; |
| } |
| @@ -384,6 +384,49 @@ struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
| return 0; |
| } |
| +#if NACL_TARGET_SUBARCH == 64 |
| + if (ELFCLASS64 == ehdr.ehdr64.e_ident[EI_CLASS]) { |
| + /* |
| + * Convert ELFCLASS64 format to ELFCLASS32 format. |
| + * The initial four fields are the same in both classes. |
| + */ |
| + memcpy(image.ehdr.e_ident, ehdr.ehdr64.e_ident, EI_NIDENT); |
| + image.ehdr.e_ident[EI_CLASS] = ELFCLASS32; |
| + image.ehdr.e_type = ehdr.ehdr64.e_type; |
| + image.ehdr.e_machine = ehdr.ehdr64.e_machine; |
| + image.ehdr.e_version = ehdr.ehdr64.e_version; |
| + if (ehdr.ehdr64.e_entry > 0xffffffffU || |
| + ehdr.ehdr64.e_phoff > 0xffffffffU || |
| + ehdr.ehdr64.e_shoff > 0xffffffffU) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_EHDR_OVERFLOW; |
| + } |
| + NaClLog(2, "ELFCLASS64 file header fields overflow 32 bits\n"); |
| + return 0; |
| + } |
| + image.ehdr.e_entry = (Elf32_Addr) ehdr.ehdr64.e_entry; |
| + image.ehdr.e_phoff = (Elf32_Off) ehdr.ehdr64.e_phoff; |
| + image.ehdr.e_shoff = (Elf32_Off) ehdr.ehdr64.e_shoff; |
| + image.ehdr.e_flags = ehdr.ehdr64.e_flags; |
| + if (ehdr.ehdr64.e_ehsize < sizeof(ehdr.ehdr64)) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_BAD_EHSIZE; |
| + } |
| + NaClLog(2, "ELFCLASS64 file e_ehsize != %d\n", (int) sizeof(ehdr.ehdr64)); |
| + return 0; |
| + } |
| + image.ehdr.e_ehsize = sizeof(image.ehdr); |
| + image.ehdr.e_phentsize = sizeof(image.phdrs[0]); |
| + image.ehdr.e_phnum = ehdr.ehdr64.e_phnum; |
| + image.ehdr.e_shentsize = ehdr.ehdr64.e_shentsize; |
| + image.ehdr.e_shnum = ehdr.ehdr64.e_shnum; |
| + image.ehdr.e_shstrndx = ehdr.ehdr64.e_shstrndx; |
| + } else |
| +#endif |
| + { |
| + image.ehdr = ehdr.ehdr32; |
| + } |
| + |
| NaClDumpElfHeader(2, &image.ehdr); |
| /* read program headers */ |
| @@ -394,18 +437,6 @@ struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
| return 0; |
| } |
| - if (image.ehdr.e_phentsize < sizeof image.phdrs[0]) { |
| - if (NULL != err_code) { |
| - *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; |
| - } |
| - NaClLog(2, "bad prog headers size\n"); |
| - NaClLog(2, " image.ehdr.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", |
| - image.ehdr.e_phentsize); |
| - NaClLog(2, " sizeof image.phdrs[0] = 0x%"NACL_PRIxS"\n", |
| - sizeof image.phdrs[0]); |
| - return 0; |
| - } |
| - |
| /* |
| * NB: cast from e_phoff to off_t may not be valid, since off_t can be |
| * smaller than Elf64_off, but since invalid values will be rejected |
| @@ -421,15 +452,83 @@ struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
| return 0; |
| } |
| - if ((size_t) (*gp->vtbl->Read)(gp, |
| - &image.phdrs[0], |
| - image.ehdr.e_phnum * sizeof image.phdrs[0]) |
| - != (image.ehdr.e_phnum * sizeof image.phdrs[0])) { |
| - if (NULL != err_code) { |
| - *err_code = LOAD_READ_ERROR; |
| +#if NACL_TARGET_SUBARCH == 64 |
| + if (ELFCLASS64 == ehdr.ehdr64.e_ident[EI_CLASS]) { |
| + /* |
| + * We'll load the 64-bit phdrs and convert them to 32-bit format. |
| + */ |
| + Elf64_Phdr phdr64[NACL_MAX_PROGRAM_HEADERS]; |
| + |
| + if (ehdr.ehdr64.e_phentsize < sizeof(Elf64_Phdr)) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; |
| + } |
| + NaClLog(2, "bad prog headers size\n"); |
| + NaClLog(2, " ehdr64.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", |
| + ehdr.ehdr64.e_phentsize); |
| + NaClLog(2, " sizeof(Elf64_Phdr) = 0x%"NACL_PRIxS"\n", |
| + sizeof(Elf64_Phdr)); |
| + return 0; |
| + } |
| + |
| + if ((size_t) (*gp->vtbl->Read)(gp, |
| + &phdr64[0], |
| + image.ehdr.e_phnum * sizeof phdr64[0]) |
| + != (image.ehdr.e_phnum * sizeof phdr64[0])) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_READ_ERROR; |
| + } |
| + NaClLog(2, "cannot load tp prog headers\n"); |
| + return 0; |
| + } |
| + |
| + for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { |
| + if (phdr64[cur_ph].p_offset > 0xffffffffU || |
| + phdr64[cur_ph].p_vaddr > 0xffffffffU || |
| + phdr64[cur_ph].p_paddr > 0xffffffffU || |
| + phdr64[cur_ph].p_filesz > 0xffffffffU || |
| + phdr64[cur_ph].p_memsz > 0xffffffffU || |
| + phdr64[cur_ph].p_align > 0xffffffffU) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_PHDR_OVERFLOW; |
| + } |
| + NaClLog(2, "ELFCLASS64 program header fields overflow 32 bits\n"); |
| + return 0; |
| + } |
| + image.phdrs[cur_ph].p_type = phdr64[cur_ph].p_type; |
| + image.phdrs[cur_ph].p_offset = (Elf32_Off) phdr64[cur_ph].p_offset; |
| + image.phdrs[cur_ph].p_vaddr = (Elf32_Addr) phdr64[cur_ph].p_vaddr; |
| + image.phdrs[cur_ph].p_paddr = (Elf32_Addr) phdr64[cur_ph].p_paddr; |
| + image.phdrs[cur_ph].p_filesz = (Elf32_Word) phdr64[cur_ph].p_filesz; |
| + image.phdrs[cur_ph].p_memsz = (Elf32_Word) phdr64[cur_ph].p_memsz; |
| + image.phdrs[cur_ph].p_flags = phdr64[cur_ph].p_flags; |
| + image.phdrs[cur_ph].p_align = (Elf32_Word) phdr64[cur_ph].p_align; |
| + } |
| + } else |
| +#endif |
| + { |
| + if (image.ehdr.e_phentsize < sizeof image.phdrs[0]) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; |
| + } |
| + NaClLog(2, "bad prog headers size\n"); |
| + NaClLog(2, " image.ehdr.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", |
| + image.ehdr.e_phentsize); |
| + NaClLog(2, " sizeof image.phdrs[0] = 0x%"NACL_PRIxS"\n", |
| + sizeof image.phdrs[0]); |
| + return 0; |
| + } |
| + |
| + if ((size_t) (*gp->vtbl->Read)(gp, |
| + &image.phdrs[0], |
| + image.ehdr.e_phnum * sizeof image.phdrs[0]) |
| + != (image.ehdr.e_phnum * sizeof image.phdrs[0])) { |
| + if (NULL != err_code) { |
| + *err_code = LOAD_READ_ERROR; |
| + } |
| + NaClLog(2, "cannot load tp prog headers\n"); |
| + return 0; |
| } |
| - NaClLog(2, "cannot load tp prog headers\n"); |
| - return 0; |
| } |
| NaClLog(2, "=================================================\n"); |
| @@ -608,7 +707,7 @@ NaClErrorCode NaClElfImageLoadDynamically(struct NaClElfImage *image, |
| * instead.) |
| */ |
| result = NaClCommonSysMmapIntern( |
| - nap, (void *) php->p_vaddr, mapping_size, |
| + nap, (void *) (uintptr_t) php->p_vaddr, mapping_size, |
| NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, |
| NACL_ABI_MAP_ANONYMOUS | NACL_ABI_MAP_PRIVATE, |
| -1, 0); |