Bug 24085 - An Out of Memory problem was discovered in function in read_long_names in elf_begin.c in libelf
Summary: An Out of Memory problem was discovered in function in read_long_names in elf...
Status: RESOLVED FIXED
Alias: None
Product: elfutils
Classification: Unclassified
Component: libelf (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-01-11 06:27 UTC by wcventure
Modified: 2019-02-14 10:51 UTC (History)
2 users (show)

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


Attachments
POC (125 bytes, application/x-archive)
2019-01-11 06:27 UTC, wcventure
Details

Note You need to log in before you can comment on or make changes to this bug.
Description wcventure 2019-01-11 06:27:30 UTC
Created attachment 11531 [details]
POC

Hi, there.

We test the program at the master branch. An Out of Memory problem was discovered in function in read_long_names in elf_begin.c in libelf. The program tries to allocate with a large number size(444444454912 bytes) of memory.

$git log

> commit 1dabad36ee28aa76b8cf14b6426b379cabee6def
> Author: Jim Wilson <jimw@sifive.com>
> Date:   Thu Dec 27 15:25:49 2018 -0800
> 
>     RISC-V: Improve riscv64 core file support.
> 
>     This fixes two problems.  The offset for x1 is changed from 1 to 8 because
>     this is a byte offset not a register skip count.  Support for reading the
>     PC value is added.  This requires changing the testsuite to match the new
>     readelf output for coredumps.
> 
>     Signed-off-by: Jim Wilson <jimw@sifive.com>

The ASAN dumps the stack trace as follows:

> ==10165==ERROR: AddressSanitizer failed to allocate 0x677af43000 (444444454912) bytes of LargeMmapAllocator (error code: 12)
> ==10165==Process memory map follows:
> 	0x000000400000-0x000000430000	/home/wencheng/Experiment/elfutils/build/bin/eu-ar
> 	0x00000062f000-0x000000630000	/home/wencheng/Experiment/elfutils/build/bin/eu-ar
> 	0x000000630000-0x000000633000	/home/wencheng/Experiment/elfutils/build/bin/eu-ar
> 	0x00007fff7000-0x00008fff7000	
> 	0x00008fff7000-0x02008fff7000	
> 	0x02008fff7000-0x10007fff8000	
> 	0x600000000000-0x602000000000	
> 	0x602000000000-0x602000010000	
> 	0x602000010000-0x602e00000000	
> 	0x602e00000000-0x602e00010000	
> 	0x602e00010000-0x604000000000	
> 	0x604000000000-0x604000010000	
> 	0x604000010000-0x604e00000000	
> 	0x604e00000000-0x604e00010000	
> 	0x604e00010000-0x606000000000	
> 	0x606000000000-0x606000010000	
> 	0x606000010000-0x606e00000000	
> 	0x606e00000000-0x606e00010000	
> 	0x606e00010000-0x607000000000	
> 	0x607000000000-0x607000010000	
> 	0x607000010000-0x607e00000000	
> 	0x607e00000000-0x607e00010000	
> 	0x607e00010000-0x608000000000	
> 	0x608000000000-0x608000010000	
> 	0x608000010000-0x608e00000000	
> 	0x608e00000000-0x608e00010000	
> 	0x608e00010000-0x60b000000000	
> 	0x60b000000000-0x60b000010000	
> 	0x60b000010000-0x60be00000000	
> 	0x60be00000000-0x60be00010000	
> 	0x60be00010000-0x60c000000000	
> 	0x60c000000000-0x60c000010000	
> 	0x60c000010000-0x60ce00000000	
> 	0x60ce00000000-0x60ce00010000	
> 	0x60ce00010000-0x60f000000000	
> 	0x60f000000000-0x60f000010000	
> 	0x60f000010000-0x60fe00000000	
> 	0x60fe00000000-0x60fe00010000	
> 	0x60fe00010000-0x610000000000	
> 	0x610000000000-0x610000010000	
> 	0x610000010000-0x610e00000000	
> 	0x610e00000000-0x610e00010000	
> 	0x610e00010000-0x611000000000	
> 	0x611000000000-0x611000010000	
> 	0x611000010000-0x611e00000000	
> 	0x611e00000000-0x611e00010000	
> 	0x611e00010000-0x612000000000	
> 	0x612000000000-0x612000010000	
> 	0x612000010000-0x612e00000000	
> 	0x612e00000000-0x612e00010000	
> 	0x612e00010000-0x614000000000	
> 	0x614000000000-0x614000010000	
> 	0x614000010000-0x614e00000000	
> 	0x614e00000000-0x614e00010000	
> 	0x614e00010000-0x618000000000	
> 	0x618000000000-0x618000010000	
> 	0x618000010000-0x618e00000000	
> 	0x618e00000000-0x618e00010000	
> 	0x618e00010000-0x619000000000	
> 	0x619000000000-0x619000010000	
> 	0x619000010000-0x619e00000000	
> 	0x619e00000000-0x619e00010000	
> 	0x619e00010000-0x61a000000000	
> 	0x61a000000000-0x61a000010000	
> 	0x61a000010000-0x61ae00000000	
> 	0x61ae00000000-0x61ae00010000	
> 	0x61ae00010000-0x624000000000	
> 	0x624000000000-0x624000010000	
> 	0x624000010000-0x624e00000000	
> 	0x624e00000000-0x624e00010000	
> 	0x624e00010000-0x640000000000	
> 	0x640000000000-0x640000003000	
> 	0x7f18aa227000-0x7f18aa500000	/usr/lib/locale/locale-archive
> 	0x7f18aa500000-0x7f18aa600000	
> 	0x7f18aa700000-0x7f18aa800000	
> 	0x7f18aa900000-0x7f18aaa00000	
> 	0x7f18aab00000-0x7f18aac00000	
> 	0x7f18aac59000-0x7f18acfab000	
> 	0x7f18acfab000-0x7f18acfc4000	/lib/x86_64-linux-gnu/libz.so.1.2.8
> 	0x7f18acfc4000-0x7f18ad1c3000	/lib/x86_64-linux-gnu/libz.so.1.2.8
> 	0x7f18ad1c3000-0x7f18ad1c4000	/lib/x86_64-linux-gnu/libz.so.1.2.8
> 	0x7f18ad1c4000-0x7f18ad1c5000	/lib/x86_64-linux-gnu/libz.so.1.2.8
> 	0x7f18ad1c5000-0x7f18ad1dc000	/lib/x86_64-linux-gnu/libgcc_s.so.1
> 	0x7f18ad1dc000-0x7f18ad3db000	/lib/x86_64-linux-gnu/libgcc_s.so.1
> 	0x7f18ad3db000-0x7f18ad3dc000	/lib/x86_64-linux-gnu/libgcc_s.so.1
> 	0x7f18ad3dc000-0x7f18ad3dd000	/lib/x86_64-linux-gnu/libgcc_s.so.1
> 	0x7f18ad3dd000-0x7f18ad4e5000	/lib/x86_64-linux-gnu/libm-2.23.so
> 	0x7f18ad4e5000-0x7f18ad6e4000	/lib/x86_64-linux-gnu/libm-2.23.so
> 	0x7f18ad6e4000-0x7f18ad6e5000	/lib/x86_64-linux-gnu/libm-2.23.so
> 	0x7f18ad6e5000-0x7f18ad6e6000	/lib/x86_64-linux-gnu/libm-2.23.so
> 	0x7f18ad6e6000-0x7f18ad6fe000	/lib/x86_64-linux-gnu/libpthread-2.23.so
> 	0x7f18ad6fe000-0x7f18ad8fd000	/lib/x86_64-linux-gnu/libpthread-2.23.so
> 	0x7f18ad8fd000-0x7f18ad8fe000	/lib/x86_64-linux-gnu/libpthread-2.23.so
> 	0x7f18ad8fe000-0x7f18ad8ff000	/lib/x86_64-linux-gnu/libpthread-2.23.so
> 	0x7f18ad8ff000-0x7f18ad903000	
> 	0x7f18ad903000-0x7f18ad90a000	/lib/x86_64-linux-gnu/librt-2.23.so
> 	0x7f18ad90a000-0x7f18adb09000	/lib/x86_64-linux-gnu/librt-2.23.so
> 	0x7f18adb09000-0x7f18adb0a000	/lib/x86_64-linux-gnu/librt-2.23.so
> 	0x7f18adb0a000-0x7f18adb0b000	/lib/x86_64-linux-gnu/librt-2.23.so
> 	0x7f18adb0b000-0x7f18adb0e000	/lib/x86_64-linux-gnu/libdl-2.23.so
> 	0x7f18adb0e000-0x7f18add0d000	/lib/x86_64-linux-gnu/libdl-2.23.so
> 	0x7f18add0d000-0x7f18add0e000	/lib/x86_64-linux-gnu/libdl-2.23.so
> 	0x7f18add0e000-0x7f18add0f000	/lib/x86_64-linux-gnu/libdl-2.23.so
> 	0x7f18add0f000-0x7f18adecf000	/lib/x86_64-linux-gnu/libc-2.23.so
> 	0x7f18adecf000-0x7f18ae0cf000	/lib/x86_64-linux-gnu/libc-2.23.so
> 	0x7f18ae0cf000-0x7f18ae0d3000	/lib/x86_64-linux-gnu/libc-2.23.so
> 	0x7f18ae0d3000-0x7f18ae0d5000	/lib/x86_64-linux-gnu/libc-2.23.so
> 	0x7f18ae0d5000-0x7f18ae0d9000	
> 	0x7f18ae0d9000-0x7f18ae211000	/home/wencheng/Experiment/elfutils/build/lib/libelf-0.175.so
> 	0x7f18ae211000-0x7f18ae410000	/home/wencheng/Experiment/elfutils/build/lib/libelf-0.175.so
> 	0x7f18ae410000-0x7f18ae411000	/home/wencheng/Experiment/elfutils/build/lib/libelf-0.175.so
> 	0x7f18ae411000-0x7f18ae414000	/home/wencheng/Experiment/elfutils/build/lib/libelf-0.175.so
> 	0x7f18ae414000-0x7f18ae415000	
> 	0x7f18ae415000-0x7f18ae567000	/usr/lib/x86_64-linux-gnu/libasan.so.4.0.0
> 	0x7f18ae567000-0x7f18ae766000	/usr/lib/x86_64-linux-gnu/libasan.so.4.0.0
> 	0x7f18ae766000-0x7f18ae769000	/usr/lib/x86_64-linux-gnu/libasan.so.4.0.0
> 	0x7f18ae769000-0x7f18ae76c000	/usr/lib/x86_64-linux-gnu/libasan.so.4.0.0
> 	0x7f18ae76c000-0x7f18af3d1000	
> 	0x7f18af3d1000-0x7f18af3f7000	/lib/x86_64-linux-gnu/ld-2.23.so
> 	0x7f18af4fd000-0x7f18af5c5000	
> 	0x7f18af5c5000-0x7f18af5c6000	/home/wencheng/Experiment/elfutils/Fuzzing/ar_out/crashes/id:000000,sig:06,src:000264,op:havoc,rep:2
> 	0x7f18af5c6000-0x7f18af5de000	
> 	0x7f18af5de000-0x7f18af5f6000	
> 	0x7f18af5f6000-0x7f18af5f7000	/lib/x86_64-linux-gnu/ld-2.23.so
> 	0x7f18af5f7000-0x7f18af5f8000	/lib/x86_64-linux-gnu/ld-2.23.so
> 	0x7f18af5f8000-0x7f18af5f9000	
> 	0x7fff88ddc000-0x7fff88dfd000	[stack]
> 	0x7fff88f04000-0x7fff88f07000	[vvar]
> 	0x7fff88f07000-0x7fff88f09000	[vdso]
> 	0xffffffffff600000-0xffffffffff601000	[vsyscall]
> ==10165==End of process memory map.
> ==10165==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/sanitizer_common/sanitizer_common.cc:118 "((0 && "unable to mmap")) != (0)" (0x0, 0x0)
>     #0 0x7f18ae4fec42  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe9c42)
>     #1 0x7f18ae51d5d5 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x1085d5)
>     #2 0x7f18ae5084d2  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xf34d2)
>     #3 0x7f18ae5148e5  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xff8e5)
>     #4 0x7f18ae43d83d  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x2883d)
>     #5 0x7f18ae4f3b5a in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb5a)
>     #6 0x7f18ae0fd25c in read_long_names /home/wencheng/Experiment/elfutils/libelf/elf_begin.c:750
>     #7 0x7f18ae0fd25c in __libelf_next_arhdr_wrlock /home/wencheng/Experiment/elfutils/libelf/elf_begin.c:881
>     #8 0x7f18ae100db7 in dup_elf /home/wencheng/Experiment/elfutils/libelf/elf_begin.c:1030
>     #9 0x7f18ae100db7 in lock_dup_elf /home/wencheng/Experiment/elfutils/libelf/elf_begin.c:1088
>     #10 0x7f18ae100db7 in elf_begin /home/wencheng/Experiment/elfutils/libelf/elf_begin.c:1134
>     #11 0x4090b0 in do_oper_extract /home/wencheng/Experiment/elfutils/src/ar.c:496
>     #12 0x403e25 in main /home/wencheng/Experiment/elfutils/src/ar.c:252
>     #13 0x7f18add2f82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
>     #14 0x405338 in _start (/home/wencheng/Experiment/elfutils/build/bin/eu-ar+0x405338)
Comment 1 wcventure 2019-01-11 06:34:05 UTC
Please use the "./eu-ar -tv $POC" to reproduce the bug. If you have any questions, please let me know.
Comment 2 Mark Wielaard 2019-01-15 14:09:16 UTC
I am not sure this is a real issue. The read_long_names code does the following:

  newp = (char *) malloc (len);
  if (newp != NULL)

And if it is newp NULL is returned, which is then interpreted as an error:

              /* No long name table although it is reference.  The archive is
                 broken.  */
              __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
              return -1;

There are also checks that no more data is read than there is in the file, so if len is really big and malloc still succeeds that is also flagged as a corrupt file.

So, yeah, a malloc call might fail on an invalid file, but nothing bad will happen.

If you do feel it is an issue. We could move up the size checks, so no malloc is done at all if len is really weird and we know the malloc would probably fail anyway.
Comment 3 Mark Wielaard 2019-02-08 00:40:18 UTC
CVE-2019-7148
Comment 4 Mark Wielaard 2019-02-14 10:51:16 UTC
commit e32380ecefbb23448541367283d3b94930762986
Author: Mark Wielaard <mark@klomp.org>
Date:   Thu Feb 14 11:47:59 2019 +0100

    libelf: Make sure ar_size is terminated when reading ar long names.
    
    The ar_size is given as a fixed size decimal string, right padded with
    spaces.  Make sure we read it properly even if there is no terminating
    space. Also sanity check len early if we can.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=24085
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>