Bug 21299 - heap-based buffer overflow in handle_gnu_hash (readelf.c)
Summary: heap-based buffer overflow in handle_gnu_hash (readelf.c)
Status: RESOLVED FIXED
Alias: None
Product: elfutils
Classification: Unclassified
Component: tools (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-24 09:09 UTC by Agostino Sarubbo
Modified: 2017-04-10 07:26 UTC (History)
2 users (show)

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


Attachments
stacktrace (4.33 KB, text/plain)
2017-03-24 09:09 UTC, Agostino Sarubbo
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Agostino Sarubbo 2017-03-24 09:09:12 UTC
Created attachment 9936 [details]
stacktrace

On elfutils-0.168:

# eu-readelf -a $FILE

READ of size 4 at 0x611000009ffc thread T0
    #0 0x421a8b in handle_gnu_hash /tmp/portage/dev-libs/elfutils-0.168/work/elfutils-0.168/src/readelf.c:3268

Compiled with: gcc-6.3.0

Reproducer:
https://github.com/asarubbo/poc/blob/master/00225-elfutils-heapoverflow-handle_gnu_hash

Stacktrace attached.
Comment 1 Mark Wielaard 2017-03-24 11:06:45 UTC
Thanks, it was an off-by-one sanity check.

diff --git a/src/readelf.c b/src/readelf.c
index 8d96ba3..490b6d5 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3263,7 +3263,7 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, 
            ++nsyms;
            if (maxlength < ++lengths[cnt])
              ++maxlength;
-           if (inner > max_nsyms)
+           if (inner >= max_nsyms)
              goto invalid_data;
          }
        while ((chain[inner++] & 1) == 0);

max_nsyms is the maximum number, but inner is a zero-based index.
Comment 2 Mark Wielaard 2017-04-03 21:43:51 UTC
commit 9d84fdd78705d7a1b9947a9f4ca77fbccdd76d4a
Author: Mark Wielaard <mark@klomp.org>
Date:   Fri Mar 24 12:15:02 2017 +0100

    readelf: Fix off by one sanity check in handle_gnu_hash.
    
    We sanity check to make sure we don't index outside the chain array
    by testing inner > max_nsyms. But inner is a zero-based index, while
    max_nsyms is the maximum number. Change the check to inner >= max_nsyms.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=21299
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>
Comment 3 Agostino Sarubbo 2017-04-10 07:26:30 UTC
Mitre assigned CVE-2017-7607 to this issue.