[Bug c++/87350] New: NULL-Pointer problem in cplus-dem.c when executing program c++filt

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] New: NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

            Bug ID: 87350
           Summary: NULL-Pointer problem in cplus-dem.c when executing
                    program c++filt
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wcventure at 126 dot com
  Target Milestone: ---

Hi,

Our fuzzer caught NULL-Pointer problems in c++filt of the latest binutils code
base, those inputs will cause the segment faults and I have confirmed them with
address sanitizer.
Please use the “c++filt < $POC ” to reproduce the bug.
Please check it and debug it. Thank you.


The ASAN dumps the stack trace as follows on POC1:
https://github.com/ntu-sec/pocs/blob/master/binutils-aff4a119/crashes/npd_r_cplus-dem.c:1345_1.err.txt

AddressSanitizer:DEADLYSIGNAL
=================================================================
==23610==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x7f67702435a1 bp 0x7ffe2a376680 sp 0x7ffe2a375e08 T0)
==23610==The signal is caused by a READ memory access.
==23610==Hint: address points to the zero page.
    #0 0x7f67702435a0
/build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:59
    #1 0x49728c in __interceptor_strlen.part.30
(/home/hongxu/FOT/binutils/BUILD/install/bin/c++filt+0x49728c)
    #2 0x8c9caa in work_stuff_copy_to_from
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:1345:17
    #3 0x8c553c in iterate_demangle_function
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:2731:3
    #4 0x8b77ec in demangle_prefix
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:2971:14
    #5 0x8b2d00 in internal_cplus_demangle
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:1253:14
    #6 0x8afe53 in cplus_demangle
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:918:9
    #7 0x513dd5 in demangle_it
/home/hongxu/FOT/binutils/BUILD/binutils/../../binutils/cxxfilt.c:62:12
    #8 0x5139c9 in main
/home/hongxu/FOT/binutils/BUILD/binutils/../../binutils/cxxfilt.c:276:4
    #9 0x7f67700d6b96 in __libc_start_main
/build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #10 0x41a989 in _start
(/home/hongxu/FOT/binutils/BUILD/install/bin/c++filt+0x41a989)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:59
==23610==ABORTING


The ASAN dumps the stack trace as follows on POC2:
https://github.com/ntu-sec/pocs/blob/master/binutils-aff4a119/crashes/npd_r_cplus-dem.c:1360_1.err.txt

AddressSanitizer:DEADLYSIGNAL
=================================================================
==23847==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x0000008ca218 bp 0x7ffe44bfad50 sp 0x7ffe44bfaa10 T0)
==23847==The signal is caused by a READ memory access.
==23847==Hint: address points to the zero page.
    #0 0x8ca217 in work_stuff_copy_to_from
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:1360:25
    #1 0x8c553c in iterate_demangle_function
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:2731:3
    #2 0x8b77ec in demangle_prefix
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:2971:14
    #3 0x8b2d00 in internal_cplus_demangle
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:1253:14
    #4 0x8afe53 in cplus_demangle
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:918:9
    #5 0x513dd5 in demangle_it
/home/hongxu/FOT/binutils/BUILD/binutils/../../binutils/cxxfilt.c:62:12
    #6 0x5139c9 in main
/home/hongxu/FOT/binutils/BUILD/binutils/../../binutils/cxxfilt.c:276:4
    #7 0x7ff52abf2b96 in __libc_start_main
/build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #8 0x41a989 in _start
(/home/hongxu/FOT/binutils/BUILD/install/bin/c++filt+0x41a989)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/home/hongxu/FOT/binutils/BUILD/libiberty/../../libiberty/cplus-dem.c:1360:25
in work_stuff_copy_to_from
==23847==ABORTING
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

--- Comment #1 from Cheng Wen <wcventure at 126 dot com> ---
Created attachment 44714
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44714&action=edit
POC1
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

--- Comment #2 from Cheng Wen <wcventure at 126 dot com> ---
Created attachment 44715
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44715&action=edit
POC2
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2018-09-18
     Ever confirmed|0                           |1

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Cheng Wen from comment #1)
> Created attachment 44714 [details]
> POC1

You've uploaded two complete HTML pages saved from github, but the mangled name
that crash are just:

_GLOBAL_$D$__tf30___0__
__thunk_0__0__$__H1



$ echo '_GLOBAL_$D$__tf30___0__' | /tmp/binutils/bin/c++filt
ASAN:DEADLYSIGNAL
=================================================================
==6977==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x7f5fbbb47f31 bp 0x7fff4a202c20 sp 0x7fff4a202398 T0)
==6977==The signal is caused by a READ memory access.
==6977==Hint: address points to the zero page.
    #0 0x7f5fbbb47f30 in __strlen_avx2 (/lib64/libc.so.6+0x155f30)
    #1 0x7f5fbbffd27b  (/lib64/libasan.so.4+0x5127b)
    #2 0x497e34 in work_stuff_copy_to_from
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:1345
    #3 0x49cdd8 in iterate_demangle_function
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:2731
    #4 0x49d962 in demangle_prefix
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:2971
    #5 0x49d962 in internal_cplus_demangle
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:1253
    #6 0x498860 in cplus_demangle
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:918
    #7 0x402ea5 in demangle_it (/tmp/binutils/bin/c++filt+0x402ea5)
    #8 0x4037af in main (/tmp/binutils/bin/c++filt+0x4037af)
    #9 0x7f5fbba12fe9 in __libc_start_main (/lib64/libc.so.6+0x20fe9)
    #10 0x402d29 in _start (/tmp/binutils/bin/c++filt+0x402d29)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib64/libc.so.6+0x155f30) in __strlen_avx2
==6977==ABORTING
wraith:tmp$ echo '__thunk_0__0__$__H1' | /tmp/binutils/bin/c++filt
ASAN:DEADLYSIGNAL
=================================================================
==6981==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x000000497f27 bp 0x7ffc897891e0 sp 0x7ffc89789170 T0)
==6981==The signal is caused by a READ memory access.
==6981==Hint: address points to the zero page.
    #0 0x497f26 in work_stuff_copy_to_from
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:1358
    #1 0x49cdd8 in iterate_demangle_function
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:2731
    #2 0x49d962 in demangle_prefix
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:2971
    #3 0x49d962 in internal_cplus_demangle
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:1253
    #4 0x498860 in cplus_demangle
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:918
    #5 0x402ea5 in demangle_it (/tmp/binutils/bin/c++filt+0x402ea5)
    #6 0x4037af in main (/tmp/binutils/bin/c++filt+0x4037af)
    #7 0x7ff5a9a18fe9 in __libc_start_main (/lib64/libc.so.6+0x20fe9)
    #8 0x402d29 in _start (/tmp/binutils/bin/c++filt+0x402d29)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/home/jwakely/src/binutils-gdb/libiberty/cplus-dem.c:1358 in
work_stuff_copy_to_from
==6981==ABORTING
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

--- Comment #4 from Cheng Wen <wcventure at 126 dot com> ---
Yes.

One input test case is "_GLOBAL_$D$__tf30___0__".
Another input test case is "__thunk_0__0__$__H1".

I see that you can you can reproduce this error. Do you know the reason for
this bug?
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

Bernhard Kaindl <bernhard.kaindl at thalesgroup dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bernhard.kaindl@thalesgroup
                   |                            |.com

--- Comment #5 from Bernhard Kaindl <bernhard.kaindl at thalesgroup dot com> ---
Simple observation from the asan traces, the source and a quick test:

iterate_demangle_function (struct work_stuff *work, ...
{
   [only cases for early returns here]

   work_stuff_copy_to_from (&work_init, work); <- SEGV on a member of work here

work_stuff_copy_to_from () is a dumb copy function which assumes that the
vectors it shall copy have been allocated:

void work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)

  [nothing relevant here]
  for... {
      int len = strlen (from->ktypevec[i]) + 1; <- SIGSEGV happens here bc
NULL.

I verified that function remember_Ktype() which does the all allocation of
work_stuff->ktypevec is never called by these POCs, hence ktypevec is still
NULL, causing the SIGSEGV.

iterate_demangle_function() itself is called from a rather complex function.

The only safe fix: Before copying work_stuff, check the work_stuff vectors to
be already. If not, return 0 -> no demangle.
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

--- Comment #6 from Bernhard Kaindl <bernhard.kaindl at thalesgroup dot com> ---
Created attachment 45167
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45167&action=edit
Safe fix: Before copying work, check if the vectors have been allocated. If
not, input wasn't valid.

Fixes CVE-2018-17794:

In cplus-dem.c in GNU libiberty, as distributed in GNU Binutils 2.31 (and all
prior versions) There is a NULL pointer dereference in work_stuff_copy_to_from
when called from iterate_demangle_function.

https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2018-17794

Safe fix: Before copying work, check if the vectors have been allocated.
If not, input wasn't valid. -- Bernhard Kaindl

diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 6d58bd899b..ab30cd5fd5 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -2723,6 +2723,11 @@ iterate_demangle_function (struct work_stuff *work,
const char **mangled,
       || strstr (scan + 2, "__") == NULL)
     return demangle_function_name (work, mangled, declp, scan);

+  /* Before copying work, check if the vectors have been allocated.
+     If not, our input isn't a valid mangled name and we'd sigseg then: */
+  if (!work->typevec || !work->ktypevec || !work->btypevec)
+    return 0;
+
   /* Save state so we can restart if the guess at the correct "__" was
      wrong.  */
   string_init (&decl_init);

It would be enough to check just for !work->typevec to fix this CVE, the others
are just related as work_stuff_copy_to_from() copies them in the same way as
ktypevec.

To be sure there is no oversight, proper review and testing would be in
required.
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

--- Comment #7 from Nick Clifton <nickc at gcc dot gnu.org> ---
Author: nickc
Date: Fri Dec  7 10:33:30 2018
New Revision: 266886

URL: https://gcc.gnu.org/viewcvs?rev=266886&root=gcc&view=rev
Log:
Add a recursion limit to libiberty's demangling code.  The limit is enabled by
default, but can be disabled via a new demangling option.

include * demangle.h (DMGL_NO_RECURSE_LIMIT): Define.
        (DEMANGLE_RECURSION_LIMIT): Define

        PR 87681
        PR 87675
        PR 87636
        PR 87350
        PR 87335
libiberty * cp-demangle.h (struct d_info): Add recursion_level field.
        * cp-demangle.c (d_function_type): Add recursion counter.
        If the recursion limit is reached and the check is not disabled,
        then return with a failure result.
        (cplus_demangle_init_info): Initialise the recursion_level field.
        (d_demangle_callback): If the recursion limit is enabled, check
        for a mangled string that is so long that there is not enough
        stack space for the local arrays.
        * cplus-dem.c (struct work): Add recursion_level field.
        (squangle_mop_up): Set the numb and numk fields to zero.
        (work_stuff_copy_to_from): Handle the case where a btypevec or
        ktypevec field is NULL.
        (demangle_nested_args): Add recursion counter.  If
        the recursion limit is not disabled and reached, return with a
        failure result.

Modified:
    trunk/include/ChangeLog
    trunk/include/demangle.h
    trunk/libiberty/ChangeLog
    trunk/libiberty/cp-demangle.c
    trunk/libiberty/cp-demangle.h
    trunk/libiberty/cplus-dem.c
Reply | Threaded
Open this post in threaded view
|

[Bug c++/87350] NULL-Pointer problem in cplus-dem.c when executing program c++filt

kargl at gcc dot gnu.org
In reply to this post by kargl at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87350

Nick Clifton <nickc at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |nickc at gcc dot gnu.org
         Resolution|---                         |FIXED

--- Comment #8 from Nick Clifton <nickc at gcc dot gnu.org> ---
Fixed by commit 266886