Bug 1680651 (CVE-2019-9070) - CVE-2019-9070 binutils: heap-based buffer over-read in function d_expression_1 in cp-demangle.c
Summary: CVE-2019-9070 binutils: heap-based buffer over-read in function d_expression_...
Keywords:
Status: CLOSED WONTFIX
Alias: CVE-2019-9070
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 1680652
Blocks: 1680680
TreeView+ depends on / blocked
 
Reported: 2019-02-25 13:17 UTC by Dhananjay Arunesh
Modified: 2019-09-29 15:08 UTC (History)
13 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-06-10 10:48:46 UTC


Attachments (Terms of Use)

Description Dhananjay Arunesh 2019-02-25 13:17:11 UTC
An issue was discovered in GNU libiberty, as distributed in GNU Binutils 2.32. It is a heap-based buffer over-read in d_expression_1 in cp-demangle.c after many recursive calls.

Reference:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89395

Comment 1 Dhananjay Arunesh 2019-02-25 13:17:24 UTC
Created binutils tracking bugs for this issue:

Affects: fedora-all [bug 1680652]

Comment 2 Scott Gayou 2019-03-13 14:10:08 UTC
Segfault on Red Hat Enterprise Linux 6. 7 seems to be okay.

```
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ba071a in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2681
2681	      if (d_peek_char (di) == 'I')
(gdb) bt
#0  0x00007ffff7ba071a in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2681
#1  0x00007ffff7ba09f8 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2741
#2  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
#3  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
#4  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
#5  0x00007ffff7ba09f8 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2741
#6  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
#7  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
#8  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
#9  0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737
```

Comment 3 Scott Gayou 2019-03-13 15:20:40 UTC
Red Hat Enterprise Linux 6:

```
   │1399    d_source_name (struct d_info *di)                            		  │
   │1400    {                                                                             │
   │1401      long len;                                                                   │
   │1402      struct demangle_component *ret;                                             │
   │1403                                                                                  │
   │1404      len = d_number (di);                                            		  │
  >│1405      if (len <= 0)

(gdb) print len
$13 = 7550956185914230101
```

Looks like d_number is returning junk in this case.

After this, `ret = d_identifier (di, len);` runs and presumably increments di->n len bytes.

```
(gdb) print di->n
$14 = 0xfffffffff85596f2 <Address 0xfffffffff85596f2 out of bounds>
```

Thus, next time di->n is used (as a string ptr I believe), a deference leads to a crash.

Comment 4 Scott Gayou 2019-03-13 15:40:57 UTC
Still unclear why I am unable to reproduce on later versions. It looks like the di advance function in RHEL7's version (and up) has support for a "checked" advance. It looks for a NULL character and aborts if it finds one.

I didn't see an abort signal raised though, so that doesn't seem to be the solution.


Note You need to log in before you can comment on or make changes to this bug.