summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2014-11-17 00:33:36 +0100
committerMark Wielaard <[email protected]>2014-11-17 00:33:36 +0100
commit436275edd015ab6a6f8e164ee2292f74f03d2413 (patch)
tree3ae7d3d504f409719f7e3194b5121cfc1ccc8c32
parent2af7b4942ad1e08d6e0609afec4edc82588f089e (diff)
libelf: Fix handling of (extended) phnum.
If there is no e_phoff e_phnum cannot be trusted. Extended phnum can only be gotten if we have an actual section table and a shdr for section zero, Extended phnum can be too large to fit in the file (or a size_t). Signed-off-by: Mark Wielaard <[email protected]>
-rw-r--r--libelf/ChangeLog7
-rw-r--r--libelf/elf32_getphdr.c6
-rw-r--r--libelf/elf_getphdrnum.c18
-rw-r--r--src/ChangeLog6
-rw-r--r--src/readelf.c7
5 files changed, 36 insertions, 8 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index beb431fd..ef5da43d 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,5 +1,12 @@
2014-11-16 Mark Wielaard <[email protected]>
+ * elf32_getphdr.c (getphdr_wrlock): Check e_phoff isn't zero.
+ Check for too many pheaders.
+ * elf_getphdrnum.c (__elf_getphdrnum_rdlock): Check section zero
+ actually exists before handling PN_XNUM.
+
+2014-11-16 Mark Wielaard <[email protected]>
+
* gelf_getnote.c (gelf_getnote): Check padding overflow.
2014-11-16 Mark Wielaard <[email protected]>
diff --git a/libelf/elf32_getphdr.c b/libelf/elf32_getphdr.c
index e74e63fd..1b82a480 100644
--- a/libelf/elf32_getphdr.c
+++ b/libelf/elf32_getphdr.c
@@ -76,15 +76,17 @@ __elfw2(LIBELFBITS,getphdr_wrlock) (elf)
size_t phnum;
if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
goto out;
- if (phnum == 0)
+ if (phnum == 0 || ehdr->e_phoff == 0)
{
__libelf_seterrno (ELF_E_NO_PHDR);
goto out;
}
+ /* Check this doesn't overflow. */
size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
- if (ehdr->e_phoff > elf->maximum_size
+ if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))
+ || ehdr->e_phoff > elf->maximum_size
|| elf->maximum_size - ehdr->e_phoff < size)
{
__libelf_seterrno (ELF_E_INVALID_DATA);
diff --git a/libelf/elf_getphdrnum.c b/libelf/elf_getphdrnum.c
index 99649bee..d8e34d7e 100644
--- a/libelf/elf_getphdrnum.c
+++ b/libelf/elf_getphdrnum.c
@@ -1,5 +1,5 @@
/* Return number of program headers in the ELF file.
- Copyright (C) 2010 Red Hat, Inc.
+ Copyright (C) 2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -62,10 +62,18 @@ __elf_getphdrnum_rdlock (elf, dst)
/* If there are no section headers, perhaps this is really just 65536
written without PN_XNUM support. Either that or it's bad data. */
- if (likely (scns->cnt > 0))
- *dst = (elf->class == ELFCLASS32
- ? scns->data[0].shdr.e32->sh_info
- : scns->data[0].shdr.e64->sh_info);
+ if (elf->class == ELFCLASS32)
+ {
+ if (likely (scns->cnt > 0
+ && elf->state.elf32.scns.data[0].shdr.e32 != NULL))
+ *dst = scns->data[0].shdr.e32->sh_info;
+ }
+ else
+ {
+ if (likely (scns->cnt > 0
+ && elf->state.elf64.scns.data[0].shdr.e64 != NULL))
+ *dst = scns->data[0].shdr.e64->sh_info;
+ }
}
return 0;
diff --git a/src/ChangeLog b/src/ChangeLog
index fefd6c1d..737c6743 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,11 @@
2014-11-16 Mark Wielaard <[email protected]>
+ * readelf (process_elf_file): Set phnum to zero if there aren't
+ actually any pheaders.
+ (print_phdr): Check there actually is a phdr.
+
+2014-11-16 Mark Wielaard <[email protected]>
+
* readelf.c (print_cfa_program): Check block len before calling
print_ops.
diff --git a/src/readelf.c b/src/readelf.c
index 697a0e50..583b5daf 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -835,6 +835,11 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
gettext ("cannot determine number of program headers: %s"),
elf_errmsg (-1));
+ /* If there isn't actually a program header then set phnum to zero.
+ Don't do any extra work. gelf_getphdr will always return NULL. */
+ if (ehdr->e_phoff == 0)
+ phnum = 0;
+
/* For an ET_REL file, libdwfl has adjusted the in-core shdrs
and may have applied relocation to some sections.
So we need to get a fresh Elf handle on the file to display those. */
@@ -1157,7 +1162,7 @@ There are %d section headers, starting at offset %#" PRIx64 ":\n\
static void
print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
{
- if (ehdr->e_phnum == 0)
+ if (ehdr->e_phnum == 0 || ehdr->e_phoff == 0)
/* No program header, this is OK in relocatable objects. */
return;