Bug 20794

Summary: Heap buffer overflow in readelf
Product: binutils Reporter: Joseph Bisch <joseph.bisch>
Component: binutilsAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: nickc
Priority: P2    
Version: 2.28   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: testcase that causes crash
readelf and ASan output from running testcase

Description Joseph Bisch 2016-11-08 13:01:57 UTC
Created attachment 9614 [details]
testcase that causes crash

While fuzzing with afl, I encountered a heap buffer overflow in readelf compiled with ASan. The git commit is ec7b600bf1410f6bda239666fac258a605dc3f43.

To reproduce, compile binutils with ASan and run:

/path/to/readelf -a /path/to/testcase

Here is the ASan output (which I am also attaching):

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x401130
  Start of program headers:          64 (bytes into file)
  Start of section headers:          8760 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         5
  Section header string table index: 28 <corrupt: out of range>

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0] <no-name>         NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] <no-name>         PROGBITS         0000000000400238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] <no-name>         NOTE             0000000000400254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] <no-name>         NOTE             0000000000400274  00000274
       0000000000000024  0000000000000000   A       0     0     4
=================================================================
==20759==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61400000fdd4 at pc 0x00000052b599 bp 0x7fff0a292970 sp 0x7fff0a292968
READ of size 4 at 0x61400000fdd4 thread T0
    #0 0x52b598 in process_section_headers /home/joseph/binutils/binutils-gdb/binutils/readelf.c:5982:46
    #1 0x52b598 in process_object /home/joseph/binutils/binutils-gdb/binutils/readelf.c:16684
    #2 0x502c69 in process_file /home/joseph/binutils/binutils-gdb/binutils/readelf.c:17087:13
    #3 0x502c69 in main /home/joseph/binutils/binutils-gdb/binutils/readelf.c:17158
    #4 0x7f7754f2b290 in __libc_start_main (/usr/lib/libc.so.6+0x20290)
    #5 0x419089 in _start (/home/joseph/binutils/binutils-gdb/binutils/readelf+0x419089)

0x61400000fdd4 is located 4 bytes to the right of 400-byte region [0x61400000fc40,0x61400000fdd0)
allocated by thread T0 here:
    #0 0x4c8998 in __interceptor_malloc (/home/joseph/binutils/binutils-gdb/binutils/readelf+0x4c8998)
    #1 0x5b78fa in xmalloc /home/joseph/binutils/binutils-gdb/libiberty/./xmalloc.c:148:12

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/joseph/binutils/binutils-gdb/binutils/readelf.c:5982:46 in process_section_headers
Shadow bytes around the buggy address:
  0x0c287fff9f60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c287fff9f70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c287fff9f80: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c287fff9f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c287fff9fa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c287fff9fb0: 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa
  0x0c287fff9fc0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c287fff9fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c287fff9fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c287fff9ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa fa
  0x0c287fffa000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==20759==ABORTING
Comment 1 Joseph Bisch 2016-11-08 13:03:05 UTC
Created attachment 9615 [details]
readelf and ASan output from running testcase
Comment 2 cvs-commit@gcc.gnu.org 2016-11-08 15:05:06 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cb64e50d42a49bce61050c79c5ab0846905b6a82

commit cb64e50d42a49bce61050c79c5ab0846905b6a82
Author: Nick Clifton <nickc@redhat.com>
Date:   Tue Nov 8 15:03:46 2016 +0000

    Fix heap-buffer-overflow error detected by address sanitization on a fuzzed binary.
    
    	PR binutils/20794
    	* readelf.c (process_section_headers): Fix off-by-one error when
    	checking for invalid sh_link and sh_info fields.
Comment 3 Nick Clifton 2016-11-08 15:08:57 UTC
Hi Joseph,

  Thanks for filing this bug report.  The problem was a silly off-by-one error in the code to check for invalis sh_link and sh_info fields.  I have checked in a patch to fix the problem.  Please let us know (via a new bugzilla report) if you find any more bugs like this.

Cheers
  Nick