Bug 15157 - readelf crash (relocation handling)
Summary: readelf crash (relocation handling)
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.23
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-19 11:00 UTC by Paul Marinescu
Modified: 2016-02-11 09:14 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
bug trigger. readelf -wR buggy1.o (429 bytes, application/octet-stream)
2013-02-19 11:00 UTC, Paul Marinescu
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Marinescu 2013-02-19 11:00:37 UTC
Created attachment 6878 [details]
bug trigger. readelf -wR buggy1.o

I came across a bug which in readelf which seems to be present in 2.23.52.20130219 as well. I attached the input file to reproduce. The output on my machine (64bit Fedora 16) is

$ binutils/readelf -wR buggy1.o 
Contents of the .debug_ranges section:

    Offset   Begin    End
    00000000 00000000 00000002 
    00000000 <End of list>
    00000010 00000000 00000002 
    00000010 <End of list>

*** glibc detected *** binutils/readelf: double free or corruption (out): 0x000000000179e630 ***
======= Backtrace: =========
/lib64/libc.so.6[0x376887da76]
/lib64/libc.so.6[0x376887ed5e]
binutils/readelf[0x41ce33]
binutils/readelf[0x41d452]
binutils/readelf[0x41eb12]
binutils/readelf[0x420e9c]
/lib64/libc.so.6(__libc_start_main+0xed)[0x376882169d]
binutils/readelf[0x401799]
======= Memory map: ========
00400000-0045f000 r-xp 00000000 fd:00 2771716                            /home/pdm110/binutils-latest/binutils/readelf
0045f000-00462000 rw-p 0005e000 fd:00 2771716                            /home/pdm110/binutils-latest/binutils/readelf
00462000-00464000 rw-p 00000000 00:00 0 
0179c000-017bd000 rw-p 00000000 00:00 0                                  [heap]
3768400000-3768422000 r-xp 00000000 fd:03 2883586                        /lib64/ld-2.14.90.so
3768621000-3768622000 r--p 00021000 fd:03 2883586                        /lib64/ld-2.14.90.so
3768622000-3768623000 rw-p 00022000 fd:03 2883586                        /lib64/ld-2.14.90.so
3768623000-3768624000 rw-p 00000000 00:00 0 
3768800000-37689ad000 r-xp 00000000 fd:03 2883587                        /lib64/libc-2.14.90.so
37689ad000-3768bad000 ---p 001ad000 fd:03 2883587                        /lib64/libc-2.14.90.so
3768bad000-3768bb1000 r--p 001ad000 fd:03 2883587                        /lib64/libc-2.14.90.so
3768bb1000-3768bb3000 rw-p 001b1000 fd:03 2883587                        /lib64/libc-2.14.90.so
3768bb3000-3768bb8000 rw-p 00000000 00:00 0 
3769c00000-3769c17000 r-xp 00000000 fd:03 2883596                        /lib64/libz.so.1.2.5
3769c17000-3769e16000 ---p 00017000 fd:03 2883596                        /lib64/libz.so.1.2.5
3769e16000-3769e17000 rw-p 00016000 fd:03 2883596                        /lib64/libz.so.1.2.5
376a000000-376a015000 r-xp 00000000 fd:03 2883600                        /lib64/libgcc_s-4.6.3-20120306.so.1
376a015000-376a214000 ---p 00015000 fd:03 2883600                        /lib64/libgcc_s-4.6.3-20120306.so.1
376a214000-376a215000 rw-p 00014000 fd:03 2883600                        /lib64/libgcc_s-4.6.3-20120306.so.1
7f6ab5120000-7f6ab5222000 rw-p 00000000 00:00 0 
7f6ab5222000-7f6abb645000 r--p 00000000 fd:03 1069018                    /usr/lib/locale/locale-archive
7f6abb645000-7f6abb648000 rw-p 00000000 00:00 0 
7f6abb65c000-7f6abb65d000 rw-p 00000000 00:00 0 
7fff7834e000-7fff7836f000 rw-p 00000000 00:00 0                          [stack]
7fff783ff000-7fff78400000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted


objdump on the other hand seems to be fine. binutils/objdump -WR buggy1.o says

Can't get contents for section '.debug_ranges'.
Comment 1 Paul Marinescu 2013-02-19 16:12:26 UTC
I looked a bit more into this and it seems that the problem has to do with handling of relocation offsets. More exactly, in readelf.c:10512, the code checks for a invalid (too big) relocation offset:

rloc = start + rp->r_offset;
if ((rloc + reloc_size) > end)
{
  warn (_("skipping invalid relocation offset 0x%lx in section %s\n"),
         (unsigned long) rp->r_offset,
         SECTION_NAME (section));
  continue;
}

However, the code fails to take into account a value such as rp->r_offset = (unsigned long)-5. One possible implication would be that a specially crafted binary can make readelf write to any memory location below rloc.
Comment 2 cvs-commit@gcc.gnu.org 2013-03-22 16:04:57 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	nickc@sourceware.org	2013-03-22 16:04:56

Modified files:
	binutils       : ChangeLog readelf.c 

Log message:
	PR binutils/15157
	* readelf.c (apply_relocations): Catch relocations with negative
	offsets.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/ChangeLog.diff?cvsroot=src&r1=1.2000&r2=1.2001
http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/readelf.c.diff?cvsroot=src&r1=1.598&r2=1.599
Comment 3 Nick Clifton 2013-03-22 16:06:24 UTC
Thanks to Paul's tip I have created and applied a patch to handle relocs with negative offsets.
Comment 4 cereza28 2016-02-11 09:14:18 UTC
Enviado desde mi iPhone