struct NaClElfImage *NaClElfImageNew(struct Gio *gp) { struct NaClElfImage *result; struct NaClElfImage image; int cur_ph; memset(image.loadable, 0, sizeof image.loadable); /* fail if could not seek to beginning of Gio object containing nexe */ ZLOGFAIL(-1 == (*gp->vtbl->Seek)(gp, 0, 0), EIO, FAILED_MSG); /* fail if could not load elf headers*/ ZLOGFAIL((*gp->vtbl->Read)(gp, &image.ehdr, sizeof image.ehdr) != sizeof image.ehdr, EIO, FAILED_MSG); NaClDumpElfHeader(LOG_DEBUG, &image.ehdr); /* read program headers. fail if too many prog headers */ ZLOGFAIL(image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS, ENOEXEC, FAILED_MSG); /* fail if ELF program header size too small */ ZLOGFAIL(image.ehdr.e_phentsize < sizeof image.phdrs[0], ENOEXEC, "bad prog headers size. image.ehdr.e_phentsize = 0x%x, sizeof " "image.phdrs[0] = 0x%x", image.ehdr.e_phentsize, sizeof image.phdrs[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) * d'b: fail if cannot seek tp prog headers */ ZLOGFAIL((*gp->vtbl->Seek)(gp, (off_t)image.ehdr.e_phoff, SEEK_SET) == (off_t)-1, EIO, FAILED_MSG); /* fail if cannot load tp prog headers */ ZLOGFAIL((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]), EIO, FAILED_MSG); ZLOGS(LOG_DEBUG, "%020o (elf segments) %020o", 0, 0); for(cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) NaClDumpElfProgramHeader(LOG_DEBUG, &image.phdrs[cur_ph]); /* we delay allocating till the end to avoid cleanup code */ /* fail if not enough memory for image meta data */ result = g_malloc(sizeof image); ZLOGFAIL(result == NULL, ENOMEM, FAILED_MSG); memcpy(result, &image, sizeof image); return result; }
struct NaClElfImage *NaClElfImageNew(struct NaClDesc *ndp, NaClErrorCode *err_code) { ssize_t read_ret; struct NaClElfImage *result; struct NaClElfImage image; union { Elf32_Ehdr ehdr32; #if NACL_BUILD_SUBARCH == 64 Elf64_Ehdr ehdr64; #endif } ehdr; int cur_ph; memset(image.loadable, 0, sizeof image.loadable); /* * 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. */ read_ret = (*NACL_VTBL(NaClDesc, ndp)->PRead)(ndp, &ehdr, sizeof ehdr, 0); if (NaClSSizeIsNegErrno(&read_ret) || (size_t) read_ret != sizeof ehdr) { *err_code = LOAD_READ_ERROR; NaClLog(2, "could not load elf headers\n"); return 0; } #if NACL_BUILD_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) { *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)) { *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); *err_code = NaClElfImageValidateElfHeader(&image); if (LOAD_OK != *err_code) { return 0; } /* read program headers */ if (image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) { *err_code = LOAD_TOO_MANY_PROG_HDRS; NaClLog(2, "too many prog headers\n"); return 0; } #if NACL_BUILD_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)) { *err_code = LOAD_BAD_PHENTSIZE; 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. */ read_ret = (*NACL_VTBL(NaClDesc, ndp)-> PRead)(ndp, &phdr64[0], image.ehdr.e_phnum * sizeof phdr64[0], (nacl_off64_t) image.ehdr.e_phoff); if (NaClSSizeIsNegErrno(&read_ret) || (size_t) read_ret != image.ehdr.e_phnum * sizeof phdr64[0]) { *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) { *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]) { *err_code = LOAD_BAD_PHENTSIZE; 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; } read_ret = (*NACL_VTBL(NaClDesc, ndp)-> PRead)(ndp, &image.phdrs[0], image.ehdr.e_phnum * sizeof image.phdrs[0], (nacl_off64_t) image.ehdr.e_phoff); if (NaClSSizeIsNegErrno(&read_ret) || (size_t) read_ret != image.ehdr.e_phnum * sizeof image.phdrs[0]) { *err_code = LOAD_READ_ERROR; NaClLog(2, "cannot load tp prog headers\n"); return 0; } } NaClLog(2, "=================================================\n"); NaClLog(2, "Elf Program headers\n"); NaClLog(2, "==================================================\n"); for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { NaClDumpElfProgramHeader(2, &image.phdrs[cur_ph]); } /* we delay allocating till the end to avoid cleanup code */ result = malloc(sizeof image); if (result == 0) { *err_code = LOAD_NO_MEMORY; NaClLog(LOG_FATAL, "no enough memory for image meta data\n"); return 0; } memcpy(result, &image, sizeof image); *err_code = LOAD_OK; return result; }
struct NaClElfImage *NaClElfImageNew(struct Gio *gp, NaClErrorCode *err_code) { struct NaClElfImage *result; struct NaClElfImage image; int cur_ph; memset(image.loadable, 0, sizeof image.loadable); if (-1 == (*gp->vtbl->Seek)(gp, 0, 0)) { NaClLog(2, "could not seek to beginning of Gio object containing nexe\n"); if (NULL != err_code) { *err_code = LOAD_READ_ERROR; } return 0; } if ((*gp->vtbl->Read)(gp, &image.ehdr, sizeof image.ehdr) != sizeof image.ehdr) { if (NULL != err_code) { *err_code = LOAD_READ_ERROR; } NaClLog(2, "could not load elf headers\n"); return 0; } NaClDumpElfHeader(2, &image.ehdr); /* read program headers */ if (image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) { if (NULL != err_code) *err_code = LOAD_TOO_MANY_PROG_HDRS; NaClLog(2, "too many prog headers\n"); 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) { if (NULL != err_code) { *err_code = LOAD_READ_ERROR; } NaClLog(2, "cannot seek tp prog headers\n"); 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, "=================================================\n"); NaClLog(2, "Elf Program headers\n"); NaClLog(2, "==================================================\n"); for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { NaClDumpElfProgramHeader(2, &image.phdrs[cur_ph]); } /* we delay allocating till the end to avoid cleanup code */ result = malloc(sizeof image); if (result == 0) { if (NULL != err_code) { *err_code = LOAD_NO_MEMORY; } NaClLog(LOG_FATAL, "no enough memory for image meta data\n"); return 0; } memcpy(result, &image, sizeof image); return result; }