Bug 21156

Summary: readelf segfault - invalid read of size 4
Product: binutils Reporter: Thuan Pham <thuanpv>
Component: binutilsAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: nickc
Priority: P2    
Version: 2.29   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed: 2017-02-14 00:00:00
Attachments: Crashing input
Another crashing input
Bug triggering input

Description Thuan Pham 2017-02-14 10:08:27 UTC
Created attachment 9823 [details]
Crashing input

Dear all,

This bug was found with AFLGo, a directed version of AFL/AFLFast. Thanks also to Marcel Böhme. 

This bug was found on Ubuntu 14.04 64-bit & binutils was checked out from main repository at git://sourceware.org/git/binutils-gdb.git. Its commit is 61697d017e114d7667fbb340fb73f8184d48ee5a (Tue Feb 14 00:00:30 2017) 

binutils was built with ASAN using gcc-6.2 and clang-3.4. The configure command was:

CC=clang CFLAGS="-DFORTIFY_SOURCE=2 -fstack-protector-all -fsanitize=undefined,address -fno-omit-frame-pointer -g -Wno-error" ../configure --disable-shared --disable-gdb --disable-libdecnumber --disable-readline --disable-sim

To reproduce:
Download the attached file - bug_2
readelf -w bug_2

Valgrind says:
==1379== Invalid read of size 4
==1379==    at 0x4035F3: find_section_in_set (readelf.c:679)
==1379==    by 0x422724: load_debug_section (readelf.c:13043)
==1379==    by 0x435D25: load_debug_info (dwarf.c:2720)
==1379==    by 0x437D1F: display_debug_aranges (dwarf.c:4933)
==1379==    by 0x423A0A: display_debug_section (readelf.c:13132)
==1379==    by 0x423A0A: process_section_contents (readelf.c:13207)
==1379==    by 0x423A0A: process_object (readelf.c:16899)
==1379==    by 0x402111: process_file (readelf.c:17273)
==1379==    by 0x402111: main (readelf.c:17344)
==1379==  Address 0x5205e00 is 0 bytes inside a block of size 60 free'd
==1379==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1379==    by 0x4E6B587: _nl_make_l10nflist (l10nflist.c:256)
==1379==    by 0x4E68FD9: _nl_find_domain (finddomain.c:86)
==1379==    by 0x4E6881D: __dcigettext (dcigettext.c:640)
==1379==    by 0x42872A: get_FORM_name (dwarf.c:864)
==1379==    by 0x428D78: display_debug_abbrev (dwarf.c:4385)
==1379==    by 0x423A0A: display_debug_section (readelf.c:13132)
==1379==    by 0x423A0A: process_section_contents (readelf.c:13207)
==1379==    by 0x423A0A: process_object (readelf.c:16899)
==1379==    by 0x402111: process_file (readelf.c:17273)
==1379==    by 0x402111: main (readelf.c:17344)
==1379== 
==1379== 
==1379== Process terminating with default action of signal 11 (SIGSEGV)
==1379==  Access not within mapped region at address 0x4CE5202E80
==1379==    at 0x4035F3: find_section_in_set (readelf.c:679)
==1379==    by 0x422724: load_debug_section (readelf.c:13043)
==1379==    by 0x435D25: load_debug_info (dwarf.c:2720)
==1379==    by 0x437D1F: display_debug_aranges (dwarf.c:4933)
==1379==    by 0x423A0A: display_debug_section (readelf.c:13132)
==1379==    by 0x423A0A: process_section_contents (readelf.c:13207)
==1379==    by 0x423A0A: process_object (readelf.c:16899)
==1379==    by 0x402111: process_file (readelf.c:17273)
==1379==    by 0x402111: main (readelf.c:17344)

ASAN says:
==112697==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61c000012800 at pc 0x47fd80 bp 0x7ffd87842e70 sp 0x7ffd87842e68
READ of size 4 at 0x61c000012800 thread T0
    #0 0x47fd7f in find_section_in_set /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:679
    #1 0x47edc0 in load_debug_section /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:13043
    #2 0x6ad616 in load_debug_info /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/dwarf.c:2720
    #3 0x647cb4 in display_debug_aranges /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/dwarf.c:4933
    #4 0x5667ca in display_debug_section /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:13132
    #5 0x4e1a7f in process_section_contents /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:13207
    #6 0x48d720 in process_object /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:16899
    #7 0x488475 in process_file /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:17273
    #8 0x4856d3 in main /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/../../binutils/readelf.c:17344
    #9 0x7f1697af2f44 (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #10 0x47ddfc in _start (/home/ubuntu/thesis/subjects/binutils-gdb-nick/build-asan/binutils/readelf+0x47ddfc)
Comment 1 Nick Clifton 2017-02-14 13:29:13 UTC
Hi Thuan,

  I could not reproduce this failure.  I think that it might have already been fixed by one of the previous patches, possibly for PR 21139.  Please could you check to see if the problem still happens with the latest sources ?

Cheers
  Nick
Comment 2 Thuan Pham 2017-02-14 13:50:46 UTC
Hi Nick,
I just checked out the newest version and the problem is still there
commit b32e566ba6ee02687c6def22ade0899076adf7dd
Author: Nick Clifton <nickc@redhat.com>
Date:   Tue Feb 14 13:24:09 2017 +0000

    Fix illegal memory access problems with readelf processing corrupt RL78 binaries.

        PR binutils/21155

I think it should not be 21139 since both the call stack and crashing function are different.
You cannot reproduce the bug maybe because of your testing environment. I found the bug on ubuntu 14-04 64 bit, kernel 3.19. 
Thanks,
Thuan
Comment 3 Thuan Pham 2017-02-17 15:10:51 UTC
Created attachment 9835 [details]
Another crashing input

Hi Nick,
I have attached another crashing input which still crashes the newest version of readelf on trunk. Could you please try it one more time?
To reproduce:
Download the newly attached file - bug_21156
readelf -w bug_21156
Thanks,
Thuan
Comment 4 Sourceware Commits 2017-02-17 16:01:03 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

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

commit b814a36d3440de95f2ac6eaa4fc7935c322ea456
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Feb 17 15:59:45 2017 +0000

    Fix illegal memory accesses in readelf when parsing a corrupt binary.
    
    	PR binutils/21156
    	* readelf.c (find_section_in_set): Test for invalid section
    	indicies.
Comment 5 Nick Clifton 2017-02-17 16:02:56 UTC
Hi Thuan,

  I have checked in a patch to fix this second problem.  Please can you give it
  a go and let me know if this PR can be closed.

Cheers
  Nick
Comment 6 Thuan Pham 2017-02-18 05:04:25 UTC
Created attachment 9837 [details]
Bug triggering input

Hi Nick,
Thanks for your bug fix. Your patch almost fixes the bug, except one corner case. I have attached one more file (bug_21156_2). Readelf is still vulnerable to buffer overflow in the while loop condition at line 678:  while ((i = *set++) > 0)

To reproduce:
Download the newly attached file: bug_21156_2
readelf -w bug_21156_2

ASAN says:

==140857==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61400000f9f4 at pc 0x47fa95 bp 0x7ffc15203a90 sp 0x7ffc15203a88
READ of size 4 at 0x61400000f9f4 thread T0
    #0 0x47fa94 in find_section_in_set /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:678
    #1 0x47edc0 in load_debug_section /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:13071
    #2 0x6b1f83 in process_debug_info /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/dwarf.c:2331
    #3 0x67aa3f in display_debug_info /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/dwarf.c:4907
    #4 0x566d0a in display_debug_section /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:13160
    #5 0x4e1b3f in process_section_contents /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:13235
    #6 0x48d7e0 in process_object /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:16927
    #7 0x488535 in process_file /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:17301
    #8 0x485793 in main /home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/../../binutils/readelf.c:17372
    #9 0x7f3d8e8bff44 (/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
    #10 0x47ddfc in _start (/home/ubuntu/thesis/subjects/binutils-gdb-nick/build-nick-asan/binutils/readelf+0x47ddfc)
Cheers,
Thuan
Comment 7 Sourceware Commits 2017-02-20 14:41:47 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

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

commit 43a444f9c5bfd44b4304eafd78338e21d54bea14
Author: Nick Clifton <nickc@redhat.com>
Date:   Mon Feb 20 14:40:39 2017 +0000

    Fix another memory access error in readelf when parsing a corrupt binary.
    
    	PR binutils/21156
    	* dwarf.c (cu_tu_indexes_read): Move into...
    	(load_cu_tu_indexes): ... here.  Change the variable into
    	tri-state.  Change the function into boolean, returning
    	false if the indicies could not be loaded.
    	(find_cu_tu_set): Return NULL if the indicies could not be
    	loaded.
Comment 8 Nick Clifton 2017-02-20 14:43:06 UTC
Hi Thuan,

> Thanks for your bug fix. Your patch almost fixes the bug, except one corner
> case. I have attached one more file (bug_21156_2).

Darn!  Please try the latest sources.  I have just checked in a second patch which I think should resolve this problem.

Cheers
  Nick
Comment 9 Thuan Pham 2017-02-20 19:00:28 UTC
Hi Nick,
Your newest patch has resolved the problem.
Cheers,
Thuan
Comment 10 Thuan Pham 2017-04-13 06:07:08 UTC
This is CVE-2017-6969