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]

Re: malformed elf file causes readelf -e to hang forever


On Sun, 2015-01-25 at 15:05 -0800, Josh Stone wrote:
> On 01/25/2015 11:39 AM, Hanno Böck wrote:
> > Please see attached file, which is a malformed (fuzzed) elf file that
> > causes elfutil's readelf -e to hang, testet with the latest version
> > 0.161.
> > 
> > This was found with zzuf.
> 
> You should be fuzzing with git master, as Mark is still making a lot of
> commits for robustness.

Yes please. We made a lot of progress with elfutils 0.161, but we aren't
completely there yet. Also if possible please do add new samples to the
"Fuzzing elfutils -- various badness" bug report
https://bugzilla.redhat.com/show_bug.cgi?id=1170810
so we don't forget about any fuzzing issue found.

>   That said, I can reproduce this on master.
> 
> I'm not sure it's a hang, exactly, but it's a least a really huge loop.
> :)  I see it stuck in __libdwfl_addrsym::search_table with the end value
> of 1073741862, from the call "search_table (1, first_global)".
> 
> Debugging earlier, I see this comes from load_symtab, where the shdr is:
> 
> (gdb) p *shdr
> $4 = {
>   sh_name = 1,
>   sh_type = 2,
>   sh_flags = 0,
>   sh_addr = 0,
>   sh_offset = 7200,
>   sh_size = 1392,
>   sh_link = 33,
>   sh_info = 1073741862,
>   sh_addralign = 8,
>   sh_entsize = 24
> }
> 
> These are used as:
>     *syments = shdr->sh_size / shdr->sh_entsize;
>     *first_global = shdr->sh_info;
> 
> I guess it should be an error for first_global to be out of range, or at
> least clamp it to at most syments.

And we do that in find_symtab when we find the normal symtab or the aux
symtab. But in this case after we found the symtab we detect something
is fishy with the string table/shdrs, so we discard the result and fall
back to find_dynsym to get a backup symbol table through phdrs. Which
succeeds. dynsym only has global syms, so we don't need to set
first_global because it is initialized to zero. But... we forgot to
clear the original first_global we found when we discarded the result...
oops.

How does the following fix look?

From 6e576f095e6f3bb810e6388ed8e606eacb318b67 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Mon, 26 Jan 2015 16:34:57 +0100
Subject: [PATCH] libdwfl: Clear symtab result on error before using
 find_dynsym fallback.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

find_dynsym could succeed after find_symtab failed but had already set up
symdata, syments and first_global. find_dynsym would not set or clear
first_global since all syms in dynsym are global. Causing lots of failing
lookups when calling __libdwfl_addrsym if first_global was some huge
bogus value.

Reported-by: Hanno Böck <hanno@hboeck.de>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdwfl/ChangeLog              | 5 +++++
 libdwfl/dwfl_module_getdwarf.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 5a97578..d40dbae 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-26  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Explicitly clear symdata,
+	syments and first_global on elferr before calling find_dynsym.
+
 2014-12-27  Mark Wielaard  <mjw@redhat.com>
 
 	* dwfl_module_getsrc.c (dwfl_module_getsrc): Never match a line that
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 494407d..a31898a 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1083,6 +1083,9 @@ find_symtab (Dwfl_Module *mod)
   if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL)
     {
     elferr:
+      mod->symdata = NULL;
+      mod->syments = 0;
+      mod->first_global = 0;
       mod->symerr = DWFL_E (LIBELF, elf_errno ());
       goto aux_cleanup; /* This cleans up some more and tries find_dynsym.  */
     }
-- 
1.8.3.1


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