Bug 23994 - Heap overflow in libbfd caused by integer overflow
Summary: Heap overflow in libbfd caused by integer overflow
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.32
: P2 normal
Target Milestone: 2.32
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-16 08:56 UTC by tfx
Modified: 2019-04-15 03:51 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2018-12-16 00:00:00


Attachments
Heap overflow in libbfd caused by integer overflow. (3.39 KB, application/zip)
2018-12-16 08:56 UTC, tfx
Details

Note You need to log in before you can comment on or make changes to this bug.
Description tfx 2018-12-16 08:56:23 UTC
Created attachment 11464 [details]
Heap overflow in libbfd caused by integer overflow.

Hi there,

A Heap overflow issue was discovered in bfd caused by integer overflow, as distributed in GNU Binutils 2.31. It also exists with the latest version in Binutils 2.32 commit 76d2760bc38ada83f81087f16eb151ccc0176574. This issue may exist for a long time.

The source Code show as follow. Exec Binutils 2.31 "objdump -d poc1" as example:

In disassemble_data function in objdump.c, line 2463 is a heap allocation. But 'relsize' maybe too small caused by integer overflow . Line 8271 in _bfd_elf_canonicalize_dynamic_reloc function in elf.c will cause heap overflow.


objdump.c 
>2456  long relsize = bfd_get_dynamic_reloc_upper_bound (abfd); //relsize = 4

>2463    aux.dynrelbuf = (arelent **) xmalloc (relsize);
>2464    aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd,  
>2465						    aux.dynrelbuf,
>2466						    dynsyms);   //heap overflow

elf.c
>8210  _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
>8211  {
>8212    long ret; 
  ...

>8226    ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize) 
>8227      * sizeof(arelent *));   //integer overflow  

  
>8229    return ret; 
>8230  }

>8241  _bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
>8242				     arelent **storage, //objdump.c:2463 alloc
>8243				     asymbol **syms)
>8244  {
          ...
	
>8268     count = s->size / elf_section_data (s)->this_hdr.sh_entsize;
>8269	  p = s->relocation;
>8270	  for (i = 0; i < count; i++)
>8271	    *storage++ = p++;             //heap overflow

          ...
}


The crash output show as follow.

$ ../binutils-gdb/binutils/objdump --version
GNU objdump (GNU Binutils) 2.31.51.20181216


$ ../binutils-gdb/binutils/objdump -d poc2 
../binutils-gdb/binutils/objdump: warning: poc2 has a corrupt section with a size (fbffffff80) larger than the file size

poc2:     file format elf64-x86-64

*** Error in `../binutils-gdb/binutils/objdump': malloc(): memory corruption: 0x08997948 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xf7d60377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xf7d662f7]
/lib/i386-linux-gnu/libc.so.6(+0x6f3f2)[0xf7d683f2]
/lib/i386-linux-gnu/libc.so.6(__libc_malloc+0xc5)[0xf7d69fc5]
/lib/i386-linux-gnu/libc.so.6(+0x29171)[0xf7d22171]
/lib/i386-linux-gnu/libc.so.6(+0x270a2)[0xf7d200a2]
/lib/i386-linux-gnu/libc.so.6(+0x26a20)[0xf7d1fa20]
/lib/i386-linux-gnu/libc.so.6(dcgettext+0x26)[0xf7d1e8b6]
/lib/i386-linux-gnu/libc.so.6(dgettext+0x12)[0xf7d1e8d2]
../binutils-gdb/binutils/objdump[0x809b1aa]
../binutils-gdb/binutils/objdump[0x8088100]
../binutils-gdb/binutils/objdump[0x80882ad]
../binutils-gdb/binutils/objdump[0x804edfd]
../binutils-gdb/binutils/objdump[0x80516a0]
../binutils-gdb/binutils/objdump[0x805182f]
../binutils-gdb/binutils/objdump[0x8051a7e]
../binutils-gdb/binutils/objdump[0x8051aeb]
../binutils-gdb/binutils/objdump[0x8052458]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xf7d11637]
../binutils-gdb/binutils/objdump[0x8049b51]
======= Memory map: ========
08048000-08246000 r-xp 00000000 08:22 433952                             ../testcase/binutils/binutils-gdb/binutils/objdump
08246000-08247000 r--p 001fd000 08:22 433952                             ../testcase/binutils/binutils-gdb/binutils/objdump
08247000-0824c000 rw-p 001fe000 08:22 433952                             ../testcase/binutils/binutils-gdb/binutils/objdump
0824c000-08253000 rw-p 00000000 00:00 0 
0898f000-089b0000 rw-p 00000000 00:00 0                                  [heap]
f7900000-f7921000 rw-p 00000000 00:00 0 
f7921000-f7a00000 ---p 00000000 00:00 0 
f7ab5000-f7ad1000 r-xp 00000000 08:06 3802106                            /lib/i386-linux-gnu/libgcc_s.so.1
f7ad1000-f7ad2000 r--p 0001b000 08:06 3802106                            /lib/i386-linux-gnu/libgcc_s.so.1
f7ad2000-f7ad3000 rw-p 0001c000 08:06 3802106                            /lib/i386-linux-gnu/libgcc_s.so.1
f7af8000-f7cf8000 r--p 00000000 08:06 527047                             /usr/lib/locale/locale-archive
f7cf8000-f7cf9000 rw-p 00000000 00:00 0 
f7cf9000-f7ea9000 r-xp 00000000 08:06 3805752                            /lib/i386-linux-gnu/libc-2.23.so
f7ea9000-f7eab000 r--p 001af000 08:06 3805752                            /lib/i386-linux-gnu/libc-2.23.so
f7eab000-f7eac000 rw-p 001b1000 08:06 3805752                            /lib/i386-linux-gnu/libc-2.23.so
f7eac000-f7eaf000 rw-p 00000000 00:00 0 
f7eaf000-f7eb2000 r-xp 00000000 08:06 3805774                            /lib/i386-linux-gnu/libdl-2.23.so
f7eb2000-f7eb3000 r--p 00002000 08:06 3805774                            /lib/i386-linux-gnu/libdl-2.23.so
f7eb3000-f7eb4000 rw-p 00003000 08:06 3805774                            /lib/i386-linux-gnu/libdl-2.23.so
f7ed0000-f7ed1000 rw-p 00000000 00:00 0 
f7ed1000-f7ed8000 r--s 00000000 08:06 676504                             /usr/lib/i386-linux-gnu/gconv/gconv-modules.cache
f7ed8000-f7ed9000 r--p 002d4000 08:06 527047                             /usr/lib/locale/locale-archive
f7ed9000-f7eda000 rw-p 00000000 00:00 0 
f7eda000-f7edd000 r--p 00000000 00:00 0                                  [vvar]
f7edd000-f7edf000 r-xp 00000000 00:00 0                                  [vdso]
f7edf000-f7f02000 r-xp 00000000 08:06 3805748                            /lib/i386-linux-gnu/ld-2.23.so
f7f02000-f7f03000 r--p 00022000 08:06 3805748                            /lib/i386-linux-gnu/ld-2.23.so
f7f03000-f7f04000 rw-p 00023000 08:06 3805748                            /lib/i386-linux-gnu/ld-2.23.so
ffd42000-ffd63000 rw-p 00000000 00:00 0                                  [stack]
Aborted
Comment 1 tfx 2018-12-16 09:08:37 UTC
I use 32bit objdump in 64bit Ubuntu 16.04.4 LTS.
Comment 2 Sourceware Commits 2018-12-17 02:26:31 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

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

commit 3a551c7a1b80fca579461774860574eabfd7f18f
Author: Alan Modra <amodra@gmail.com>
Date:   Sun Dec 16 23:02:50 2018 +1030

    PR23994, libbfd integer overflow
    
    	PR 23994
    	* aoutx.h: Include limits.h.
    	(get_reloc_upper_bound): Detect long overflow and return a file
    	too big error if it occurs.
    	* elf.c: Include limits.h.
    	(_bfd_elf_get_symtab_upper_bound): Detect long overflow and return
    	a file too big error if it occurs.
    	(_bfd_elf_get_dynamic_symtab_upper_bound): Likewise.
    	(_bfd_elf_get_dynamic_reloc_upper_bound): Likewise.
Comment 3 Alan Modra 2018-12-17 02:59:11 UTC
Fixed, along with some similar cases.
Comment 4 wang peng 2019-04-15 03:51:00 UTC
(In reply to tfx from comment #0)
> Created attachment 11464 [details]
> Heap overflow in libbfd caused by integer overflow.
> 
> Hi there,
> 
> A Heap overflow issue was discovered in bfd caused by integer overflow, as
> distributed in GNU Binutils 2.31. It also exists with the latest version in
> Binutils 2.32 commit 76d2760bc38ada83f81087f16eb151ccc0176574. This issue
> may exist for a long time.
> 
> The source Code show as follow. Exec Binutils 2.31 "objdump -d poc1" as
> example:
> 
> In disassemble_data function in objdump.c, line 2463 is a heap allocation.
> But 'relsize' maybe too small caused by integer overflow . Line 8271 in
> _bfd_elf_canonicalize_dynamic_reloc function in elf.c will cause heap
> overflow.
> 
> 
> objdump.c 
> >2456  long relsize = bfd_get_dynamic_reloc_upper_bound (abfd); //relsize = 4
> 
> >2463    aux.dynrelbuf = (arelent **) xmalloc (relsize);
> >2464    aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd,  
> >2465						    aux.dynrelbuf,
> >2466						    dynsyms);   //heap overflow
> 
> elf.c
> >8210  _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
> >8211  {
> >8212    long ret; 
>   ...
> 
> >8226    ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize) 
> >8227      * sizeof(arelent *));   //integer overflow  
> 
>   
> >8229    return ret; 
> >8230  }
> 
> >8241  _bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
> >8242				     arelent **storage, //objdump.c:2463 alloc
> >8243				     asymbol **syms)
> >8244  {
>           ...
> 	
> >8268     count = s->size / elf_section_data (s)->this_hdr.sh_entsize;
> >8269	  p = s->relocation;
> >8270	  for (i = 0; i < count; i++)
> >8271	    *storage++ = p++;             //heap overflow
> 
>           ...
> }
> 
> 
> The crash output show as follow.
> 
> $ ../binutils-gdb/binutils/objdump --version
> GNU objdump (GNU Binutils) 2.31.51.20181216
> 
> 
> $ ../binutils-gdb/binutils/objdump -d poc2 
> ../binutils-gdb/binutils/objdump: warning: poc2 has a corrupt section with a
> size (fbffffff80) larger than the file size
> 
> poc2:     file format elf64-x86-64
> 
> *** Error in `../binutils-gdb/binutils/objdump': malloc(): memory
> corruption: 0x08997948 ***
> ======= Backtrace: =========
> /lib/i386-linux-gnu/libc.so.6(+0x67377)[0xf7d60377]
> /lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xf7d662f7]
> /lib/i386-linux-gnu/libc.so.6(+0x6f3f2)[0xf7d683f2]
> /lib/i386-linux-gnu/libc.so.6(__libc_malloc+0xc5)[0xf7d69fc5]
> /lib/i386-linux-gnu/libc.so.6(+0x29171)[0xf7d22171]
> /lib/i386-linux-gnu/libc.so.6(+0x270a2)[0xf7d200a2]
> /lib/i386-linux-gnu/libc.so.6(+0x26a20)[0xf7d1fa20]
> /lib/i386-linux-gnu/libc.so.6(dcgettext+0x26)[0xf7d1e8b6]
> /lib/i386-linux-gnu/libc.so.6(dgettext+0x12)[0xf7d1e8d2]
> ../binutils-gdb/binutils/objdump[0x809b1aa]
> ../binutils-gdb/binutils/objdump[0x8088100]
> ../binutils-gdb/binutils/objdump[0x80882ad]
> ../binutils-gdb/binutils/objdump[0x804edfd]
> ../binutils-gdb/binutils/objdump[0x80516a0]
> ../binutils-gdb/binutils/objdump[0x805182f]
> ../binutils-gdb/binutils/objdump[0x8051a7e]
> ../binutils-gdb/binutils/objdump[0x8051aeb]
> ../binutils-gdb/binutils/objdump[0x8052458]
> /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xf7d11637]
> ../binutils-gdb/binutils/objdump[0x8049b51]
> ======= Memory map: ========
> 08048000-08246000 r-xp 00000000 08:22 433952                            
> ../testcase/binutils/binutils-gdb/binutils/objdump
> 08246000-08247000 r--p 001fd000 08:22 433952                            
> ../testcase/binutils/binutils-gdb/binutils/objdump
> 08247000-0824c000 rw-p 001fe000 08:22 433952                            
> ../testcase/binutils/binutils-gdb/binutils/objdump
> 0824c000-08253000 rw-p 00000000 00:00 0 
> 0898f000-089b0000 rw-p 00000000 00:00 0                                 
> [heap]
> f7900000-f7921000 rw-p 00000000 00:00 0 
> f7921000-f7a00000 ---p 00000000 00:00 0 
> f7ab5000-f7ad1000 r-xp 00000000 08:06 3802106                           
> /lib/i386-linux-gnu/libgcc_s.so.1
> f7ad1000-f7ad2000 r--p 0001b000 08:06 3802106                           
> /lib/i386-linux-gnu/libgcc_s.so.1
> f7ad2000-f7ad3000 rw-p 0001c000 08:06 3802106                           
> /lib/i386-linux-gnu/libgcc_s.so.1
> f7af8000-f7cf8000 r--p 00000000 08:06 527047                            
> /usr/lib/locale/locale-archive
> f7cf8000-f7cf9000 rw-p 00000000 00:00 0 
> f7cf9000-f7ea9000 r-xp 00000000 08:06 3805752                           
> /lib/i386-linux-gnu/libc-2.23.so
> f7ea9000-f7eab000 r--p 001af000 08:06 3805752                           
> /lib/i386-linux-gnu/libc-2.23.so
> f7eab000-f7eac000 rw-p 001b1000 08:06 3805752                           
> /lib/i386-linux-gnu/libc-2.23.so
> f7eac000-f7eaf000 rw-p 00000000 00:00 0 
> f7eaf000-f7eb2000 r-xp 00000000 08:06 3805774                           
> /lib/i386-linux-gnu/libdl-2.23.so
> f7eb2000-f7eb3000 r--p 00002000 08:06 3805774                           
> /lib/i386-linux-gnu/libdl-2.23.so
> f7eb3000-f7eb4000 rw-p 00003000 08:06 3805774                           
> /lib/i386-linux-gnu/libdl-2.23.so
> f7ed0000-f7ed1000 rw-p 00000000 00:00 0 
> f7ed1000-f7ed8000 r--s 00000000 08:06 676504                            
> /usr/lib/i386-linux-gnu/gconv/gconv-modules.cache
> f7ed8000-f7ed9000 r--p 002d4000 08:06 527047                            
> /usr/lib/locale/locale-archive
> f7ed9000-f7eda000 rw-p 00000000 00:00 0 
> f7eda000-f7edd000 r--p 00000000 00:00 0                                 
> [vvar]
> f7edd000-f7edf000 r-xp 00000000 00:00 0                                 
> [vdso]
> f7edf000-f7f02000 r-xp 00000000 08:06 3805748                           
> /lib/i386-linux-gnu/ld-2.23.so
> f7f02000-f7f03000 r--p 00022000 08:06 3805748                           
> /lib/i386-linux-gnu/ld-2.23.so
> f7f03000-f7f04000 rw-p 00023000 08:06 3805748                           
> /lib/i386-linux-gnu/ld-2.23.so
> ffd42000-ffd63000 rw-p 00000000 00:00 0                                 
> [stack]
> Aborted


hi,I have some questions about this vulnerability.
1. Do you have to compile in 32-bit to get this exception?
2. Can you provide the source code of poc1 and poc2 that reproduce the error?
3. How is the error details above displayed?