Bug 21301

Summary: memory allocation failure in __libelf_decompress
Product: elfutils Reporter: Agostino Sarubbo <ago>
Component: libelfAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: elfutils-devel, mark
Priority: P2    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: stacktrace

Description Agostino Sarubbo 2017-03-24 09:20:26 UTC
Created attachment 9938 [details]
stacktrace

AN IMPORTANT NOTE:
as the stacktrace said this can be a false positive, so if you think that there isn't anything to fix, feel free to close.

On elfutils-0.168:

# eu-readelf -a $FILE
==1927==WARNING: AddressSanitizer failed to allocate 0x280065041580 bytes
    #5 0x7f85fb88dd1e in __libelf_decompress /tmp/portage/dev-libs/elfutils-0.168/work/elfutils-0.168/libelf/elf_compress.c:214


Compiled with: gcc-6.3.0

Reproducer:
https://github.com/asarubbo/poc/blob/master/00227-elfutils-memallocfailure

Stacktrace attached.
Comment 1 Mark Wielaard 2017-03-24 13:53:52 UTC
That is slightly tricky. We do have to trust the input data to give us the expected output size. We won't know if that was correct till we decompressed the input. We do actually double check the given output size was correct at the end of the decompression. But we could catch some really bogus sizes before trying to allocate a giant amount of memory and decompressing stuff for nothing (like in this case).

diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index dac0ac6..711be59 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -211,6 +211,15 @@ void *
 internal_function
 __libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
 {
+  /* Catch highly unlikely compression ratios so we don't allocate
+     some giant amount of memory for nothing. The max compression
+     factor 1032:1 comes from http://www.zlib.net/zlib_tech.html  */
+  if (unlikely (size_out / 1032 > size_in))
+    {
+      __libelf_seterrno (ELF_E_INVALID_DATA);
+      return NULL;
+    }
+
   void *buf_out = malloc (size_out);
   if (unlikely (buf_out == NULL))
     {
Comment 2 Mark Wielaard 2017-04-03 21:54:34 UTC
commit 8dcc4bf791469a32c3a09ebcc23b309bf75c795f
Author: Mark Wielaard <mark@klomp.org>
Date:   Fri Mar 24 15:06:04 2017 +0100

    libelf: Check compression ratio before trying to allocate output buffer.
    
    The maximum compression factor (http://www.zlib.net/zlib_tech.html) is
    1032:1. Add a sanity check for that before trying to allocate lots of
    memory and trying to decompress lots of bogus data.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=21301
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>
Comment 3 Agostino Sarubbo 2017-04-10 07:31:50 UTC
Mitre assigned CVE-2017-7609 to this issue.