Bug 22385

Summary: Integer overflow in coff_get_normalized_symtab
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-02 06:00:49 UTC
Created attachment 10568 [details]
poc of the crash

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

An integer overflow is occurred when numbers of symbols are too large.


ASAN output:

./objdump -r $POC

==30813==ERROR: AddressSanitizer: SEGV on unknown address 0xbebebebe (pc 0x08127bc6 bp 0xbfe51da8 sp 0xbfe5191c T0)
    #0 0x8127bc5 in __sanitizer::internal_strlen(char const*) (/home/min/fuzzing/program/binutils-master-asan/bin/objdump+0x8127bc5)
    #1 0x80b4121 in printf_common(void*, char const*, char*) (/home/min/fuzzing/program/binutils-master-asan/bin/objdump+0x80b4121)
    #2 0x80b45fc in __interceptor_vfprintf (/home/min/fuzzing/program/binutils-master-asan/bin/objdump+0x80b45fc)
    #3 0x80b464b in __interceptor_fprintf (/home/min/fuzzing/program/binutils-master-asan/bin/objdump+0x80b464b)
    #4 0x82b1b47 in _bfd_doprnt /home/min/fuzzing/src/binutils/binutils-gdb/bfd/bfd.c:805:8
    #5 0x82b016c in error_handler_internal /home/min/fuzzing/src/binutils/binutils-gdb/bfd/bfd.c:887:3
    #6 0x82a8e5e in _bfd_error_handler /home/min/fuzzing/src/binutils/binutils-gdb/bfd/bfd.c:909:3
    #7 0x851deae in coff_slurp_symbol_table /home/min/fuzzing/src/binutils/binutils-gdb/bfd/./coffcode.h:5085:8


The GDB debugging information is as follows:

(gdb) r -r $POC

Program received signal SIGSEGV, Segmentation fault.
0xb7e43383 in _IO_vfprintf_internal (s=0xbfffc4b8, format=<optimized out>, 
    ap=0xbfffea9c "\306\350\"\b\214\342\365\267\200!\373\267@\353\377\277\242`ⷀ!\373\267\214\342\365\267\022")
    at vfprintf.c:1632
1632  vfprintf.c: No such file or directory.
(gdb) bt
#0  0xb7e43383 in _IO_vfprintf_internal (s=0xbfffc4b8, format=<optimized out>, 
    ap=0xbfffea9c "\306\350\"\b\214\342\365\267\200!\373\267@\353\377\277\242`ⷀ!\373\267\214\342\365\267\022")
    at vfprintf.c:1632
#1  0xb7e43671 in buffered_vfprintf (s=s@entry=0xb7fb1cc0 <_IO_2_1_stderr_>, format=format@entry=0xbfffeb8c "%s", 
    args=args@entry=0xbfffea98 "\001") at vfprintf.c:2320
#2  0xb7e412d1 in _IO_vfprintf_internal (s=0xb7fb1cc0 <_IO_2_1_stderr_>, format=0xbfffeb8c "%s", 
    ap=0xbfffea98 "\001") at vfprintf.c:1293
#3  0xb7e48668 in __fprintf (stream=0xb7fb1cc0 <_IO_2_1_stderr_>, format=0xbfffeb8c "%s") at fprintf.c:32
#4  0x080c08c2 in _bfd_doprnt (stream=0xb7fb1cc0 <_IO_2_1_stderr_>, 
    format=0x822e89e "%B: Unrecognized storage class %d for %s symbol `%s'", ap=0xbfffeca4 "\340\276%\b\001")
    at bfd.c:805
#5  0x080c006f in error_handler_internal (fmt=0x822e89e "%B: Unrecognized storage class %d for %s symbol `%s'", 
    ap=0xbfffec94 "\bZ%\b") at bfd.c:887
#6  0x080be625 in _bfd_error_handler (fmt=0x822e89e "%B: Unrecognized storage class %d for %s symbol `%s'")
    at bfd.c:909
#7  0x08151029 in coff_slurp_symbol_table (abfd=0x8255a08) at ./coffcode.h:5085
#8  0x08166d06 in coff_get_symtab_upper_bound (abfd=0x8255a08) at coffgen.c:419
#9  0x0804c1d7 in slurp_symtab (abfd=0x8255a08) at ./objdump.c:615
#10 0x0804b82c in dump_bfd (abfd=0x8255a08) at ./objdump.c:3523
#11 0x0804b5d2 in display_object_bfd (abfd=0x8255a08) at ./objdump.c:3611
#12 0x0804b587 in display_any_bfd (file=0x8255a08, level=0) at ./objdump.c:3700
#13 0x0804b2b1 in display_file (filename=0xbffff2b7 "/tmp/poc", target=0x0, last_file=1) at ./objdump.c:3721
#14 0x0804ae80 in main (argc=3, argv=0xbffff0a4) at ./objdump.c:4023


Proposed patch:

Check whether integer overflow occurs in coff_get_normalized_symtab ()

--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1790,6 +1790,8 @@ coff_get_normalized_symtab (bfd *abfd)
     return NULL;
 
   size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
+  if (obj_raw_syment_count (abfd) > size)
+    return NULL;
   internal = (combined_entry_type *) bfd_zalloc (abfd, size);
   if (internal == NULL && size != 0)
     return NULL;


Credits:

This vulnerability was discovered by Mingi Cho and Taekyoung Kwon of the Information Security Lab, Yonsei University. Please contact mgcho.minic@gmail.com and taekyoung@yonsei.ac.kr if you need more information about the vulnerability and the lab.
Comment 1 cvs-commit@gcc.gnu.org 2017-11-03 11:57:17 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

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

commit 6cee897971d4d7cd37d2a686bb6d2aa3e759c8ca
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Nov 3 11:55:21 2017 +0000

    Fix excessive memory allocation attempts and possible integer overfloaws when attempting to read a COFF binary with a corrupt symbol count.
    
    	PR 22385
    	* coffgen.c (_bfd_coff_get_external_symbols): Check for an
    	overlarge raw syment count.
    	(coff_get_normalized_symtab): Likewise.
Comment 2 Nick Clifton 2017-11-03 11:58:57 UTC
Hi Mingi,

  Thanks for another bug report and patch!  I have applied the patch, but
  I also decided that a second check, in _bfd_coff_get_external_symbols,
  was also a good idea, so I have added that as well.

Cheers
  Nick