diff options
Diffstat (limited to 'libelf/elf_begin.c')
-rw-r--r-- | libelf/elf_begin.c | 172 |
1 files changed, 91 insertions, 81 deletions
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 30abe0bf..213b5c0b 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -1,5 +1,5 @@ /* Create descriptor for processing file. - Copyright (C) 1998-2010, 2012, 2014 Red Hat, Inc. + Copyright (C) 1998-2010, 2012, 2014, 2015 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 1998. @@ -151,8 +151,8 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA && (ALLOW_UNALIGNED - || (((size_t) ((char *) map_address + offset)) - & (__alignof__ (Elf32_Ehdr) - 1)) == 0)) + || (((size_t) ((char *) map_address + ehdr.e32->e_shoff)) + & (__alignof__ (Elf32_Shdr) - 1)) == 0)) /* We can directly access the memory. */ result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff + offset))->sh_size; @@ -201,8 +201,8 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, Elf64_Xword size; if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA && (ALLOW_UNALIGNED - || (((size_t) ((char *) map_address + offset)) - & (__alignof__ (Elf64_Ehdr) - 1)) == 0)) + || (((size_t) ((char *) map_address + ehdr.e64->e_shoff)) + & (__alignof__ (Elf64_Shdr) - 1)) == 0)) /* We can directly access the memory. */ size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff + offset))->sh_size; @@ -306,17 +306,46 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, /* This is a 32-bit binary. */ if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA && (ALLOW_UNALIGNED - || ((((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0 - && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff) - & (__alignof__ (Elf32_Shdr) - 1)) == 0 - && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff) - & (__alignof__ (Elf32_Phdr) - 1)) == 0))) + || (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0)) { /* We can use the mmapped memory. */ elf->state.elf32.ehdr = ehdr; + } + else + { + /* Copy the ELF header. */ + elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident, + sizeof (Elf32_Ehdr)); - if (unlikely (ehdr->e_shoff >= maxsize) - || unlikely (maxsize - ehdr->e_shoff + if (e_ident[EI_DATA] != MY_ELFDATA) + { + CONVERT (elf->state.elf32.ehdr_mem.e_type); + CONVERT (elf->state.elf32.ehdr_mem.e_machine); + CONVERT (elf->state.elf32.ehdr_mem.e_version); + CONVERT (elf->state.elf32.ehdr_mem.e_entry); + CONVERT (elf->state.elf32.ehdr_mem.e_phoff); + CONVERT (elf->state.elf32.ehdr_mem.e_shoff); + CONVERT (elf->state.elf32.ehdr_mem.e_flags); + CONVERT (elf->state.elf32.ehdr_mem.e_ehsize); + CONVERT (elf->state.elf32.ehdr_mem.e_phentsize); + CONVERT (elf->state.elf32.ehdr_mem.e_phnum); + CONVERT (elf->state.elf32.ehdr_mem.e_shentsize); + CONVERT (elf->state.elf32.ehdr_mem.e_shnum); + CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx); + } + } + + /* Don't precache the phdr pointer here. + elf32_getphdr will validate it against the size when asked. */ + + Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff; + if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA + && (ALLOW_UNALIGNED + || (((uintptr_t) ((char *) ehdr + e_shoff) + & (__alignof__ (Elf32_Shdr) - 1)) == 0))) + { + if (unlikely (e_shoff >= maxsize) + || unlikely (maxsize - e_shoff < scncnt * sizeof (Elf32_Shdr))) { free_and_out: @@ -325,10 +354,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, return NULL; } elf->state.elf32.shdr - = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff); - - /* Don't precache the phdr pointer here. - elf32_getphdr will validate it against the size when asked. */ + = (Elf32_Shdr *) ((char *) ehdr + e_shoff); for (size_t cnt = 0; cnt < scncnt; ++cnt) { @@ -361,27 +387,6 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, } else { - /* Copy the ELF header. */ - elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident, - sizeof (Elf32_Ehdr)); - - if (e_ident[EI_DATA] != MY_ELFDATA) - { - CONVERT (elf->state.elf32.ehdr_mem.e_type); - CONVERT (elf->state.elf32.ehdr_mem.e_machine); - CONVERT (elf->state.elf32.ehdr_mem.e_version); - CONVERT (elf->state.elf32.ehdr_mem.e_entry); - CONVERT (elf->state.elf32.ehdr_mem.e_phoff); - CONVERT (elf->state.elf32.ehdr_mem.e_shoff); - CONVERT (elf->state.elf32.ehdr_mem.e_flags); - CONVERT (elf->state.elf32.ehdr_mem.e_ehsize); - CONVERT (elf->state.elf32.ehdr_mem.e_phentsize); - CONVERT (elf->state.elf32.ehdr_mem.e_phnum); - CONVERT (elf->state.elf32.ehdr_mem.e_shentsize); - CONVERT (elf->state.elf32.ehdr_mem.e_shnum); - CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx); - } - for (size_t cnt = 0; cnt < scncnt; ++cnt) { elf->state.elf32.scns.data[cnt].index = cnt; @@ -402,24 +407,50 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, /* This is a 64-bit binary. */ if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA && (ALLOW_UNALIGNED - || ((((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0 - && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff) - & (__alignof__ (Elf64_Shdr) - 1)) == 0 - && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff) - & (__alignof__ (Elf64_Phdr) - 1)) == 0))) + || (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0)) { /* We can use the mmapped memory. */ elf->state.elf64.ehdr = ehdr; + } + else + { + /* Copy the ELF header. */ + elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident, + sizeof (Elf64_Ehdr)); - if (unlikely (ehdr->e_shoff >= maxsize) - || unlikely (maxsize - ehdr->e_shoff + if (e_ident[EI_DATA] != MY_ELFDATA) + { + CONVERT (elf->state.elf64.ehdr_mem.e_type); + CONVERT (elf->state.elf64.ehdr_mem.e_machine); + CONVERT (elf->state.elf64.ehdr_mem.e_version); + CONVERT (elf->state.elf64.ehdr_mem.e_entry); + CONVERT (elf->state.elf64.ehdr_mem.e_phoff); + CONVERT (elf->state.elf64.ehdr_mem.e_shoff); + CONVERT (elf->state.elf64.ehdr_mem.e_flags); + CONVERT (elf->state.elf64.ehdr_mem.e_ehsize); + CONVERT (elf->state.elf64.ehdr_mem.e_phentsize); + CONVERT (elf->state.elf64.ehdr_mem.e_phnum); + CONVERT (elf->state.elf64.ehdr_mem.e_shentsize); + CONVERT (elf->state.elf64.ehdr_mem.e_shnum); + CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx); + } + } + + /* Don't precache the phdr pointer here. + elf64_getphdr will validate it against the size when asked. */ + + Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff; + if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA + && (ALLOW_UNALIGNED + || (((uintptr_t) ((char *) ehdr + e_shoff) + & (__alignof__ (Elf64_Shdr) - 1)) == 0))) + { + if (unlikely (e_shoff >= maxsize) + || unlikely (maxsize - e_shoff < scncnt * sizeof (Elf64_Shdr))) goto free_and_out; elf->state.elf64.shdr - = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff); - - /* Don't precache the phdr pointer here. - elf64_getphdr will validate it against the size when asked. */ + = (Elf64_Shdr *) ((char *) ehdr + e_shoff); for (size_t cnt = 0; cnt < scncnt; ++cnt) { @@ -452,27 +483,6 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, } else { - /* Copy the ELF header. */ - elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident, - sizeof (Elf64_Ehdr)); - - if (e_ident[EI_DATA] != MY_ELFDATA) - { - CONVERT (elf->state.elf64.ehdr_mem.e_type); - CONVERT (elf->state.elf64.ehdr_mem.e_machine); - CONVERT (elf->state.elf64.ehdr_mem.e_version); - CONVERT (elf->state.elf64.ehdr_mem.e_entry); - CONVERT (elf->state.elf64.ehdr_mem.e_phoff); - CONVERT (elf->state.elf64.ehdr_mem.e_shoff); - CONVERT (elf->state.elf64.ehdr_mem.e_flags); - CONVERT (elf->state.elf64.ehdr_mem.e_ehsize); - CONVERT (elf->state.elf64.ehdr_mem.e_phentsize); - CONVERT (elf->state.elf64.ehdr_mem.e_phnum); - CONVERT (elf->state.elf64.ehdr_mem.e_shentsize); - CONVERT (elf->state.elf64.ehdr_mem.e_shnum); - CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx); - } - for (size_t cnt = 0; cnt < scncnt; ++cnt) { elf->state.elf64.scns.data[cnt].index = cnt; @@ -749,10 +759,7 @@ read_long_names (Elf *elf) } /* NUL-terminate the string. */ - *runp = '\0'; - - /* Skip the NUL byte and the \012. */ - runp += 2; + *runp++ = '\0'; /* A sanity check. Somebody might have generated invalid archive. */ @@ -768,8 +775,7 @@ read_long_names (Elf *elf) /* Read the next archive header. */ int internal_function -__libelf_next_arhdr_wrlock (elf) - Elf *elf; +__libelf_next_arhdr_wrlock (Elf *elf) { struct ar_hdr *ar_hdr; Elf_Arhdr *elf_ar_hdr; @@ -924,9 +930,16 @@ __libelf_next_arhdr_wrlock (elf) INT_FIELD (ar_mode); INT_FIELD (ar_size); + if (elf_ar_hdr->ar_size < 0) + { + __libelf_seterrno (ELF_E_INVALID_ARCHIVE); + return -1; + } + /* Truncated file? */ size_t maxsize; - maxsize = elf->maximum_size - elf->state.ar.offset - sizeof (struct ar_hdr); + maxsize = (elf->start_offset + elf->maximum_size + - elf->state.ar.offset - sizeof (struct ar_hdr)); if ((size_t) elf_ar_hdr->ar_size > maxsize) elf_ar_hdr->ar_size = maxsize; @@ -1029,10 +1042,7 @@ write_file (int fd, Elf_Cmd cmd) /* Return a descriptor for the file belonging to FILDES. */ Elf * -elf_begin (fildes, cmd, ref) - int fildes; - Elf_Cmd cmd; - Elf *ref; +elf_begin (int fildes, Elf_Cmd cmd, Elf *ref) { Elf *retval; @@ -1053,7 +1063,7 @@ elf_begin (fildes, cmd, ref) return NULL; } - Elf *lock_dup_elf () + Elf *lock_dup_elf (void) { /* We need wrlock to dup an archive. */ if (ref->kind == ELF_K_AR) |