Bug 22508

Summary: Heap overflow in dump_relocs_in_section
Product: binutils Reporter: Mingi Cho <mgcho.minic>
Component: binutilsAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: nickc
Priority: P2    
Version: 2.30   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: poc of the crash

Description Mingi Cho 2017-11-28 05:46:40 UTC
Created attachment 10644 [details]
poc of the crash

Triggered by "./objdump -x $POC"
Tested on Ubuntu 16.04 (x86)

Heap overflow occurred when processing malformed PE file.


The GDB debugging information is as follows:

Program received signal SIGABRT, Aborted.
0xb7fd9ce5 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fd9ce5 in __kernel_vsyscall ()
#1  0xb7e2aea9 in __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#2  0xb7e2c407 in __GI_abort () at abort.c:89
#3  0xb7e6637c in __libc_message (do_abort=2, fmt=0xb7f5edf4 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#4  0xb7e6c2f7 in malloc_printerr (action=<optimized out>, str=0xb7f5eeac "double free or corruption (out)", 
    ptr=<optimized out>, ar_ptr=0xb7fb1780 <main_arena>) at malloc.c:5006
#5  0xb7e6cc31 in _int_free (av=0xb7fb1780 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:3867
#6  0xb7e285e6 in _nl_make_l10nflist (l10nfile_list=0xb7fb2180 <_nl_loaded_domains>, 
    dirlist=0x825c7a8 "/home/min/fuzzing/program/binutils-master-patch-noasan/share/locale", dirlist_len=68, 
    mask=0, language=0xbfffeb70 "en_US", territory=0x0, codeset=0x0, normalized_codeset=0x0, modifier=0x0, 
    filename=0xbfffeb90 "LC_MESSAGES/binutils.mo", do_allocate=0) at l10nflist.c:237
#7  0xb7e260a2 in _nl_find_domain (
    dirname=dirname@entry=0x825c7a8 "/home/min/fuzzing/program/binutils-master-patch-noasan/share/locale", 
    locale=locale@entry=0xbfffeb70 "en_US", domainname=domainname@entry=0xbfffeb90 "LC_MESSAGES/binutils.mo", 
    domainbinding=0x825c788) at finddomain.c:91
#8  0xb7e25a20 in __dcigettext (domainname=0x825c7f0 "binutils", msgid1=0x81b39fc "failed to read relocs in: %s", 
    msgid2=0x0, plural=0, n=0, category=5) at dcigettext.c:722
#9  0xb7e248b6 in __GI___dcgettext (domainname=0x0, msgid=0x81b39fc "failed to read relocs in: %s", category=5)
    at dcgettext.c:47
#10 0xb7e248f0 in __gettext (msgid=0x81b39fc "failed to read relocs in: %s") at gettext.c:55
#11 0x0804e5a2 in dump_relocs_in_section (abfd=0x825ca08, section=0x825ddb8, dummy=0x0) at ./objdump.c:3443
#12 0x080cd36c in bfd_map_over_sections (abfd=0x825ca08, operation=0x804e3d0 <dump_relocs_in_section>, 
    user_storage=0x0) at section.c:1395
#13 0x0804cbae in dump_relocs (abfd=0x825ca08) at ./objdump.c:3460
#14 0x0804bb28 in dump_bfd (abfd=0x825ca08) at ./objdump.c:3586
#15 0x0804b742 in display_object_bfd (abfd=0x825ca08) at ./objdump.c:3649
---Type <return> to continue, or q <return> to quit---
#16 0x0804b6f7 in display_any_bfd (file=0x825ca08, level=0) at ./objdump.c:3738
#17 0x0804b421 in display_file (filename=0xbffff2a7 "/home/min/Downloads/heapoverflow_coff_slurp_reloc_table", 
    target=0x0, last_file=1) at ./objdump.c:3759
#18 0x0804aff0 in main (argc=3, argv=0xbffff094) at ./objdump.c:4061


ASAN output:

==7862==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4509cec at pc 0x0857747b bp 0xbfcee988 sp 0xbfcee97c
WRITE of size 4 at 0xb4509cec thread T0
    #0 0x857747a in coff_slurp_reloc_table /home/min/fuzzing/src/binutils/binutils-gdb/bfd/./coffcode.h:5336:26
    #1 0x8567bc3 in coff_canonicalize_reloc /home/min/fuzzing/src/binutils/binutils-gdb/bfd/./coffcode.h:5452:13
    #2 0x82af16d in bfd_canonicalize_reloc /home/min/fuzzing/src/binutils/binutils-gdb/bfd/bfd.c:1372:10
    #3 0x814e3c4 in dump_relocs_in_section /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3438:14
    #4 0x82da95e in bfd_map_over_sections /home/min/fuzzing/src/binutils/binutils-gdb/bfd/section.c:1395:5
    #5 0x8148f3d in dump_relocs /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3460:3
    #6 0x8145c58 in dump_bfd /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3586:5
    #7 0x81450ef in display_object_bfd /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3649:7
    #8 0x8144ffb in display_any_bfd /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3738:5
    #9 0x8144aa0 in display_file /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3759:3
    #10 0x814421e in main /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:4061:6
    #11 0xb748b636 in __libc_start_main /build/glibc-KM3i_a/glibc-2.23/csu/../csu/libc-start.c:291
    #12 0x806c7c7 in _start (/home/min/fuzzing/program/binutils-master-patch/bin/objdump+0x806c7c7)

0xb4509cec is located 4 bytes to the right of 4072-byte region [0xb4508d00,0xb4509ce8)
allocated by thread T0 here:
    #0 0x8110b04 in malloc (/home/min/fuzzing/program/binutils-master-patch/bin/objdump+0x8110b04)
    #1 0x870d3f3 in _objalloc_alloc /home/min/fuzzing/src/binutils/binutils-gdb/libiberty/./objalloc.c:143:22
    #2 0x82d3dce in bfd_alloc /home/min/fuzzing/src/binutils/binutils-gdb/bfd/opncls.c:949:9
    #3 0x8577253 in coff_slurp_reloc_table /home/min/fuzzing/src/binutils/binutils-gdb/bfd/./coffcode.h:5314:29
    #4 0x8567bc3 in coff_canonicalize_reloc /home/min/fuzzing/src/binutils/binutils-gdb/bfd/./coffcode.h:5452:13
    #5 0x82af16d in bfd_canonicalize_reloc /home/min/fuzzing/src/binutils/binutils-gdb/bfd/bfd.c:1372:10
    #6 0x814e3c4 in dump_relocs_in_section /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3438:14
    #7 0x82da95e in bfd_map_over_sections /home/min/fuzzing/src/binutils/binutils-gdb/bfd/section.c:1395:5
    #8 0x8148f3d in dump_relocs /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3460:3
    #9 0x8145c58 in dump_bfd /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3586:5
    #10 0x81450ef in display_object_bfd /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3649:7
    #11 0x8144ffb in display_any_bfd /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3738:5
    #12 0x8144aa0 in display_file /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3759:3
    #13 0x814421e in main /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:4061:6
    #14 0xb748b636 in __libc_start_main /build/glibc-KM3i_a/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/min/fuzzing/src/binutils/binutils-gdb/bfd/./coffcode.h:5336:26 in coff_slurp_reloc_table


Credits:

Mingi Cho and Taekyoung Kwon of the Information Security Lab, Yonsei University.
Comment 1 Sourceware Commits 2017-11-29 12:42: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=d785b7d4b877ed465d04072e17ca19d0f47d840f

commit d785b7d4b877ed465d04072e17ca19d0f47d840f
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Nov 29 12:40:43 2017 +0000

    Stop objdump from attempting to allocate a huge chunk of memory when parsing relocs in a corrupt file.
    
    	PR 22508
    	* objdump.c (dump_relocs_in_section): Also check the section's
    	relocation count to make sure that it is reasonable before
    	attempting to allocate space for the relocs.
Comment 2 Nick Clifton 2017-11-29 12:46:51 UTC
Hi Mingi,

  Thanks for reporting this problem.  I have checked in a patch that should stop the memory exhaustion from happening:

  https://sourceware.org/ml/binutils/2017-11/msg00551.html

Cheers
  Nick