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); |