Bug 24075

Summary: Program Crash due to buffer over-read in ebl_object_note function in eblobjnote.c in libebl.
Product: elfutils Reporter: wcventure <wcventure>
Component: backendsAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: critical CC: elfutils-devel, mark
Priority: P1    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: POC1
POC2
Regressiong_POC

Description wcventure 2019-01-09 11:33:34 UTC
Created attachment 11523 [details]
POC1

Hi there,

Our fuzzer caught Pointer Deference problem in eu-readelf of the latest elfutils-0.174 code base, this inputs will cause the segment faults and I have confirmed them with address sanitizer too. Please use the "./eu-readelf -a $POC"to reproduce the bug. If you have any questions, please let me know.

This problem is in the code as fllow, it seem like a use-after-fee problem.

> size_t i;
> for (i = 0; i < prop.pr_datasz - 1; i++)
> 	printf ("%02" PRIx8 " ", (uint8_t) desc[i]);

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>
Comment 1 wcventure 2019-01-09 11:33:58 UTC
Created attachment 11524 [details]
POC2

The ASAN dumps the stack trace as follows:

> =================================================================
> ==20499==ERROR: AddressSanitizer: unknown-crash on address 0x7f908068e000 at pc 0x000000577730 bp 0x7ffd5103ba10 sp 0x7ffd5103ba00
> READ of size 1 at 0x7f908068e000 thread T0
>     #0 0x57772f in ebl_object_note /elfutils/libebl/eblobjnote.c:488
>     #1 0x4a06f3 in handle_notes_data /elfutils/src/readelf.c:12251
>     #2 0x4c5b47 in handle_notes /elfutils/src/readelf.c:12315
>     #3 0x4c5b47 in process_elf_file /elfutils/src/readelf.c:1000
>     #4 0x4c5b47 in process_dwflmod /elfutils/src/readelf.c:760
>     #5 0x7f907f1e9e9c in dwfl_getmodules /elfutils/libdwfl/dwfl_getmodules.c:86
>     #6 0x41399c in process_file /elfutils/src/readelf.c:868
>     #7 0x405df6 in main /elfutils/src/readelf.c:350
>     #8 0x7f907e6ff82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
>     #9 0x406ef8 in _start (/elfutils/build/bin/eu-readelf+0x406ef8)
> 
> Address 0x7f908068e000 is a wild pointer.
> SUMMARY: AddressSanitizer: unknown-crash /elfutils/libebl/eblobjnote.c:488 in ebl_object_note
> Shadow bytes around the buggy address:
>   0x0ff2900c9bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0ff2900c9bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0ff2900c9bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0ff2900c9be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0ff2900c9bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> =>0x0ff2900c9c00:[fe]fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0ff2900c9c10: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0ff2900c9c20: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0ff2900c9c30: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0ff2900c9c40: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0ff2900c9c50: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
> 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
>   Freed heap region:       fd
>   Stack left redzone:      f1
>   Stack mid redzone:       f2
>   Stack right redzone:     f3
>   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
> ==20499==ABORTING
Comment 2 Mark Wielaard 2019-01-15 13:16:58 UTC
*** Bug 24081 has been marked as a duplicate of this bug. ***
Comment 3 Mark Wielaard 2019-01-16 11:09:11 UTC
(In reply to wcventure from comment #0)

> Our fuzzer caught Pointer Deference problem in eu-readelf of the latest
> elfutils-0.174 code base, this inputs will cause the segment faults and I
> have confirmed them with address sanitizer too. Please use the "./eu-readelf
> -a $POC"to reproduce the bug. If you have any questions, please let me know.

This code was introduced in 0.175 and not present in 0.174.
Confirmed by running the reproducer under valgrind.
 
> This problem is in the code as fllow, it seem like a use-after-fee problem.
> 
> > size_t i;
> > for (i = 0; i < prop.pr_datasz - 1; i++)
> > 	printf ("%02" PRIx8 " ", (uint8_t) desc[i]);

Yes, this over-reads the buffer because pr_datasz isn't checked.
Fixed as follows:

commit 012018907ca05eb0ab51d424a596ef38fc87cae1
Author: Mark Wielaard <mark@klomp.org>
Date:   Wed Jan 16 11:57:35 2019 +0100

    libebl: Check GNU property note pr_datasz fits inside note description.
    
    Before printing the data values, make sure pr_datasz doesn't go beyond
    the end of the note description data.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=24075
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>

diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 0174f33..77c2274 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,7 @@
+2019-01-16  Mark Wielaard  <mark@klomp.org>
+
+       * eblobjnte.c (ebl_object_note): Check pr_datasz isn't too large.
+
 2018-12-02  Mark Wielaard  <mark@klomp.org>
 
        * eblobjnte.c (ebl_object_note): For GNU_PROPERTY_STACK_SIZE use
diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c
index c19ea37..9094715 100644
--- a/libebl/eblobjnote.c
+++ b/libebl/eblobjnote.c
@@ -350,6 +350,13 @@ ebl_object_note (Ebl *ebl, uint32_t namesz, const char *name, uint32_t type,
                  desc += 8;
                  descsz -= 8;
 
+                 if (prop.pr_datasz > descsz)
+                   {
+                     printf ("BAD property datasz: %" PRId32 "\n",
+                             prop.pr_datasz);
+                     return;
+                   }
+
                  int elfclass = gelf_getclass (ebl->elf);
                  char *elfident = elf_getident (ebl->elf, NULL);
                  GElf_Ehdr ehdr;
Comment 4 wcventure 2019-01-26 08:04:34 UTC
Regression Testing:

I have done regression testing.
This problem can be broken again!

Here is the POC file.


The Commit ID I used:

> commit a17c2c0917901ffa542ac4d3e327d46742219e04
> Author: Mark Wielaard <mark@klomp.org>
> Date:   Tue Jan 22 15:55:18 2019 +0100
> 
>     readelf: Don't go past end of line data reading unknown opcode parameters.
> 
>     https://sourceware.org/bugzilla/show_bug.cgi?id=24116
> 
>     Signed-off-by: Mark Wielaard <mark@klomp.org>


ASAN trace:

> ==22829==ERROR: AddressSanitizer: unknown-crash on address 0x7f07d1c81000 at pc 0x0000004c0857 bp 0x7ffc6580df50 sp 0x7ffc6580df40
READ of size 1 at 0x7f07d1c81000 thread T0
>     #0 0x4c0856 in ebl_object_note /home/wencheng/Experiment/elfutils/libebl/eblobjnote.c:495
>     #1 0x452e0f in handle_notes_data /home/wencheng/Experiment/elfutils/src/readelf.c:12256
>     #2 0x465ec3 in handle_notes /home/wencheng/Experiment/elfutils/src/readelf.c:12320
>     #3 0x465ec3 in process_elf_file /home/wencheng/Experiment/elfutils/src/readelf.c:1000
>     #4 0x465ec3 in process_dwflmod /home/wencheng/Experiment/elfutils/src/readelf.c:760
>     #5 0x7f07d0893961 in dwfl_getmodules /home/wencheng/Experiment/elfutils/libdwfl/dwfl_getmodules.c:86
>     #6 0x40d035 in process_file /home/wencheng/Experiment/elfutils/src/readelf.c:868
>     #7 0x40579e in main /home/wencheng/Experiment/elfutils/src/readelf.c:350
>     #8 0x7f07cff1882f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
>     #9 0x406428 in _start (/home/wencheng/Experiment/elfutils/build/bin/eu-readelf+0x406428)
> 
> Address 0x7f07d1c81000 is a wild pointer.
> SUMMARY: AddressSanitizer: unknown-crash /home/wencheng/Experiment/elfutils/libebl/eblobjnote.c:495 in ebl_object_note
> Shadow bytes around the buggy address:
>   0x0fe17a3881b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0fe17a3881c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0fe17a3881d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0fe17a3881e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>   0x0fe17a3881f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> =>0x0fe17a388200:[fe]fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0fe17a388210: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0fe17a388220: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0fe17a388230: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0fe17a388240: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>   0x0fe17a388250: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
> 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
>   Freed heap region:       fd
>   Stack left redzone:      f1
>   Stack mid redzone:       f2
>   Stack right redzone:     f3
>   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
> ==22829==ABORTING
Comment 5 wcventure 2019-01-26 08:06:21 UTC
Created attachment 11573 [details]
Regressiong_POC
Comment 6 wcventure 2019-01-29 11:17:32 UTC
CVE-2019-7146
Comment 7 Mark Wielaard 2019-01-29 23:09:54 UTC
Nice find. The property data is padded and we also must make sure that the extra padding fits the note description.

commit cd7ded3df43f655af945c869976401a602e46fcd (HEAD -> master)
Author: Mark Wielaard <mark@klomp.org>
Date:   Wed Jan 30 00:04:11 2019 +0100

    libebl: Check GNU property note data padding fits inside note.
    
    The GNU property note data is padded. Make sure the extra padding
    still fits in the note description.
    
    https://sourceware.org/bugzilla/show_bug.cgi?id=24075
    
    Signed-off-by: Mark Wielaard <mark@klomp.org>