This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[COMMITTED] 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 <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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]