public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 13:49 Petr Machata
  0 siblings, 0 replies; 28+ messages in thread
From: Petr Machata @ 2014-11-11 13:49 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 427 bytes --]

Petr Machata <pmachata@redhat.com> writes:

> Hanno Böck <hanno@hboeck.de> writes:
>
>> I can't build elfutils git head with -m32 right now at all (likely
>> another bug? was possible a few days ago), so I can't test, but we can
>> probably assume that it was due to the systemwide libs it used.
>
> That would be my fault.  Is the following fix acceptable?

OK, I see Mark was quicker.  Please disregard.

Petr.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-13 21:55 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-13 21:55 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 409 bytes --]

Am Thu, 13 Nov 2014 22:51:47 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> Are you sure you are using the git master sources?
> The backtrace looks like it is using the system installed libdw.so.

Sorry, you're right. Everything's fine, I used LD_PRELOAD with a typo
in the path, doesn't crash if I do it right.

-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-13 21:51 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-13 21:51 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1631 bytes --]

On Thu, Nov 13, 2014 at 08:39:32PM +0100, Hanno Böck wrote:
> Am Thu, 13 Nov 2014 15:45:26 +0100
> schrieb Mark Wielaard <mjw@redhat.com>:
> 
> > I pushed this now to master as attached.
> 
> still crashes readelf -a in
> id:000116,src:000000,op:flip32,pos:5554

> Program received signal SIGSEGV, Segmentation fault.
> 0xf7d96112 in vfprintf () from /lib32/libc.so.6

Sorry, you'll have to dig into that one a bit deeper yourself, since it
doesn't crash for me, even on a (Fedora 21 beta) i686 setup.

Maybe you could install debuginfo for glibc and see what is being
passed to printf that seem to cause it to crash.

> (gdb) bt
> #0  0xf7d96112 in vfprintf () from /lib32/libc.so.6
> #1  0xf7d9c5c8 in printf () from /lib32/libc.so.6
> #2  0x0805163c in handle_symtab (ebl=0x8078b58, scn=0x807a140,
> shdr=0xffffca5c) at readelf.c:2245
> #3  0x08050fbb in print_symtab (ebl=0x8078b58, type=2) at readelf.c:2139
> #4  0x0804cb06 in process_elf_file (dwflmod=0x80789e8, fd=3) at
> readelf.c:887 #5  0x0804c1f4 in process_dwflmod (dwflmod=0x80789e8,
> userdata=0x80789f0, name=0x8078af8
> "id:000116,src:000000,op:flip32,pos:5554", base=134512640,
> arg=0xffffcc8c) at readelf.c:691 #6  0xf7f38be4 in dwfl_getmodules ()
> from /usr/lib32/libdw.so.1 #7  0x0804c66a in process_file (fd=3, 
>     fname=0xffffcfe6 "id:000116,src:000000,op:flip32,pos:5554",
> only_one=true) at readelf.c:790
> #8  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296

Are you sure you are using the git master sources?
The backtrace looks like it is using the system installed libdw.so.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-13 19:39 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-13 19:39 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1211 bytes --]

Am Thu, 13 Nov 2014 15:45:26 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> I pushed this now to master as attached.

still crashes readelf -a in
id:000116,src:000000,op:flip32,pos:5554


Program received signal SIGSEGV, Segmentation fault.
0xf7d96112 in vfprintf () from /lib32/libc.so.6
(gdb) bt
#0  0xf7d96112 in vfprintf () from /lib32/libc.so.6
#1  0xf7d9c5c8 in printf () from /lib32/libc.so.6
#2  0x0805163c in handle_symtab (ebl=0x8078b58, scn=0x807a140,
shdr=0xffffca5c) at readelf.c:2245
#3  0x08050fbb in print_symtab (ebl=0x8078b58, type=2) at readelf.c:2139
#4  0x0804cb06 in process_elf_file (dwflmod=0x80789e8, fd=3) at
readelf.c:887 #5  0x0804c1f4 in process_dwflmod (dwflmod=0x80789e8,
userdata=0x80789f0, name=0x8078af8
"id:000116,src:000000,op:flip32,pos:5554", base=134512640,
arg=0xffffcc8c) at readelf.c:691 #6  0xf7f38be4 in dwfl_getmodules ()
from /usr/lib32/libdw.so.1 #7  0x0804c66a in process_file (fd=3, 
    fname=0xffffcfe6 "id:000116,src:000000,op:flip32,pos:5554",
only_one=true) at readelf.c:790
#8  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296


-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-13 14:45 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-13 14:45 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1319 bytes --]

On Tue, 2014-11-11 at 17:57 +0100, Mark Wielaard wrote:
> On Tue, Nov 11, 2014 at 02:57:05PM +0100, Hanno Böck wrote:
> > Am Tue, 11 Nov 2014 14:53:52 +0100
> > schrieb Mark Wielaard <mjw@redhat.com>:
> > 
> > > On Tue, 2014-11-11 at 14:40 +0100, Hanno Böck wrote:
> > > > I still get a bunch of crashers with correct LD_LIBRARY_PATH on
> > > > readelf -a with 32 bit compile (CFLAGS="-m32 -g"):
> > > > sig:11,hash:378b8b26
> > > > sig:11,hash:1aa8d351
> > > > sig:11,hash:872fe371
> > > > from attachment eu-readelf-crasher-hangs-2.tar.xz
> > > > 
> > > > and
> > > > id:000113,src:000000,op:flip32,pos:5474
> > > > id:000116,src:000000,op:flip32,pos:5554
> > > > from attachment 
> > > > /tmp/elfutils-nm-crasher.tar.xz
> > > 
> > > Could you attach or post those files somewhere?
> > 
> > These are all in attachments of previous mails in this thread:
> > 
> > eu-readelf-crasher-hangs-2.tar.xz
> > https://lists.fedorahosted.org/pipermail/elfutils-devel/2014-November/004237.html
> > 
> > elfutils-nm-crasher.tar.xz
> > https://lists.fedorahosted.org/pipermail/elfutils-devel/2014-November/004249.html
> 
> Aha, apparently I am unable to write correct overflow checks... sigh.
> 
> Please try the following:
> [...]

I pushed this now to master as attached.

Cheers,

Mark

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-libelf-Fix-unsigned-overflow-check-in-elf_getdata.patch --]
[-- Type: text/x-patch, Size: 1456 bytes --]

From c50ddfca105a73f7567f3072831dcfbf49ad0567 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Thu, 13 Nov 2014 15:43:02 +0100
Subject: [PATCH] libelf: Fix unsigned overflow check in elf_getdata.

---
 libelf/ChangeLog     | 5 +++++
 libelf/elf_getdata.c | 5 ++---
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index a9d8c6f..45e220d 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Fix unsigned overflow
+	check.
+
 2014-11-08  Mark Wielaard  <mjw@redhat.com>
 
 	* elf_begin.c (__libelf_next_arhdr_wrlock): Use mempcpy not __mempcpy.
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index 33d35d6..1ce1e23 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -245,9 +245,8 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn)
 	  /* First see whether the information in the section header is
 	     valid and it does not ask for too much.  Check for unsigned
 	     overflow.  */
-	  if (unlikely (offset + size > elf->maximum_size
-			|| (offset + size + elf->maximum_size
-			    < elf->maximum_size)))
+	  if (unlikely (offset > elf->maximum_size
+	      || elf->maximum_size - offset < size))
 	    {
 	      /* Something is wrong.  */
 	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 16:57 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-11 16:57 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1947 bytes --]

On Tue, Nov 11, 2014 at 02:57:05PM +0100, Hanno Böck wrote:
> Am Tue, 11 Nov 2014 14:53:52 +0100
> schrieb Mark Wielaard <mjw@redhat.com>:
> 
> > On Tue, 2014-11-11 at 14:40 +0100, Hanno Böck wrote:
> > > I still get a bunch of crashers with correct LD_LIBRARY_PATH on
> > > readelf -a with 32 bit compile (CFLAGS="-m32 -g"):
> > > sig:11,hash:378b8b26
> > > sig:11,hash:1aa8d351
> > > sig:11,hash:872fe371
> > > from attachment eu-readelf-crasher-hangs-2.tar.xz
> > > 
> > > and
> > > id:000113,src:000000,op:flip32,pos:5474
> > > id:000116,src:000000,op:flip32,pos:5554
> > > from attachment 
> > > /tmp/elfutils-nm-crasher.tar.xz
> > 
> > Could you attach or post those files somewhere?
> 
> These are all in attachments of previous mails in this thread:
> 
> eu-readelf-crasher-hangs-2.tar.xz
> https://lists.fedorahosted.org/pipermail/elfutils-devel/2014-November/004237.html
> 
> elfutils-nm-crasher.tar.xz
> https://lists.fedorahosted.org/pipermail/elfutils-devel/2014-November/004249.html

Aha, apparently I am unable to write correct overflow checks... sigh.

Please try the following:

diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index 33d35d6..a60f3db 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -245,9 +245,8 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn)
          /* First see whether the information in the section header is
             valid and it does not ask for too much.  Check for unsigned
             overflow.  */
-         if (unlikely (offset + size > elf->maximum_size
-                       || (offset + size + elf->maximum_size
-                           < elf->maximum_size)))
+         if (unlikely (offset > elf->maximum_size
+                       || elf->maximum_size - offset < size))
            {
              /* Something is wrong.  */
              __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);

Thansk,

Mark


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 13:57 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-11 13:57 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 998 bytes --]

Am Tue, 11 Nov 2014 14:53:52 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> On Tue, 2014-11-11 at 14:40 +0100, Hanno Böck wrote:
> > I still get a bunch of crashers with correct LD_LIBRARY_PATH on
> > readelf -a with 32 bit compile (CFLAGS="-m32 -g"):
> > sig:11,hash:378b8b26
> > sig:11,hash:1aa8d351
> > sig:11,hash:872fe371
> > from attachment eu-readelf-crasher-hangs-2.tar.xz
> > 
> > and
> > id:000113,src:000000,op:flip32,pos:5474
> > id:000116,src:000000,op:flip32,pos:5554
> > from attachment 
> > /tmp/elfutils-nm-crasher.tar.xz
> 
> Could you attach or post those files somewhere?

These are all in attachments of previous mails in this thread:

eu-readelf-crasher-hangs-2.tar.xz
https://lists.fedorahosted.org/pipermail/elfutils-devel/2014-November/004237.html

elfutils-nm-crasher.tar.xz
https://lists.fedorahosted.org/pipermail/elfutils-devel/2014-November/004249.html

-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 13:53 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-11 13:53 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 523 bytes --]

On Tue, 2014-11-11 at 14:40 +0100, Hanno Böck wrote:
> I still get a bunch of crashers with correct LD_LIBRARY_PATH on
> readelf -a with 32 bit compile (CFLAGS="-m32 -g"):
> sig:11,hash:378b8b26
> sig:11,hash:1aa8d351
> sig:11,hash:872fe371
> from attachment eu-readelf-crasher-hangs-2.tar.xz
> 
> and
> id:000113,src:000000,op:flip32,pos:5474
> id:000116,src:000000,op:flip32,pos:5554
> from attachment 
> /tmp/elfutils-nm-crasher.tar.xz

Could you attach or post those files somewhere?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 13:40 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-11 13:40 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 5499 bytes --]

Am Tue, 11 Nov 2014 14:15:31 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> Replicated on Fedora 21 Beta i686. Fix pushed as attached.

Thanks, tested an works.

I still get a bunch of crashers with correct LD_LIBRARY_PATH on
readelf -a with 32 bit compile (CFLAGS="-m32 -g"):
sig:11,hash:378b8b26
sig:11,hash:1aa8d351
sig:11,hash:872fe371
from attachment eu-readelf-crasher-hangs-2.tar.xz

and
id:000113,src:000000,op:flip32,pos:5474
id:000116,src:000000,op:flip32,pos:5554
from attachment 
/tmp/elfutils-nm-crasher.tar.xz

I can't seem to valgrind them because it'll throw an illegal opcode
error before getting to the point where the non-valgrind-crash happens.
(I assume this is a valgrind bug, will try to report it there)

This is gdb:

File id:000113,src:000000,op:flip32,pos:5474
Program received signal SIGSEGV, Segmentation fault.
0xf7ddc112 in vfprintf () from /lib32/libc.so.6
(gdb) bt
#0  0xf7ddc112 in vfprintf () from /lib32/libc.so.6
#1  0xf7de25c8 in printf () from /lib32/libc.so.6
#2  0x0804dbca in print_shdr (ebl=0x8078a18, ehdr=0xffffcb3c) at
readelf.c:1138 #3  0x0804ca16 in process_elf_file (dwflmod=0x80788a8,
fd=3) at readelf.c:871 #4  0x0804c1f4 in process_dwflmod
(dwflmod=0x80788a8, userdata=0x80788b0, name=0x80789b8
"./c/id:000113,src:000000,op:flip32,pos:5474", base=134512640,
arg=0xffffcc8c) at readelf.c:691 #5  0xf7f7ebe4 in dwfl_getmodules ()
from /usr/lib32/libdw.so.1 #6  0x0804c66a in process_file (fd=3, 
    fname=0xffffcfdc "./c/id:000113,src:000000,op:flip32,pos:5474", 
    only_one=true) at readelf.c:790
#7  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296

000116,src:000000,op:flip32,pos:5554
Program received signal SIGSEGV, Segmentation fault.
0xf7ddc112 in vfprintf () from /lib32/libc.so.6
(gdb) bt
#0  0xf7ddc112 in vfprintf () from /lib32/libc.so.6
#1  0xf7de25c8 in printf () from /lib32/libc.so.6
#2  0x0805163c in handle_symtab (ebl=0x8078a18, scn=0x8079888,
shdr=0xffffca5c) at readelf.c:2245
#3  0x08050fbb in print_symtab (ebl=0x8078a18, type=2) at readelf.c:2139
#4  0x0804cb06 in process_elf_file (dwflmod=0x80788a8, fd=3) at
readelf.c:887 #5  0x0804c1f4 in process_dwflmod (dwflmod=0x80788a8,
userdata=0x80788b0, name=0x80789b8
"./c/id:000116,src:000000,op:flip32,pos:5554", base=134512640,
arg=0xffffcc8c) at readelf.c:691 #6  0xf7f7ebe4 in dwfl_getmodules ()
from /usr/lib32/libdw.so.1 #7  0x0804c66a in process_file (fd=3, 
    fname=0xffffcfdc "./c/id:000116,src:000000,op:flip32,pos:5554", 
    only_one=true) at readelf.c:790
#8  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296

sig:11,hash:73ad0820:
Program received signal SIGSEGV, Segmentation fault.
0xf7f584ab in gelf_getdyn () from /usr/lib32/libelf.so.1
(gdb) bt
#0  0xf7f584ab in gelf_getdyn () from /usr/lib32/libelf.so.1
#1  0x0804f1ea in handle_dynamic (ebl=0x8078a08, scn=0x807955c, 
    shdr=0xffffca5c) at readelf.c:1603
#2  0x0804f8ac in print_dynamic (ebl=0x8078a08) at readelf.c:1713
#3  0x0804ca70 in process_elf_file (dwflmod=0x80788a8, fd=3) at readelf.c:877
#4  0x0804c1f4 in process_dwflmod (dwflmod=0x80788a8, userdata=0x80788b0, 
    name=0x80789b8 "./b/crashes/sig:11,hash:73ad0820", base=4194304, 
    arg=0xffffcc8c) at readelf.c:691
#5  0xf7f7ebe4 in dwfl_getmodules () from /usr/lib32/libdw.so.1
#6  0x0804c66a in process_file (fd=3, 
    fname=0xffffcfe7 "./b/crashes/sig:11,hash:73ad0820", only_one=true)
    at readelf.c:790
#7  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296

sig:11,hash:872fe371
Program received signal SIGSEGV, Segmentation fault.
0xf7f589ce in gelf_getnote () from /usr/lib32/libelf.so.1
(gdb) bt
#0  0xf7f589ce in gelf_getnote () from /usr/lib32/libelf.so.1
#1  0x08066f36 in handle_notes_data (ebl=0x8078a08, ehdr=0xffffcb3c, 
    start=652, data=0x8078d34) at readelf.c:8980
#2  0x08067143 in handle_notes (ebl=0x8078a08, ehdr=0xffffcb3c)
    at readelf.c:9071
#3  0x0804cbc8 in process_elf_file (dwflmod=0x80788a8, fd=3) at
readelf.c:899 #4  0x0804c1f4 in process_dwflmod (dwflmod=0x80788a8,
userdata=0x80788b0, name=0x80789b8 "b/crashes/sig:11,hash:872fe371",
base=4194304, arg=0xffffcc8c) at readelf.c:691
#5  0xf7f7ebe4 in dwfl_getmodules () from /usr/lib32/libdw.so.1
#6  0x0804c66a in process_file (fd=3, 
    fname=0xffffcfe9 "b/crashes/sig:11,hash:872fe371", only_one=true)
    at readelf.c:790
#7  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296

sig:11,hash:378b8b26
Program received signal SIGSEGV, Segmentation fault.
0xf7f59088 in gelf_getsymshndx () from /usr/lib32/libelf.so.1
(gdb) bt
#0  0xf7f59088 in gelf_getsymshndx () from /usr/lib32/libelf.so.1
#1  0x08051486 in handle_symtab (ebl=0x8078a08, scn=0x8078e1c, shdr=0xffffca5c)
    at readelf.c:2236
#2  0x08050fbb in print_symtab (ebl=0x8078a08, type=11) at readelf.c:2139
#3  0x0804cacc in process_elf_file (dwflmod=0x80788a8, fd=3) at readelf.c:883
#4  0x0804c1f4 in process_dwflmod (dwflmod=0x80788a8, userdata=0x80788b0, 
    name=0x80789b8 "b/crashes/sig:11,hash:378b8b26", base=4194304, 
    arg=0xffffcc8c) at readelf.c:691
#5  0xf7f7ebe4 in dwfl_getmodules () from /usr/lib32/libdw.so.1
#6  0x0804c66a in process_file (fd=3, 
    fname=0xffffcfe9 "b/crashes/sig:11,hash:378b8b26", only_one=true)
    at readelf.c:790
#7  0x0804b13f in main (argc=3, argv=0xffffce04) at readelf.c:296


-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 13:30 Petr Machata
  0 siblings, 0 replies; 28+ messages in thread
From: Petr Machata @ 2014-11-11 13:30 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 3353 bytes --]

Hanno Böck <hanno@hboeck.de> writes:

> I can't build elfutils git head with -m32 right now at all (likely
> another bug? was possible a few days ago), so I can't test, but we can
> probably assume that it was due to the systemwide libs it used.

That would be my fault.  Is the following fix acceptable?

Subject: [PATCH] Fix compilation on x86

GCC finds two problems when compiling in 32-bit mode.

- First, the function __libdw_getsrclines is marked as internal only
  in the header, not in the C file, and in 32-bit mode, this is
  actually reported as a change in prototype.

- Second, address size is passed as a four-byte unsigned quantity, and
  GCC can't prove that it's safe to compare it with a four-byte signed
  quantity that is the result of pointer subtraction.  This is not a
  problem in 64-bit mode, where the 4-byte unsigned quantity can be
  losslessly converted to an 8-byte signed pointer difference.  But
  passing address size in a 4-byte type is overly generous, so revert
  back to uint8_t, like what CU's actually store.

Signed-off-by: Petr Machata <pmachata@redhat.com>
---
 libdw/ChangeLog           | 7 +++++++
 libdw/dwarf_getsrclines.c | 6 +++---
 libdw/libdwP.h            | 2 +-
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index d5796e8..0752566 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-11  Petr Machata  <pmachata@redhat.com>
+
+	* libdwP.h (__libdw_getsrclines): Pass address_size as uint8_t.
+	* dwarf_getsrclines.c (read_srclines): Likewise.
+	(__libdw_getsrclines): Likewise.  Also mark function as internal
+	here as well.
+
 2014-09-10  Petr Machata  <pmachata@redhat.com>
 
 	* dwarf_macro_getparamcnt.c: New file.
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 4bb19c2..959c460 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -70,7 +70,7 @@ compare_lines (const void *a, const void *b)
 static int
 read_srclines (Dwarf *dbg,
 	       const unsigned char *linep, const unsigned char *lineendp,
-	       const char *comp_dir, unsigned address_size,
+	       const char *comp_dir, uint8_t address_size,
 	       Dwarf_Lines **linesp, Dwarf_Files **filesp)
 {
   int res = -1;
@@ -729,9 +729,9 @@ files_lines_compare (const void *p1, const void *p2)
   return 0;
 }
 
-int
+internal_function int
 __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
-		     const char *comp_dir, unsigned address_size,
+		     const char *comp_dir, uint8_t address_size,
 		     Dwarf_Lines **linesp, Dwarf_Files **filesp)
 {
   struct files_lines_s fake = { .debug_line_offset = debug_line_offset };
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 5ccb13c..d798737 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -716,7 +716,7 @@ void __libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu)
    NULL) with loaded information.  Returns 0 for success or a negative
    value for failure.  */
 int __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
-			 const char *comp_dir, unsigned address_size,
+			 const char *comp_dir, uint8_t address_size,
 			 Dwarf_Lines **linesp, Dwarf_Files **filesp)
   internal_function
   __nonnull_attribute__ (1);
-- 
2.1.0


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 13:15 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-11 13:15 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

On Tue, 2014-11-11 at 11:31 +0100, Hanno Böck wrote:
> I can't build elfutils git head with -m32 right now at all (likely
> another bug? was possible a few days ago)

Replicated on Fedora 21 Beta i686. Fix pushed as attached.

You might need the recently posted "libdwfl: find_dynsym don't assume
dynamic linker has adjusted DYNAMIC entries." patch to get zero FAIL on
make check.

Thanks,

Mark

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-libdw-Fix-dwarf_getsrclines.c-32bit-compile-error.patch --]
[-- Type: text/x-patch, Size: 1904 bytes --]

From 09086238f39daab4060d0e5f39f89820a0771d8c Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Tue, 11 Nov 2014 14:10:04 +0100
Subject: [PATCH] libdw: Fix dwarf_getsrclines.c 32bit compile error.

__libdw_getsrclines should have been marked as internal_function in
both libdwP.h and dwarf_getsrclines.c. Do address_size comparison as
uint8_t to avoid signedness warning.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdw/ChangeLog           | 6 ++++++
 libdw/dwarf_getsrclines.c | 3 ++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index d5796e8..58736a6 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2014-11-11  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Do address_size comparison
+	explicitly as uint8_t.
+	(__libdw_getsrclines): Add internal_function to declaration.
+
 2014-09-10  Petr Machata  <pmachata@redhat.com>
 
 	* dwarf_macro_getparamcnt.c: New file.
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 4bb19c2..15881e8 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -428,7 +428,7 @@ read_srclines (Dwarf *dbg,
 		 apporiate for the target machine.  We use the
 		 address size field from the CU header.  */
 	      op_index = 0;
-	      if (unlikely (lineendp - linep < address_size))
+	      if (unlikely (lineendp - linep < (uint8_t) address_size))
 		goto invalid_data;
 	      if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
 					    address_size, &addr))
@@ -730,6 +730,7 @@ files_lines_compare (const void *p1, const void *p2)
 }
 
 int
+internal_function
 __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
 		     const char *comp_dir, unsigned address_size,
 		     Dwarf_Lines **linesp, Dwarf_Files **filesp)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-11 10:31 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-11 10:31 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 498 bytes --]

Am Mon, 10 Nov 2014 21:58:27 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> Note how here it seems to have picked up the system installed
> libdw.so.

Ah sorry, this likely explains the issues...

I can't build elfutils git head with -m32 right now at all (likely
another bug? was possible a few days ago), so I can't test, but we can
probably assume that it was due to the systemwide libs it used.

-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-10 20:58 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-10 20:58 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1328 bytes --]

On Sun, Nov 09, 2014 at 10:59:46PM +0100, Hanno Böck wrote:
> Am Sun, 09 Nov 2014 17:57:57 +0100
> schrieb Mark Wielaard <mjw@redhat.com>:
> 
> > > , however here are three more in
> > > nm. Seems they only crash on 32 bit.
> > 
> > I cannot get these to crash on either a fedora 20 x86_64 setup, nor
> > on a fedora 21-beta i686 setup. Could you run under gdb and provide a
> > backtrace?
> [...]
> Backtrace 2, id:000113,src:000000,op:flip32,pos:5474:
> Program received signal SIGSEGV, Segmentation fault.
> 0xf7dce3ab in __strcmp_ssse3 () from /lib32/libc.so.6
> (gdb) bt
> #0  0xf7dce3ab in __strcmp_ssse3 () from /lib32/libc.so.6
> #1  0xf7f6686d in ?? () from /usr/lib32/libdw.so.1
> #2  0xf7f66d80 in dwarf_begin_elf () from /usr/lib32/libdw.so.1

Note how here it seems to have picked up the system installed libdw.so.

Please make sure you setup LD_LIBRARY_PATH (should include backends,
libelf and libdw) correctly when running the tests.

I can only replicate your backtraces when using the system libelf/libdw,
not when running against lastest git master. e.g.

$ LD_LIBRARY_PATH=backends:libelf:libdw src/nm id\:000010\,src\:000000\,op\:flip1\,pos\:5556 

Symbols from id:000010,src:000000,op:flip1,pos:5556:

Name Value    Class  Type     Size     Line Section

Thanks,

Mark

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-09 21:59 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-09 21:59 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 3762 bytes --]

Am Sun, 09 Nov 2014 17:57:57 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> > , however here are three more in
> > nm. Seems they only crash on 32 bit.
> 
> I cannot get these to crash on either a fedora 20 x86_64 setup, nor
> on a fedora 21-beta i686 setup. Could you run under gdb and provide a
> backtrace?

Backtrace 1, id:000010,src:000000,op:flip1,pos:5556:
Program received signal SIGSEGV, Segmentation fault.
0x0804be85 in sort_by_name (p1=0xffffc310, p2=0xffffc330) at nm.c:1146
1146	  const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
(gdb) bt
#0  0x0804be85 in sort_by_name (p1=0xffffc310, p2=0xffffc330) at nm.c:1146
#1  0xf7cce30d in msort_with_tmp.part () from /lib32/libc.so.6
#2  0xf7cce217 in msort_with_tmp.part () from /lib32/libc.so.6
#3  0xf7cce200 in msort_with_tmp.part () from /lib32/libc.so.6
#4  0xf7cce200 in msort_with_tmp.part () from /lib32/libc.so.6
#5  0xf7cce200 in msort_with_tmp.part () from /lib32/libc.so.6
#6  0xf7cce200 in msort_with_tmp.part () from /lib32/libc.so.6
#7  0xf7cce787 in qsort_r () from /lib32/libc.so.6
#8  0xf7cce85a in qsort () from /lib32/libc.so.6
#9  0x0804ca6b in show_symbols (ebl=0x8055690, ehdr=0xffffcc3c, scn=0x8055580, xndxscn=0x0, shdr=0xffffcc7c, 
    prefix=0x0, fname=0xffffd056 "id:000010,src:000000,op:flip1,pos:5556", 
    fullname=0xffffcb70 "id:000010,src:000000,op:flip1,pos:5556") at nm.c:1360
#10 0x0804d19a in handle_elf (elf=0x8054898, prefix=0x0, fname=0xffffd056 "id:000010,src:000000,op:flip1,pos:5556", 
    suffix=0x0) at nm.c:1485
#11 0x08049f06 in process_file (fname=0xffffd056 "id:000010,src:000000,op:flip1,pos:5556", more_than_one=false)
    at nm.c:391
#12 0x08049b31 in main (argc=2, argv=0xffffcea4) at nm.c:252


Backtrace 2, id:000113,src:000000,op:flip32,pos:5474:
Program received signal SIGSEGV, Segmentation fault.
0xf7dce3ab in __strcmp_ssse3 () from /lib32/libc.so.6
(gdb) bt
#0  0xf7dce3ab in __strcmp_ssse3 () from /lib32/libc.so.6
#1  0xf7f6686d in ?? () from /usr/lib32/libdw.so.1
#2  0xf7f66d80 in dwarf_begin_elf () from /usr/lib32/libdw.so.1
#3  0x0804c14c in show_symbols (ebl=0x8055690, ehdr=0xffffcc3c, scn=0x8055580, xndxscn=0x0, shdr=0xffffcc7c, 
    prefix=0x0, fname=0xffffd055 "id:000113,src:000000,op:flip32,pos:5474", 
    fullname=0xffffcb70 "id:000113,src:000000,op:flip32,pos:5474") at nm.c:1194
#4  0x0804d19a in handle_elf (elf=0x8054898, prefix=0x0, fname=0xffffd055 "id:000113,src:000000,op:flip32,pos:5474", 
    suffix=0x0) at nm.c:1485
#5  0x08049f06 in process_file (fname=0xffffd055 "id:000113,src:000000,op:flip32,pos:5474", more_than_one=false)
    at nm.c:391
#6  0x08049b31 in main (argc=2, argv=0xffffcea4) at nm.c:252

Backtrace 3, id:000116,src:000000,op:flip32,pos:5554
Program received signal SIGSEGV, Segmentation fault.
0xf7d20a72 in __strlen_sse2_bsf () from /lib32/libc.so.6
(gdb) bt
#0  0xf7d20a72 in __strlen_sse2_bsf () from /lib32/libc.so.6
#1  0x0804c4d8 in show_symbols (ebl=0x8055690, ehdr=0xffffcc3c, scn=0x8055580, xndxscn=0x0, shdr=0xffffcc7c, 
    prefix=0x0, fname=0xffffd055 "id:000116,src:000000,op:flip32,pos:5554", 
    fullname=0xffffcb70 "id:000116,src:000000,op:flip32,pos:5554") at nm.c:1264
#2  0x0804d19a in handle_elf (elf=0x8054898, prefix=0x0, fname=0xffffd055 "id:000116,src:000000,op:flip32,pos:5554", 
    suffix=0x0) at nm.c:1485
#3  0x08049f06 in process_file (fname=0xffffd055 "id:000116,src:000000,op:flip32,pos:5554", more_than_one=false)
    at nm.c:391
#4  0x08049b31 in main (argc=2, argv=0xffffcea4) at nm.c:252


I compiled elfutils git head with
./configure --enable-maintainer-mode CFLAGS="-m32 -ggdb" ; make

-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-09 16:57 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-09 16:57 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 599 bytes --]

On Sat, 2014-11-08 at 17:10 +0100, Hanno Böck wrote:
> Am Sat, 8 Nov 2014 15:04:16 +0100
> schrieb Mark Wielaard <mjw@redhat.com>:
> 
> > I have pushed all three fuzz-robustify patches to master.
> 
> Yeah, seems robustness improved a lot. I couldn't trivially find
> another crasher in readelf on git head

Good. And thanks for trying.

> , however here are three more in
> nm. Seems they only crash on 32 bit.

I cannot get these to crash on either a fedora 20 x86_64 setup, nor on a
fedora 21-beta i686 setup. Could you run under gdb and provide a
backtrace?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-08 16:10 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-08 16:10 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 408 bytes --]

Am Sat, 8 Nov 2014 15:04:16 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> I have pushed all three fuzz-robustify patches to master.

Yeah, seems robustness improved a lot. I couldn't trivially find
another crasher in readelf on git head, however here are three more in
nm. Seems they only crash on 32 bit.

cu,
-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: elfutils-nm-crasher.tar.xz --]
[-- Type: application/x-xz, Size: 2024 bytes --]

[-- Attachment #3: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-08 15:32 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-08 15:32 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 501 bytes --]

On Fri, Nov 07, 2014 at 05:13:36PM +0100, Hanno Böck wrote:
> valgrind says on id:000053,src:000000,op:flip1,pos:879:
> ELF Header:
> vex x86->IR: unhandled instruction bytes: 0xC5 0xF8 0x77 0xE8
> ==6217== valgrind: Unrecognised instruction at address 0x410f7a7.

You might have to upgrade your valgrind. That is VZEROUPPER an AVX
instruction that should be supported since valgrind 3.8.0 on x86_64.
Ah, you are running 32bit? Then valgrind does indeed not support it.

Cheers,

Mark


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-08 14:04 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-08 14:04 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 992 bytes --]

On Fri, Nov 07, 2014 at 04:32:49PM +0100, Hanno Böck wrote:
> Also see attachmend, output from american fuzzy lop with latest git
> code and your two patches. 9 crashes, 10 hangs.

Thanks. One of those pointed out that my overflow check for hash section
sizes was bogus. Fixed version attached. The others seem to be because
handle_versym didn't initialize its vernames and filenames. Then when
an ELF file didn't set them we did check they were not set (NULL), but
that check failed, because the elements still contained random data.
The second second patch fixes that.

I have pushed all three fuzz-robustify patches to master.

Note that the testcases you say are hanging are just really, realy slow.
Because of very large input values they try to process a lot of elements,
but eventually they will finish. We still might to sanity check some of
those excessively large input values, but they don't lead to hangs or
crashes. Just very long runtimes.

Cheers,

Mark

[-- Attachment #2: 0001-readelf-Sanity-check-hash-section-contents-before-pr.patch --]
[-- Type: text/plain, Size: 4229 bytes --]

>From 6b246e0620bdbaf8240f3bf391ec773eea3f7f48 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Fri, 7 Nov 2014 12:54:02 +0100
Subject: [PATCH 1/2] readelf: Sanity check hash section contents before
 processing.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reported by: Hanno Böck <hanno@hboeck.de>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 src/ChangeLog |  6 ++++++
 src/readelf.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index a252cdc..3ff3e31 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2014-11-07  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_sysv_hash): Sanity check section contents.
+	(handle_sysv_hash64): Likewise.
+	(handle_gnu_hash): Likewise.
+
 2014-09-14  Petr Machata  <pmachata@redhat.com>
 
 	* readelf.c (handle_relocs_rela): Typo fix, test DESTSHDR properly.
diff --git a/src/readelf.c b/src/readelf.c
index 4d3bb36..e03a771 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -2954,8 +2954,21 @@ handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
       return;
     }
 
+  if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
+    {
+    invalid_data:
+      error (0, 0, gettext ("invalid data in sysv.hash section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
+
+  uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
+  if (used_buf > data->d_size)
+    goto invalid_data;
+
   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
 
@@ -2996,8 +3009,21 @@ handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
       return;
     }
 
+  if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
+    {
+    invalid_data:
+      error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
+
+  uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf64_Xword);
+  if (used_buf > data->d_size)
+    goto invalid_data;
+
   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
 
@@ -3037,18 +3063,37 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
       return;
     }
 
+  if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
+    {
+    invalid_data:
+      error (0, 0, gettext ("invalid data in gnu.hash section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
 
   /* Next comes the size of the bitmap.  It's measured in words for
      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
-     64 bit archs.  */
+     64 bit archs.  There is always a bloom filter present, so zero is
+     an invalid value.  */
   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
   if (gelf_getclass (ebl->elf) == ELFCLASS64)
     bitmask_words *= 2;
 
+  if (bitmask_words == 0)
+    goto invalid_data;
+
   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
 
+  /* Is there still room for the sym chain?
+     Use uint64_t calculation to prevent 32bit overlow.  */
+  uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
+  uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
+  if (used_buf > data->d_size)
+    goto invalid_data;
+
   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
 
   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
@@ -3068,6 +3113,8 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
 	    ++nsyms;
 	    if (maxlength < ++lengths[cnt])
 	      ++maxlength;
+	    if (inner > max_nsyms)
+	      goto invalid_data;
 	  }
 	while ((chain[inner++] & 1) == 0);
       }
-- 
1.9.3


[-- Attachment #3: 0002-readelf.c-handle_versym-Initialize-vername-and-filen.patch --]
[-- Type: text/plain, Size: 1614 bytes --]

>From d8b9682b1a5ff2746f172487eaf19ebd088bb7f4 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Sat, 8 Nov 2014 14:04:27 +0100
Subject: [PATCH 2/2] readelf.c (handle_versym): Initialize vername and
 filename array elements.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We check whether the elements are set before printing their contents,
but didn't make sure they were initialized.

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

diff --git a/src/ChangeLog b/src/ChangeLog
index 3ff3e31..6d3e951 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-08  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_versym): Initialize vername and filename array
+	elements.
+
 2014-11-07  Mark Wielaard  <mjw@redhat.com>
 
 	* readelf.c (handle_sysv_hash): Sanity check section contents.
diff --git a/src/readelf.c b/src/readelf.c
index e03a771..01c644f 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -2716,7 +2716,9 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
 
       /* Allocate the array.  */
       vername = (const char **) alloca (nvername * sizeof (const char *));
+      memset(vername, 0, nvername * sizeof (const char *));
       filename = (const char **) alloca (nvername * sizeof (const char *));
+      memset(filename, 0, nvername * sizeof (const char *));
 
       /* Run through the data structures again and collect the strings.  */
       if (defscn != NULL)
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-07 16:13 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-07 16:13 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 2319 bytes --]

Am Fri, 07 Nov 2014 16:45:07 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> > Fixes some of them but not all.
> > Still crashers:
> > id:000053,src:000000,op:flip1,pos:879
> > id:000054,src:000000,op:flip1,pos:885
> 
> Those seem fine for me. How do they crash for you? Could you run under
> gdb and provide a backtrace?

Hmm, interesting, seems these only crash if compiled with american
fuzzy lop instructions...
Maybe this is a bug in afl or maybe it is triggered by the
circumstances.

valgrind says on id:000053,src:000000,op:flip1,pos:879:
ELF Header:
vex x86->IR: unhandled instruction bytes: 0xC5 0xF8 0x77 0xE8
==6217== valgrind: Unrecognised instruction at address 0x410f7a7.
==6217==    at 0x410F7A7: vfprintf (in /lib32/libc-2.19.so)
==6217==    by 0x41C766F: __printf_chk (in /lib32/libc-2.19.so)
==6217==    by 0x805F27D: printf (stdio2.h:104)
==6217==    by 0x805F27D: print_ehdr (readelf.c:944)
==6217==    by 0x806E004: process_elf_file (readelf.c:869)
==6217==    by 0x806E004: process_dwflmod (readelf.c:691)
==6217==    by 0x4082BE3: dwfl_getmodules (in /usr/lib32/libdw-0.158.so)
==6217==    by 0x80580D2: process_file (readelf.c:790)
==6217==    by 0x804AD57: main (readelf.c:296)

gdb backtrace:
Program received signal SIGSEGV, Segmentation fault.
0xf7de4e37 in vfprintf () from /lib32/libc.so.6
(gdb) bt
#0  0xf7de4e37 in vfprintf () from /lib32/libc.so.6
#1  0xf7e99670 in __printf_chk () from /lib32/libc.so.6
#2  0x08064818 in printf (__fmt=0x809e055 "(%s)")
at /usr/include/bits/stdio2.h:104 #3  handle_versym (scn=0x80aef04,
shdr=0xffffcae8, ebl=<optimized out>) at readelf.c:2860 #4  0x08070531
in print_verinfo (ebl=<optimized out>) at readelf.c:2402 #5
process_elf_file (fd=<optimized out>, dwflmod=<optimized out>) at
readelf.c:885 #6  process_dwflmod (dwflmod=0x80ae8a8,
userdata=0x80ae8b0, name=0x80ae9b8
"id:000053,src:000000,op:flip1,pos:879", base=4194304, arg=0xffffca00)
at readelf.c:691 #7  0xf7f7ebe4 in dwfl_getmodules ()
from /usr/lib32/libdw.so.1 #8  0x080580d3 in process_file
(fd=fd(a)entry=3, fname=<optimized out>, only_one=only_one(a)entry=true) at
readelf.c:790 #9  0x0804ad58 in main (argc=3, argv=0xffffce84) at
readelf.c:296


-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-07 15:45 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-07 15:45 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 704 bytes --]

On Fri, 2014-11-07 at 16:32 +0100, Hanno Böck wrote:
> Am Fri, 07 Nov 2014 12:58:07 +0100
> schrieb Mark Wielaard <mjw@redhat.com>:
> > > > Thanks. If you have any other examples please do report them.
> > > 
> > > Ten to crash readelf -a attached, according to american-fuzzy-lop
> > > all distinct code paths.
> > 
> > Thanks. eu-readelf didn't sanitize the hash section data before use.
> > The attached patch should fix that.
> 
> Fixes some of them but not all.
> Still crashers:
> id:000053,src:000000,op:flip1,pos:879
> id:000054,src:000000,op:flip1,pos:885

Those seem fine for me. How do they crash for you? Could you run under
gdb and provide a backtrace?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-07 15:32 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-07 15:32 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1148 bytes --]

Am Fri, 07 Nov 2014 12:58:07 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> On Fri, 2014-11-07 at 01:27 +0100, Hanno Böck wrote:
> > Am Thu, 06 Nov 2014 16:11:43 +0100
> > schrieb Mark Wielaard <mjw@redhat.com>:
> > 
> > > > (actually this bug report is kind of a fallout of a bug search
> > > > in libbfd - various parser bugs in the binutils-tools have been
> > > > found and fixed in the past days and I thought I'd run other
> > > > elf-related tools on the collection of bug-exposing binaries)
> > > 
> > > Thanks. If you have any other examples please do report them.
> > 
> > Ten to crash readelf -a attached, according to american-fuzzy-lop
> > all distinct code paths.
> 
> Thanks. eu-readelf didn't sanitize the hash section data before use.
> The attached patch should fix that.

Fixes some of them but not all.
Still crashers:
id:000053,src:000000,op:flip1,pos:879
id:000054,src:000000,op:flip1,pos:885

Also see attachmend, output from american fuzzy lop with latest git
code and your two patches. 9 crashes, 10 hangs.

-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: eu-readelf-crasher-hangs-2.tar.xz --]
[-- Type: application/x-xz, Size: 2440 bytes --]

[-- Attachment #3: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-07 11:58 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-07 11:58 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 720 bytes --]

On Fri, 2014-11-07 at 01:27 +0100, Hanno Böck wrote:
> Am Thu, 06 Nov 2014 16:11:43 +0100
> schrieb Mark Wielaard <mjw@redhat.com>:
> 
> > > (actually this bug report is kind of a fallout of a bug search in
> > > libbfd - various parser bugs in the binutils-tools have been found
> > > and fixed in the past days and I thought I'd run other elf-related
> > > tools on the collection of bug-exposing binaries)
> > 
> > Thanks. If you have any other examples please do report them.
> 
> Ten to crash readelf -a attached, according to american-fuzzy-lop all
> distinct code paths.

Thanks. eu-readelf didn't sanitize the hash section data before use.
The attached patch should fix that.

Cheers,

Mark

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-readelf-Sanity-check-hash-section-contents-before-pr.patch --]
[-- Type: text/x-patch, Size: 4441 bytes --]

From 5f6cd01d4ca5d5b0fab6dd35d22fbf900f50364f Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Fri, 7 Nov 2014 12:54:02 +0100
Subject: [PATCH] readelf: Sanity check hash section contents before
 processing.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reported by: Hanno Böck <hanno@hboeck.de>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 src/ChangeLog |  6 ++++++
 src/readelf.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index a252cdc..3ff3e31 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2014-11-07  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_sysv_hash): Sanity check section contents.
+	(handle_sysv_hash64): Likewise.
+	(handle_gnu_hash): Likewise.
+
 2014-09-14  Petr Machata  <pmachata@redhat.com>
 
 	* readelf.c (handle_relocs_rela): Typo fix, test DESTSHDR properly.
diff --git a/src/readelf.c b/src/readelf.c
index 4d3bb36..fba6c03 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -2954,8 +2954,21 @@ handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
       return;
     }
 
+  if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
+    {
+    invalid_data:
+      error (0, 0, gettext ("invalid data in sysv.hash section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
+
+  uint32_t used_buf = (2 + nchain + nbucket) * sizeof (Elf32_Word);
+  if (used_buf > data->d_size || used_buf + data->d_size < data->d_size)
+    goto invalid_data;
+
   Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
   Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
 
@@ -2996,8 +3009,21 @@ handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
       return;
     }
 
+  if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
+    {
+    invalid_data:
+      error (0, 0, gettext ("invalid data in sysv.hash64 section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
   Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
   Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
+
+  uint32_t used_buf = (2 + nchain + nbucket) * sizeof (Elf64_Xword);
+  if (used_buf > data->d_size || used_buf + data->d_size < data->d_size)
+    goto invalid_data;
+
   Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
   Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
 
@@ -3037,18 +3063,36 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
       return;
     }
 
+  if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
+    {
+    invalid_data:
+      error (0, 0, gettext ("invalid data in gnu.hash section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
   Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
   Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
 
   /* Next comes the size of the bitmap.  It's measured in words for
      the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
-     64 bit archs.  */
+     64 bit archs.  There is always a bloom filter present, so zero is
+     an invalid value.  */
   Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
   if (gelf_getclass (ebl->elf) == ELFCLASS64)
     bitmask_words *= 2;
 
+  if (bitmask_words == 0)
+    goto invalid_data;
+
   Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
 
+  /* Is there still room for the sym chain?  Check for unsigned overlow.  */
+  uint32_t used_buf = (4 + bitmask_words + nbucket) * sizeof (Elf32_Word);
+  uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
+  if (used_buf > data->d_size || used_buf + data->d_size < data->d_size)
+    goto invalid_data;
+
   uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
 
   Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
@@ -3068,6 +3112,8 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
 	    ++nsyms;
 	    if (maxlength < ++lengths[cnt])
 	      ++maxlength;
+	    if (inner > max_nsyms)
+	      goto invalid_data;
 	  }
 	while ((chain[inner++] & 1) == 0);
       }
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-07 11:51 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-07 11:51 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 355 bytes --]

On Thu, 2014-11-06 at 10:25 -0800, Roland McGrath wrote:
> >           /* First see whether the information in the section header is
> >              valid and it does not ask for too much.  */
> >           if (unlikely (offset + size > elf->maximum_size))
> 
> This is not overflow-proof.

Missed that one. So the full fix would be as attached.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-libelf-Correct-shdr-size-check-for-raw-getdata.patch --]
[-- Type: text/x-patch, Size: 3146 bytes --]

From 996a4373aeab8ffe397cb7e66cfdf56144c4b817 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Fri, 7 Nov 2014 12:47:16 +0100
Subject: [PATCH] libelf: Correct shdr size check for (raw) getdata.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reported-by: Hanno Böck <hanno@hboeck.de>
Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libelf/ChangeLog     | 6 ++++++
 libelf/elf_begin.c   | 8 ++++----
 libelf/elf_getdata.c | 7 +++++--
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 5ad20a6..dd0a755 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,9 @@
+2014-11-07  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (file_read_elf): Correct sh_size check.
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Check for unsigned
+	overflow.
+
 2014-09-10  Petr Machata  <pmachata@redhat.com>
 
 	* elf_begin (read_unmmaped_file): Call __libelf_seterrno if the
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index c3ad140..5525a3b 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -337,8 +337,8 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
 	      elf->state.elf32.scns.data[cnt].shdr.e32 =
 		&elf->state.elf32.shdr[cnt];
 	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
-		  && likely (maxsize - elf->state.elf32.shdr[cnt].sh_offset
-			     <= elf->state.elf32.shdr[cnt].sh_size))
+		  && likely (elf->state.elf32.shdr[cnt].sh_size
+			     <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
 		elf->state.elf32.scns.data[cnt].rawdata_base =
 		  elf->state.elf32.scns.data[cnt].data_base =
 		  ((char *) map_address + offset
@@ -428,8 +428,8 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
 	      elf->state.elf64.scns.data[cnt].shdr.e64 =
 		&elf->state.elf64.shdr[cnt];
 	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
-		  && likely (maxsize - elf->state.elf64.shdr[cnt].sh_offset
-			     <= elf->state.elf64.shdr[cnt].sh_size))
+		  && likely (elf->state.elf64.shdr[cnt].sh_size
+			     <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
 		elf->state.elf64.scns.data[cnt].rawdata_base =
 		  elf->state.elf64.scns.data[cnt].data_base =
 		  ((char *) map_address + offset
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index bc9f26a..33d35d6 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -243,8 +243,11 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn)
       if (elf->map_address != NULL)
 	{
 	  /* First see whether the information in the section header is
-	     valid and it does not ask for too much.  */
-	  if (unlikely (offset + size > elf->maximum_size))
+	     valid and it does not ask for too much.  Check for unsigned
+	     overflow.  */
+	  if (unlikely (offset + size > elf->maximum_size
+			|| (offset + size + elf->maximum_size
+			    < elf->maximum_size)))
 	    {
 	      /* Something is wrong.  */
 	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-07  0:27 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-11-07  0:27 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 599 bytes --]

Am Thu, 06 Nov 2014 16:11:43 +0100
schrieb Mark Wielaard <mjw@redhat.com>:

> > (actually this bug report is kind of a fallout of a bug search in
> > libbfd - various parser bugs in the binutils-tools have been found
> > and fixed in the past days and I thought I'd run other elf-related
> > tools on the collection of bug-exposing binaries)
> 
> Thanks. If you have any other examples please do report them.

Ten to crash readelf -a attached, according to american-fuzzy-lop all
distinct code paths.

-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: eu-readelf-crasher.tar.xz --]
[-- Type: application/x-xz, Size: 2176 bytes --]

[-- Attachment #3: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-06 18:25 Roland McGrath
  0 siblings, 0 replies; 28+ messages in thread
From: Roland McGrath @ 2014-11-06 18:25 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 231 bytes --]

>           /* First see whether the information in the section header is
>              valid and it does not ask for too much.  */
>           if (unlikely (offset + size > elf->maximum_size))

This is not overflow-proof.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-06 16:05 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-06 16:05 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 3050 bytes --]

On Thu, 2014-11-06 at 16:11 +0100, Mark Wielaard wrote:
> I haven't figured out yet why we do use the data in the mmap case. It
> looks like we should catch that issue in elf_getdata:
> 
>       /* We can use the mapped or loaded data if available.  */
>       if (elf->map_address != NULL)
>         {
>           /* First see whether the information in the section header is
>              valid and it does not ask for too much.  */
>           if (unlikely (offset + size > elf->maximum_size))
>             {
>               /* Something is wrong.  */
>               __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
>               return 1;
>             }
> 
> elf->maximum_size is setup correctly based on the actual file size. But
> it seems we don't actually hit this code path in this case. The rawdata
> is setup some other way than by calling __libelf_set_rawdata_wrlock. But
> I haven't figured out how yet.

I believe it comes from a reversed check in elf_begin when it sets up
the base addresses in case the file was mmaped.

diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index c3ad140..5525a3b 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -337,8 +337,8 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
              elf->state.elf32.scns.data[cnt].shdr.e32 =
                &elf->state.elf32.shdr[cnt];
              if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
-                 && likely (maxsize - elf->state.elf32.shdr[cnt].sh_offset
-                            <= elf->state.elf32.shdr[cnt].sh_size))
+                 && likely (elf->state.elf32.shdr[cnt].sh_size
+                            <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
                elf->state.elf32.scns.data[cnt].rawdata_base =
                  elf->state.elf32.scns.data[cnt].data_base =
                  ((char *) map_address + offset
@@ -428,8 +428,8 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
              elf->state.elf64.scns.data[cnt].shdr.e64 =
                &elf->state.elf64.shdr[cnt];
              if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
-                 && likely (maxsize - elf->state.elf64.shdr[cnt].sh_offset
-                            <= elf->state.elf64.shdr[cnt].sh_size))
+                 && likely (elf->state.elf64.shdr[cnt].sh_size
+                            <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
                elf->state.elf64.scns.data[cnt].rawdata_base =
                  elf->state.elf64.scns.data[cnt].data_base =
                  ((char *) map_address + offset

With that the invalid sized sections aren't precached anymore and so
rawdata will remain NULL. __libelf_set_rawdata_wrlock will be called and
readelf will just report "cannot get data for section [28] '.strtab':
invalid section header" instead of trying to use the data.

Does the above look sane? All tests PASS with the above change.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-11-06 15:11 Mark Wielaard
  0 siblings, 0 replies; 28+ messages in thread
From: Mark Wielaard @ 2014-11-06 15:11 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 2008 bytes --]

On Fri, 2014-10-31 at 17:13 +0100, Hanno Böck wrote:
> Attached is a file that's a fuzzed elf executable which will crash
> various tools shipped with elfutils, I tried it with nm and readelf -a,
> maybe others affected.

The issue is when we call elf_strptr on the .strtab section giving the
st_name offset for the 29th symbol which is way too large. But the
section header for .strtab is corrupted and gives a way too large size.
So the sanity check for whether the index falls in the section data size
doesn't trigger. So elf_strptr returns a pointer to an address we
haven't mapped in.

The issue disappears when we open the elf file with ELF_C_READ instead
of with ELF_C_READ_MMAP. Then we do detect the  size in the section
header is bogus and so we won't try to use the section data.

I haven't figured out yet why we do use the data in the mmap case. It
looks like we should catch that issue in elf_getdata:

      /* We can use the mapped or loaded data if available.  */
      if (elf->map_address != NULL)
        {
          /* First see whether the information in the section header is
             valid and it does not ask for too much.  */
          if (unlikely (offset + size > elf->maximum_size))
            {
              /* Something is wrong.  */
              __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
              return 1;
            }

elf->maximum_size is setup correctly based on the actual file size. But
it seems we don't actually hit this code path in this case. The rawdata
is setup some other way than by calling __libelf_set_rawdata_wrlock. But
I haven't figured out how yet.

> (actually this bug report is kind of a fallout of a bug search in
> libbfd - various parser bugs in the binutils-tools have been found and
> fixed in the past days and I thought I'd run other elf-related tools on
> the collection of bug-exposing binaries)

Thanks. If you have any other examples please do report them.

Cheers,

Mark


^ permalink raw reply	[flat|nested] 28+ messages in thread

* out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file
@ 2014-10-31 16:13 
  0 siblings, 0 replies; 28+ messages in thread
From:  @ 2014-10-31 16:13 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 3082 bytes --]

Hi,

Attached is a file that's a fuzzed elf executable which will crash
various tools shipped with elfutils, I tried it with nm and readelf -a,
maybe others affected.

What puzzles me a bit is that valgrin suggests nm and readelf crash at
different code paths. Both times its a one byte out of bounds read.

(actually this bug report is kind of a fallout of a bug search in
libbfd - various parser bugs in the binutils-tools have been found and
fixed in the past days and I thought I'd run other elf-related tools on
the collection of bug-exposing binaries)

I tested it both with 0.160 and latest git code.


Here's the valgrind output for nm:

==20828== Invalid read of size 1
==20828==    at 0x4C2C4D2: strlen
(in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==20828==
by 0x40346D: show_symbols (nm.c:1264) ==20828==    by 0x4047AC:
handle_elf (nm.c:1485) ==20828==    by 0x404E32: process_file (nm.c:391)
==20828==    by 0x40247E: main (nm.c:252)
==20828==  Address 0x4043dac is not stack'd, malloc'd or (recently)
free'd ==20828== 
==20828== 
==20828== Process terminating with default action of signal 11 (SIGSEGV)
==20828==  Access not within mapped region at address 0x4043DAC
==20828==    at 0x4C2C4D2: strlen
(in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==20828==
by 0x40346D: show_symbols (nm.c:1264) ==20828==    by 0x4047AC:
handle_elf (nm.c:1485) ==20828==    by 0x404E32: process_file (nm.c:391)
==20828==    by 0x40247E: main (nm.c:252)

Here for readelf -a:

==20829== Invalid read of size 1
==20829==    at 0x54DA9A7: vfprintf (in /lib64/libc-2.19.so)
==20829==    by 0x558737F: __printf_chk (in /lib64/libc-2.19.so)
==20829==    by 0x4057E6: printf (stdio2.h:104)
==20829==    by 0x4057E6: handle_symtab (readelf.c:2245)
==20829==    by 0x4057E6: print_symtab (readelf.c:2139)
==20829==    by 0x40F26E: process_elf_file (readelf.c:887)
==20829==    by 0x411735: process_dwflmod (readelf.c:691)
==20829==    by 0x4E52620: dwfl_getmodules
(in /usr/lib64/libdw-0.160.so) ==20829==    by 0x408024: process_file
(readelf.c:790) ==20829==    by 0x403D93: main (readelf.c:296)
==20829==  Address 0x4043dac is not stack'd, malloc'd or (recently)
free'd ==20829== 
==20829== 
==20829== Process terminating with default action of signal 11 (SIGSEGV)
==20829==  Access not within mapped region at address 0x4043DAC
==20829==    at 0x54DA9A7: vfprintf (in /lib64/libc-2.19.so)
==20829==    by 0x558737F: __printf_chk (in /lib64/libc-2.19.so)
==20829==    by 0x4057E6: printf (stdio2.h:104)
==20829==    by 0x4057E6: handle_symtab (readelf.c:2245)
==20829==    by 0x4057E6: print_symtab (readelf.c:2139)
==20829==    by 0x40F26E: process_elf_file (readelf.c:887)
==20829==    by 0x411735: process_dwflmod (readelf.c:691)
==20829==    by 0x4E52620: dwfl_getmodules
(in /usr/lib64/libdw-0.160.so) ==20829==    by 0x408024: process_file
(readelf.c:790) ==20829==    by 0x403D93: main (readelf.c:296)

cu,
-- 
Hanno Böck
http://hboeck.de/

mail/jabber: hanno@hboeck.de
GPG: BBB51E42

[-- Attachment #2: 1977-elf-64bit.obj --]
[-- Type: application/octet-stream, Size: 7945 bytes --]

[-- Attachment #3: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2014-11-13 21:55 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-11 13:49 out-of-bounds read / crash in elfutils tools (readelf, nm, ...) with malformed file Petr Machata
  -- strict thread matches above, loose matches on Subject: below --
2014-11-13 21:55 
2014-11-13 21:51 Mark Wielaard
2014-11-13 19:39 
2014-11-13 14:45 Mark Wielaard
2014-11-11 16:57 Mark Wielaard
2014-11-11 13:57 
2014-11-11 13:53 Mark Wielaard
2014-11-11 13:40 
2014-11-11 13:30 Petr Machata
2014-11-11 13:15 Mark Wielaard
2014-11-11 10:31 
2014-11-10 20:58 Mark Wielaard
2014-11-09 21:59 
2014-11-09 16:57 Mark Wielaard
2014-11-08 16:10 
2014-11-08 15:32 Mark Wielaard
2014-11-08 14:04 Mark Wielaard
2014-11-07 16:13 
2014-11-07 15:45 Mark Wielaard
2014-11-07 15:32 
2014-11-07 11:58 Mark Wielaard
2014-11-07 11:51 Mark Wielaard
2014-11-07  0:27 
2014-11-06 18:25 Roland McGrath
2014-11-06 16:05 Mark Wielaard
2014-11-06 15:11 Mark Wielaard
2014-10-31 16:13 

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).