Bug 23541 - heap-buffer-overflow in /elfutils/libdw/dwarf_getaranges.c:156
Summary: heap-buffer-overflow in /elfutils/libdw/dwarf_getaranges.c:156
Status: RESOLVED FIXED
Alias: None
Product: elfutils
Classification: Unclassified
Component: libdw (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-08-17 04:06 UTC by wcventure
Modified: 2018-09-03 08:28 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
addr2line -e @@ -- 500 50 10 -1000 (787 bytes, application/x-executable)
2018-08-17 04:06 UTC, wcventure
Details

Note You need to log in before you can comment on or make changes to this bug.
Description wcventure 2018-08-17 04:06:24 UTC
Created attachment 11189 [details]
addr2line -e @@ -- 500 50 10 -1000

When executing "./eu-addr2line -e @@ -- 500 50 10 -1000", AddressSanitizer catch a heap-buffer-overflow crash.


117833==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000edbb at pc 0x7fde94ff95ed bp 0x7fff4f475910 sp 0x7fff4f475900
READ of size 1 at 0x60200000edbb thread T0
    #0 0x7fde94ff95ec in dwarf_getaranges /home/wcventure/Documents/Cproject/elfutils/libdw/dwarf_getaranges.c:156
    #1 0x7fde95091c6f in addrarange /home/wcventure/Documents/Cproject/elfutils/libdwfl/cu.c:54
    #2 0x7fde95091c6f in __libdwfl_addrcu /home/wcventure/Documents/Cproject/elfutils/libdwfl/cu.c:313
    #3 0x7fde95098b5e in dwfl_module_getsrc /home/wcventure/Documents/Cproject/elfutils/libdwfl/dwfl_module_getsrc.c:44
    #4 0x40461c in handle_address /home/wcventure/Documents/Cproject/elfutils/src/addr2line.c:680
    #5 0x40263b in main /home/wcventure/Documents/Cproject/elfutils/src/addr2line.c:197
    #6 0x7fde9459282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #7 0x402c08 in _start (/home/wcventure/Documents/Cproject/elfutils/build/bin/eu-addr2line+0x402c08)

0x60200000edbb is located 0 bytes to the right of 11-byte region [0x60200000edb0,0x60200000edbb)
allocated by thread T0 here:
    #0 0x7fde953cc602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x7fde94d10ce8 in convert_data /home/wcventure/Documents/Cproject/elfutils/libelf/elf_getdata.c:164
    #2 0x7fde94d10ce8 in __libelf_set_data_list_rdlock /home/wcventure/Documents/Cproject/elfutils/libelf/elf_getdata.c:431

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/wcventure/Documents/Cproject/elfutils/libdw/dwarf_getaranges.c:156 dwarf_getaranges
Shadow bytes around the buggy address:
  0x0c047fff9d60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9d70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9db0: fa fa fa fa fa fa 00[03]fa fa 01 fa fa fa 00 01
  0x0c047fff9dc0: fa fa 00 04 fa fa 00 04 fa fa 00 04 fa fa 00 04
  0x0c047fff9dd0: fa fa 00 04 fa fa 00 04 fa fa 00 04 fa fa fd fa
  0x0c047fff9de0: fa fa 00 04 fa fa 00 04 fa fa 00 04 fa fa 00 04
  0x0c047fff9df0: fa fa 00 04 fa fa 00 04 fa fa 00 04 fa fa fd fa
  0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 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
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==117833==ABORTING
Comment 1 Mark Wielaard 2018-08-17 19:39:57 UTC
I couldn't replicate with the given reproducer.
But it is pretty clear that we forget to check there is enough data available when reading the aranges header in dwarf_getaranges.c. In particular we forget to check we can actually read the address and segment size bytes.

diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index bff9c860..de5b81ba 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -148,6 +148,10 @@ dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
                                   length_bytes, &offset, IDX_debug_info, 4))
        goto fail;
 
+      /* Next up two bytes for address and segment size.  */
+      if (readp + 2 > readendp)
+       goto invalid;
+
       unsigned int address_size = *readp++;
       if (unlikely (address_size != 4 && address_size != 8))
        goto invalid;

While checking similar code in readelf.c I found we have a similar check missing, but this time just for the segment size:

diff --git a/src/readelf.c b/src/readelf.c
index 7b5707f8..7b488ac5 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -5447,6 +5447,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
          goto next_table;
        }
 
+      if (readp + 1 > readendp)
+       goto invalid_data;
       unsigned int segment_size = *readp++;
       printf (gettext (" Segment size:  %6" PRIu64 "\n\n"),
              (uint64_t) segment_size);

It looks like all other checks are in place, but this code could probably benefit from some extra fuzzing.
Comment 2 Mark Wielaard 2018-08-18 20:50:43 UTC
commit 29e31978ba51c1051743a503ee325b5ebc03d7e9
Author: Mark Wielaard <mark@klomp.org>
Date:   Sat Aug 18 13:27:48 2018 +0200

    libdw, readelf: Make sure there is enough data to read full aranges header.
    
    dwarf_getaranges didn't check if there was enough data left to read both
    the address and segment size. readelf didn't check there was enough data
    left to read the segment size.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=23541
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>
Comment 3 Mark Wielaard 2018-09-03 08:28:19 UTC
For reference, this bug apparently got assigned CVE-2018-16062.