* [COMMITTED] libelf: Fix handling of (extended) phnum.
@ 2014-11-16 23:38 Mark Wielaard
0 siblings, 0 replies; only message in thread
From: Mark Wielaard @ 2014-11-16 23:38 UTC (permalink / raw)
To: elfutils-devel
[-- Attachment #1: Type: text/plain, Size: 4549 bytes --]
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 <mjw@redhat.com>
---
libelf/ChangeLog | 7 +++++++
libelf/elf32_getphdr.c | 6 ++++--
libelf/elf_getphdrnum.c | 18 +++++++++++++-----
src/ChangeLog | 6 ++++++
src/readelf.c | 7 ++++++-
5 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index beb431f..ef5da43 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,5 +1,12 @@
2014-11-16 Mark Wielaard <mjw@redhat.com>
+ * 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 <mjw@redhat.com>
+
* gelf_getnote.c (gelf_getnote): Check padding overflow.
2014-11-16 Mark Wielaard <mjw@redhat.com>
diff --git a/libelf/elf32_getphdr.c b/libelf/elf32_getphdr.c
index e74e63f..1b82a48 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 99649be..d8e34d7 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 fefd6c1..737c674 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,11 @@
2014-11-16 Mark Wielaard <mjw@redhat.com>
+ * 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 <mjw@redhat.com>
+
* readelf.c (print_cfa_program): Check block len before calling
print_ops.
diff --git a/src/readelf.c b/src/readelf.c
index 697a0e5..583b5da 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;
--
1.8.3.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-11-16 23:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-16 23:38 [COMMITTED] libelf: Fix handling of (extended) phnum Mark Wielaard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).