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

Unified 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: e_phentsize checks with != 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..582583054ff2df9e614ec748f6041f1a6e7c2505 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");
@@ -281,21 +274,18 @@ NaClErrorCode NaClElfImageValidateProgramHeaders(
php->p_vaddr);
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.
- */
- if (php->p_vaddr + php->p_memsz < php->p_vaddr) {
- NaClLog(2,
- "Segment %d: p_memsz caused integer overflow\n",
- segnum);
- return LOAD_SEGMENT_OUTSIDE_ADDRSPACE;
- }
- if (php->p_vaddr + php->p_memsz >= ((Elf_Addr) 1U << addr_bits)) {
- NaClLog(2,
- "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n",
- segnum,
- php->p_vaddr + php->p_memsz);
+ if (php->p_vaddr >= ((uint64_t) 1U << addr_bits) ||
+ ((uint64_t) 1U << addr_bits) - php->p_vaddr < php->p_memsz) {
+ if (php->p_vaddr + php->p_memsz < php->p_vaddr) {
+ NaClLog(2,
+ "Segment %d: p_memsz caused integer overflow\n",
+ segnum);
+ } else {
+ NaClLog(2,
+ "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n",
+ segnum,
+ php->p_vaddr + php->p_memsz);
+ }
return LOAD_SEGMENT_OUTSIDE_ADDRSPACE;
}
if (php->p_filesz > php->p_memsz) {
@@ -363,6 +353,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);
@@ -373,10 +369,16 @@ struct NaClElfImage *NaClElfImageNew(struct Gio *gp,
}
return 0;
}
+
+ /*
+ * We read the larger size of an ELFCLASS64 header even if it turns out
+ * we're reading an ELFCLASS32 file. No usable ELFCLASS32 binary could
+ * be so small that it's not larger than Elf64_Ehdr anyway.
+ */
if ((*gp->vtbl->Read)(gp,
- &image.ehdr,
- sizeof image.ehdr)
- != sizeof image.ehdr) {
+ &ehdr,
+ sizeof ehdr)
+ != sizeof ehdr) {
if (NULL != err_code) {
*err_code = LOAD_READ_ERROR;
}
@@ -384,6 +386,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)) {
bsy 2011/10/12 20:12:38 please change this < to !=
+ 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,23 +439,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
- * by Seek() the cast is safe (cf bsy)
- */
if ((*gp->vtbl->Seek)(gp,
(off_t) image.ehdr.e_phoff,
SEEK_SET) == (off_t) -1) {
@@ -421,15 +449,87 @@ 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;
bsy 2011/10/12 20:12:38 this is no longer "TOO_SMALL" but "WRONG_SIZE"
+ }
+ 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;
+ }
+
+ /*
+ * We know the multiplication won't overflow since we rejected
+ * e_phnum values larger than the small constant NACL_MAX_PROGRAM_HEADERS.
+ */
+ 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;
bsy 2011/10/12 20:12:38 ditto
+ }
+ 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 +708,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);
« 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