Bug 22809

Summary: Segmentation fault in bfd_section_from_shdr
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.31   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: ELF file to trigger the bug
PE file to trigger the bug
Proposed patch

Description Mingi Cho 2018-02-07 11:09:30 UTC
Created attachment 10793 [details]
ELF file to trigger the bug

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

Segmentation fault occurred when processing malformed PE file.


The GDB debugging information is as follows:

- ELF File
Program received signal SIGSEGV, Segmentation fault.
bfd_section_from_shdr (abfd=0x8218a08, shindex=6) at elf.c:2022
warning: Source file is more recent than executable.
2022      hdr = elf_elfsections (abfd)[shindex];
(gdb) bt
#0  bfd_section_from_shdr (abfd=0x8218a08, shindex=6) at elf.c:2022
#1  0x080ab375 in bfd_elf32_object_p (abfd=0x8218a08) at elfcode.h:805
#2  0x080958b5 in bfd_check_format_matches (abfd=0x8218a08, format=bfd_object, 
    matching=0xbfffef48) at format.c:311
#3  0x0804faa8 in display_object_bfd (abfd=0x8218a08) at ./objdump.c:3663
#4  display_any_bfd (file=file@entry=0x8218a08, level=level@entry=0) at ./objdump.c:3754
#5  0x08051a54 in display_file (
    filename=0xbffff274 "/home/min/fuzzing/result/binutils/paper/2/objdump_x_W_pe_1_2/triage-latest/../../objdump_x_W_elf_1_2/triage-latest/objalloc.c:186:17/id:000511,sig:06,src:004162,op:havoc,rep:4", target=<optimized out>, last_file=1) at ./objdump.c:3775
#6  0x0804bf70 in main (argc=4, argv=0xbffff064) at ./objdump.c:4077

- PE File
Program received signal SIGSEGV, Segmentation fault.
__memcpy_ia32 () at ../sysdeps/i386/i686/multiarch/../memcpy.S:90
90  ../sysdeps/i386/i686/multiarch/../memcpy.S: No such file or directory.
(gdb) bt
#0  __memcpy_ia32 () at ../sysdeps/i386/i686/multiarch/../memcpy.S:90
#1  0xb7e6830f in __GI__IO_file_xsgetn (fp=0x821aa88, data=0x8218828, n=8388608) at fileops.c:1383
#2  0xb7e6a33e in __GI__IO_sgetn (fp=0x821aa88, data=0x8218828, n=8388608) at genops.c:467
#3  0xb7e5d8f7 in __GI__IO_fread (buf=0x8218828, size=1, count=8388608, fp=0x821aa88)
    at iofread.c:38
#4  0x080fc573 in fread (__stream=0x821aa88, __n=8388608, __size=1, __ptr=<optimized out>)
    at /usr/include/i386-linux-gnu/bits/stdio2.h:295
#5  cache_bread_1 (nbytes=<optimized out>, buf=<optimized out>, abfd=0x8218a08) at cache.c:337
#6  cache_bread (abfd=0x8218a08, buf=0x8218828, nbytes=4294967295) at cache.c:371
#7  0x08094618 in bfd_bread (ptr=0x8218828, size=4294967295, abfd=0x8218a08) at bfdio.c:196
#8  0x08097416 in _bfd_generic_get_section_contents (abfd=0x8218a08, section=0x8219c50, 
    location=0x8218828, offset=0, count=4294967295) at libbfd.c:826
#9  0x080d19db in _bfd_elf_parse_attributes (abfd=0x8218a08, hdr=0x8219478) at elf-attrs.c:444
#10 0x080afce9 in bfd_section_from_shdr (abfd=0x8218a08, shindex=3) at elf.c:2465
#11 0x080ab375 in bfd_elf32_object_p (abfd=0x8218a08) at elfcode.h:805
#12 0x080958b5 in bfd_check_format_matches (abfd=0x8218a08, format=bfd_object, 
    matching=0xbfffef78) at format.c:311
#13 0x0804faa8 in display_object_bfd (abfd=0x8218a08) at ./objdump.c:3663
#14 display_any_bfd (file=file@entry=0x8218a08, level=level@entry=0) at ./objdump.c:3754
#15 0x08051a54 in display_file (
    filename=0xbffff29d "/home/min/fuzzing/result/binutils/paper/2/objdump_x_W_pe_1_2/triage-latest/./SEGV/id:000361,sig:06,src:002944,op:fieldm,pos:652,val:+4", target=<optimized out>, 
    last_file=1) at ./objdump.c:3775
#16 0x0804bf70 in main (argc=3, argv=0xbffff094) at ./objdump.c:4077
(gdb) 


ASAN output:

==11631==ERROR: AddressSanitizer: SEGV on unknown address 0x2439a980 (pc 0x0871c7fa bp 0xbfc94668 sp 0xbfc94520 T0)
    #0 0x871c7f9 in objalloc_free /home/min/fuzzing/src/binutils/binutils-gdb/libiberty/./objalloc.c:186:17
    #1 0x8308faf in bfd_hash_table_free /home/min/fuzzing/src/binutils/binutils-gdb/bfd/hash.c:426:3
    #2 0x831298d in _bfd_delete_bfd /home/min/fuzzing/src/binutils/binutils-gdb/bfd/opncls.c:125:7
    #3 0x831298d in bfd_close_all_done /home/min/fuzzing/src/binutils/binutils-gdb/bfd/opncls.c:773
    #4 0x81431fc in display_file /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:3788:5
    #5 0x81431fc in main /home/min/fuzzing/src/binutils/binutils-gdb/binutils/./objdump.c:4077
    #6 0xb7515636 in __libc_start_main /build/glibc-mUak1Y/glibc-2.23/csu/../csu/libc-start.c:291
    #7 0x806c9a7 in _start (/home/min/fuzzing/program/binutils-asan/bin/objdump+0x806c9a7)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/min/fuzzing/src/binutils/binutils-gdb/libiberty/./objalloc.c:186:17 in objalloc_free


Credits:

Mingi Cho and Taekyoung Kwon of the Information Security Lab, Yonsei University.
Comment 1 Mingi Cho 2018-02-07 11:09:55 UTC
Created attachment 10794 [details]
PE file to trigger the bug
Comment 2 Nick Clifton 2018-02-13 16:01:37 UTC
Hi Mingi,

  I am sorry, but I am unable to reproduce these failures.  I do however
  get "memory exhausted" error messages, so I wonder if you have your
  test environment set up to generate a seg-fault when a memory allocation
  fails ?

  Please could you try the uploaded patch which I think will stop
  the invalid memory allocations from happening.  Is this sufficient
  to resolve this problem for you ?

Cheers
  Nick
Comment 3 Nick Clifton 2018-02-13 16:01:56 UTC
Created attachment 10814 [details]
Proposed patch
Comment 4 Mingi Cho 2018-05-07 15:16:06 UTC
Hi Nick,

 I have tested the bug in x86 Ubuntu system. When hdr->sh_size is 0xffffffff then malloc(hdr->sh_size +1) returns a valid pointer with small size at _bfd_elf_parse_attributes function and the bug is occurred after that.

 
 The proposed patch works on my system and fixes the problem. However, I got an error in _bfd_error_handler function during compilation time.


Best regards,
Mingi
Comment 5 Sourceware Commits 2018-05-08 11:52: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=95a6d23566165208853a68d9cd3c6eedca840ec6

commit 95a6d23566165208853a68d9cd3c6eedca840ec6
Author: Nick Clifton <nickc@redhat.com>
Date:   Tue May 8 12:51:06 2018 +0100

    Prevent a memory exhaustion failure when running objdump on a fuzzed input file with corrupt string and attribute sections.
    
    	PR 22809
    	* elf.c (bfd_elf_get_str_section): Check for an excessively large
    	string section.
    	* elf-attrs.c (_bfd_elf_parse_attributes): Issue an error if the
    	attribute section is larger than the size of the file.
Comment 6 Nick Clifton 2018-05-08 11:58:00 UTC
Patch applied (with an update to fix the compilation error).