Bug 17453

Summary: Two issues found by AddressSanitizer
Product: binutils Reporter: Markus Trippelsdorf <markus>
Component: ldAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: amodra
Priority: P2    
Version: 2.25   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Markus Trippelsdorf 2014-10-03 06:51:48 UTC
1)

markus@x4 ld % /var/tmp/binutils-gdb/ld/ld-new -o tmpdir/tlsie4 -L/var/tmp/binutils-gdb/ld/testsuite/ld-x86-64 -melf32_x86_64 tmpdir/tlsie4.o
=================================================================
==20993==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400000b48f at pc 0x4da32d bp 0x7fffcd882d00 sp 0x7fffcd882cf8
READ of size 1 at 0x60400000b48f thread T0
    #0 0x4da32c in elf_x86_64_relocate_section /var/tmp/binutils-gdb/bfd/elf64-x86-64.c:4294
    #1 0x5411d2 in elf_link_input_bfd /var/tmp/binutils-gdb/bfd/elflink.c:9721
    #2 0x54585c in bfd_elf_final_link /var/tmp/binutils-gdb/bfd/elflink.c:10908
    #3 0x43d377 in ldwrite /var/tmp/binutils-gdb/ld/ldwrite.c:581
    #4 0x406150 in main ldmain.c:427
    #5 0x7fddf2b84fcf in __libc_start_main (/lib/libc.so.6+0x1ffcf)
    #6 0x407484 (/var/tmp/binutils-gdb/ld/ld-new+0x407484)

0x60400000b48f is located 1 bytes to the left of 40-byte region [0x60400000b490,0x60400000b4b8)
allocated by thread T0 here:
    #0 0x7fddf3132bcf in malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/libasan.so.1+0x5ebcf)
    #1 0x490c8d in bfd_malloc /var/tmp/binutils-gdb/bfd/libbfd.c:181

SUMMARY: AddressSanitizer: heap-buffer-overflow /var/tmp/binutils-gdb/bfd/elf64-x86-64.c:4294 elf_x86_64_relocate_section
Shadow bytes around the buggy address:
  0x0c087fff9640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9670: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00 fa
  0x0c087fff9680: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
=>0x0c087fff9690: fa[fa]00 00 00 00 00 fa fa fa fd fd fd fd fd fd
  0x0c087fff96a0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
  0x0c087fff96b0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
  0x0c087fff96c0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
  0x0c087fff96d0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
  0x0c087fff96e0: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Contiguous container OOB:fc
  ASan internal:           fe
==20993==ABORTING

2)

markus@x4 ld % /var/tmp/binutils-gdb/ld/../binutils/readelf -d tmpdir/audit.out
=================================================================
==21468==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000005448c0 at pc 0x7f5d99269322 bp 0x7fffa0f91250 sp 0x7fffa0f91208
WRITE of size 4097 at 0x0000005448c0 thread T0
    #0 0x7f5d99269321 in scanf_common(void*, int, bool, char const*, __va_list_tag*) [clone .constprop.55] (/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/libasan.so.1+0x2b321)
    #1 0x7f5d99269c28 in vfscanf (/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/libasan.so.1+0x2bc28)
    #2 0x7f5d99269d22 in __interceptor_fscanf (/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/libasan.so.1+0x2bd22)
    #3 0x418337 in process_program_headers /var/tmp/binutils-gdb/binutils/readelf.c:4403
    #4 0x43c7b7 in process_object /var/tmp/binutils-gdb/binutils/readelf.c:14465
    #5 0x402d05 in process_file /var/tmp/binutils-gdb/binutils/readelf.c:14849
    #6 0x402d05 in main /var/tmp/binutils-gdb/binutils/readelf.c:14914
    #7 0x7f5d98ceefcf in __libc_start_main (/lib/libc.so.6+0x1ffcf)
    #8 0x40338d (/var/tmp/binutils-gdb/binutils/readelf+0x40338d)

0x0000005448c0 is located 32 bytes to the left of global variable 'dynamic_syminfo_nent' from 'readelf.c' (0x5448e0) of size 4
0x0000005448c0 is located 0 bytes to the right of global variable 'program_interpreter' from 'readelf.c' (0x5438c0) of size 4096
SUMMARY: AddressSanitizer: global-buffer-overflow ??:0 scanf_common(void*, int, bool, char const*, __va_list_tag*) [clone .constprop.55]
Shadow bytes around the buggy address:
  0x0000800a08c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800a08d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800a08e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800a08f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800a0900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000800a0910: 00 00 00 00 00 00 00 00[f9]f9 f9 f9 04 f9 f9 f9
  0x0000800a0920: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0000800a0930: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0000800a0940: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0000800a0950: f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0000800a0960: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Contiguous container OOB:fc
  ASan internal:           fe
==21468==ABORTING
Comment 1 Markus Trippelsdorf 2014-10-03 11:02:10 UTC
Fix for 2)

diff --git a/binutils/readelf.c b/binutils/readelf.c
index d9c12cc8da61..1a4c4b6bea0c 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -4400,7 +4400,7 @@ process_program_headers (FILE * file)
                error (_("Internal error: failed to create format string to display program interpreter\n"));
 
              program_interpreter[0] = 0;
-             if (fscanf (file, fmt, program_interpreter) <= 0)
+             if (fscanf (file, fmt, program_interpreter - 1) <= 0)
                error (_("Unable to read program interpreter name\n"));
 
              if (do_segments)
Comment 2 Markus Trippelsdorf 2014-10-03 13:27:37 UTC
Please disregard comment2.

Here's a list of issues found with  -fsanitize=undefined: 

libbfd.c:739:10: runtime error: signed integer overflow: 9223372036854775804 - -9223372036854775808 cannot be represented in type 'long'
read.c:1707:24: runtime error: left shift of 2 by 63 places cannot be represented in type 'offsetT' (aka 'long')
write.c:2312:17: runtime error: left shift of negative value -1
config/tc-i386.c:1978:27: runtime error: left shift of negative value -1
config/tc-i386.c:1979:22: runtime error: left shift of negative value -1
config/tc-i386.c:1979:53: runtime error: left shift of negative value -1
cp-demangle.c:4059:47: runtime error: variable length array bound evaluates to non-positive value 0
cp-demangle.c:4060:49: runtime error: variable length array bound evaluates to non-positive value 0
dwarf.c:262:19: runtime error: left shift of negative value -1
dwarf.c:2669:23: runtime error: left shift of 251 by 24 places cannot be represented in type 'int'
elflink.c:78:12: runtime error: member access within null pointer of type 'struct elf_link_hash_entry'
expr.c:1024:31: runtime error: negation of -9223372036854775808 cannot be represented in type 'offsetT' (aka 'long'); cast to an unsigned type to negate this value to itself
Comment 3 Markus Trippelsdorf 2014-10-03 14:13:20 UTC
Possible fix for 2)

diff --git a/binutils/readelf.c b/binutils/readelf.c
index d9c12cc8da61..924d45f8c180 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -179,7 +179,7 @@ static Elf_Internal_Sym * dynamic_symbols;
 static Elf_Internal_Syminfo * dynamic_syminfo;
 static unsigned long dynamic_syminfo_offset;
 static unsigned int dynamic_syminfo_nent;
-static char program_interpreter[PATH_MAX];
+static char program_interpreter[PATH_MAX + 1];
 static bfd_vma dynamic_info[DT_ENCODING];
 static bfd_vma dynamic_info_DT_GNU_HASH;
 static bfd_vma version_info[16];
Comment 4 Sourceware Commits 2014-10-14 04:44:23 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, master has been updated
       via  9495b2e66f772783eb89cfa755e1e09641fa44eb (commit)
      from  daf5e10e4cb2c5e502950dae5da5936d9a3d5a79 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit 9495b2e66f772783eb89cfa755e1e09641fa44eb
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Oct 14 13:30:57 2014 +1030

    Correct fscanf char field count
    
    %<number>s as an fscanf format does not include the trailing NULL.
    PATH_MAX does include the trailing NULL.
    
    	PR 17453
    	* readelf.c (process_program_headers): Correct fscanf format used
    	for interpreter.

-----------------------------------------------------------------------

Summary of changes:
 binutils/ChangeLog |   10 ++++++++--
 binutils/readelf.c |    2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)
Comment 5 Sourceware Commits 2014-10-14 04:52:32 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, master has been updated
       via  65879393f04e14a9ab8797a8e66e0ec8d94108b5 (commit)
      from  9495b2e66f772783eb89cfa755e1e09641fa44eb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit 65879393f04e14a9ab8797a8e66e0ec8d94108b5
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Oct 14 13:36:20 2014 +1030

    Avoid undefined behaviour with signed expressions
    
    	PR 17453
    bfd/
    	* libbfd.c (COERCE16, COERCE32, COERCE64): Use unsigned types.
    	(EIGHT_GAZILLION): Delete.
    binutils/
    	* dwarf.c (read_leb128): Avoid signed overflow.
    	(read_debug_line_header): Likewise.
    gas/
    	* config/tc-i386.c (fits_in_signed_long): Use unsigned param and
    	expression to avoid signed overflow.
    	(fits_in_signed_byte, fits_in_unsigned_byte, fits_in_unsigned_word,
    	fits_in_signed_word, fits_in_unsigned_long): Similarly.
    	* expr.c (operand <'-'>): Avoid signed overflow.
    	* read.c (s_comm_internal): Likewise.

-----------------------------------------------------------------------

Summary of changes:
 bfd/ChangeLog        |    6 ++++++
 bfd/libbfd.c         |    7 +++----
 binutils/ChangeLog   |    6 ++++++
 binutils/dwarf.c     |    8 ++------
 gas/ChangeLog        |   10 ++++++++++
 gas/config/tc-i386.c |   25 ++++++++++++-------------
 gas/expr.c           |    3 ++-
 gas/read.c           |    2 +-
 gas/write.c          |    2 +-
 9 files changed, 43 insertions(+), 26 deletions(-)
Comment 6 Alan Modra 2014-10-14 05:23:53 UTC
Thanks Markus.  I've fixed most of these issues, and opened pr17482 for the x86_64 tls problem.  I haven't fixed the -fsanitize=undefined problem with libiberty/cp-demangle.c.  These should be reported in gcc's bugzilla.  I also haven't fixed the elflink.c -fsanitize=undefined error since I think that one may be a bug in the sanitizer.