Created attachment 10569 [details] POC file Triggered by "./readelf -w $POC" Tested on Ubuntu 16.04 (x86) An integer overflow is occurred when processing corrupted elf file. ASAN output: ./readelf -w $POC ==14407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4803295 at pc 0x081f11ad bp 0xbff83328 sp 0xbff8331c READ of size 1 at 0xb4803295 thread T0 #0 0x81f11ac in display_debug_frames /home/min/fuzzing/src/binutils/binutils-gdb/binutils/dwarf.c:7433:20 #1 0x81c4355 in display_debug_section /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:13399:16 #2 0x8172193 in process_section_contents /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:13485:10 #3 0x81486c0 in process_object /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:18173:9 #4 0x8137e9a in process_file /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:18565:13 #5 0x81367a1 in main /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:18637:11 #6 0xb7507636 in __libc_start_main /build/glibc-KM3i_a/glibc-2.23/csu/../csu/libc-start.c:291 #7 0x805fda7 in _start (/home/min/fuzzing/program/binutils-master-asan/bin/readelf+0x805fda7) 0xb4803295 is located 0 bytes to the right of 341-byte region [0xb4803140,0xb4803295) allocated by thread T0 here: #0 0x81040e4 in __interceptor_malloc (/home/min/fuzzing/program/binutils-master-asan/bin/readelf+0x81040e4) #1 0x81384ba in get_data /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:415:9 #2 0x81347f4 in load_specific_debug_section /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:13200:38 #3 0x81c42c4 in display_debug_section /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:13392:6 #4 0x8172193 in process_section_contents /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:13485:10 #5 0x81486c0 in process_object /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:18173:9 #6 0x8137e9a in process_file /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:18565:13 #7 0x81367a1 in main /home/min/fuzzing/src/binutils/binutils-gdb/binutils/readelf.c:18637:11 #8 0xb7507636 in __libc_start_main /build/glibc-KM3i_a/glibc-2.23/csu/../csu/libc-start.c:291 SUMMARY: AddressSanitizer: heap-buffer-overflow /home/min/fuzzing/src/binutils/binutils-gdb/binutils/dwarf.c:7433:20 in display_debug_frames Shadow bytes around the buggy address: 0x36900600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36900610: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36900620: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 0x36900630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x36900640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x36900650: 00 00[05]fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36900660: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x36900670: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x36900680: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa 0x36900690: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x369006a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 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 Left alloca redzone: ca Right alloca redzone: cb ==14407==ABORTING The GDB debugging information is as follows: (gdb) r -w $POC (gdb) bt Breakpoint 4, display_debug_frames (section=0x8366c84 <debug_displays+420>, file=0xb5003d80) at dwarf.c:7432 7432 for (i = 0; i < augmentation_data_len; ++i) (gdb) bt #0 display_debug_frames (section=0x8366c84 <debug_displays+420>, file=0xb5003d80) at dwarf.c:7432 #1 0x081c4356 in display_debug_section (shndx=18, section=0xb4602d90, file=0xb5003d80) at readelf.c:13399 #2 0x08172194 in process_section_contents (file=0xb5003d80) at readelf.c:13485 #3 0x081486c1 in process_object (file_name=0xbffff284 "/home/min/Downloads/test", file=0xb5003d80) at readelf.c:18173 #4 0x08137e9b in process_file (file_name=0xbffff284 "/home/min/Downloads/test") at readelf.c:18565 #5 0x081367a2 in main (argc=3, argv=0xbffff064) at readelf.c:18637 (gdb) p start $18 = (unsigned char *) 0x27e6046a "" (gdb) p end $19 = (unsigned char *) 0xb5003994 "" (gdb) p augmentation_data_len $20 = 1927662487 Proposed patch: Check if variable start is overflowed. --- a/home/min/fuzzing/src/binutils/binutils-gdb/binutils/dwarf.c +++ b/home/min/Downloads/dwarf.c @@ -7401,7 +7401,7 @@ display_debug_frames (struct dwarf_section *section, augmentation_data = start; start += augmentation_data_len; /* PR 17512: file: 722-8446-0.004. */ - if (start >= end || ((signed long) augmentation_data_len) < 0) + if (start >= end || ((signed long) augmentation_data_len) < 0 || augmentation_data > start) { warn (_("Corrupt augmentation data length: %lx\n"), augmentation_data_len); 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.
The master branch has been updated by Nick Clifton <nickc@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bf59c5d5f4f5b8b4da1f5f605cfa546f8029b43d commit bf59c5d5f4f5b8b4da1f5f605cfa546f8029b43d Author: Nick Clifton <nickc@redhat.com> Date: Fri Nov 3 13:57:15 2017 +0000 Fix integer overflow problems when reading an ELF binary with corrupt augmentation data. PR 22386 * dwarf.c (read_cie): Use bfd_size_type for augmentation_data_len. (display_augmentation_data): New function. (display_debug_frames): Use it. Check for integer overflow when testing augmentation_data_len.
Hi Mingi, Thanks for the bug report. I was unable to reproduce the exact failure that you reported, but I did find something similar. The patch you have supplied does help, but I also found that there was a problem trying to read a 64-bit LEB128-encoded value into a 32-bit variable. So I have extended the patch to cover that. Cheers Nick PS. You might find it interesting to create some test binaries with very large LEB128 values in them (more than 128 bits say) and see how the various tools in the binutils suite cope with them.