summaryrefslogtreecommitdiffstats
path: root/libelf/elf_begin.c
diff options
context:
space:
mode:
Diffstat (limited to 'libelf/elf_begin.c')
-rw-r--r--libelf/elf_begin.c172
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)