Bug 1680675 (CVE-2019-9077)

Summary: CVE-2019-9077 binutils: heap-based buffer overflow in function process_mips_specific in readelf.c
Product: [Other] Security Response Reporter: Dhananjay Arunesh <darunesh>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: abhgupta, dbaker, dvlasenk, fweimer, jakub, jokerman, law, mprchlik, nickc, ohudlick, sipoyare, sthangav, trankin
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-05-20 21:19:09 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1680676, 1691110, 1691111    
Bug Blocks: 1680680    

Description Dhananjay Arunesh 2019-02-25 13:55:47 UTC
An issue was discovered in GNU Binutils 2.32. It is a heap-based buffer overflow in process_mips_specific in readelf.c via a malformed MIPS option section.

Reference:
https://sourceware.org/bugzilla/show_bug.cgi?id=24243

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

Affects: fedora-all [bug 1680676]

Comment 2 Scott Gayou 2019-03-20 20:58:10 UTC
Vulnerable.

```
Breakpoint 2, process_mips_specific (file=file@entry=0x681000) at readelf.c:14688
(gdb) print sect->sh_size
$1 = 1
(gdb) print sizeof (* eopt)
$2 = 8
```

size should not be < sizeof the *eopt according to the patch. Looks like we're passing in a small mips option section size.

Comment 3 Scott Gayou 2019-03-20 20:58:40 UTC
```
==28071== Memcheck, a memory error detector
==28071== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28071== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==28071== Command: readelf -a poc
==28071== 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 2d 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x70000029
  Start of program headers:          52 (bytes into file)
  Start of section headers:          164 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         2
  Size of section headers:           40 (bytes)
  Number of section headers:         4
  Section header string table index: 3
readelf: poc: Warning: Section 1 has an out of range sh_link value of 127

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00001000 000000 000000 00      0   0  0
  [ 1] .text             MIPS_OPTIONS    08048074 000074 000001 00  AX 127   0  4
readelf: poc: Warning: section 1: sh_link value of 127 is larger than the number of sections
  [ 2] .data             LOUSER+0x5dff00 08000000 000080 00000d 00 WAop  0 57087  4
  [ 3] .shstrtab         STRTAB          00000000 00008c 000017 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  DYNAMIC        0x000000 0x08048000 0x08048000 0x00090 0x00080 R E 0x1000
readelf: poc: Error: no .dynamic section in the dynamic segment
  LOAD           0x17000080 0x08049080 0x08049080 0x0000c 0x0000c RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     
  Tag        Type                         Name/Value
 0x464c457f (<unknown>: 464c457f)        0x10101
 0x00002d00 (<unknown>: 2d00)            0x0
 0x00080002 (<unknown>: 80002)           0x1
 0x70000029 (MIPS_OPTIONS)               0x34
 0x000000a4 (<unknown>: a4)              0x0
 0x00200034 (<unknown>: 200034)          0x280002
 0x00030004 (<unknown>: 30004)           0x2
 0x00000000 (NULL)                       0x8048000

There are no relocations in this file.

The decoding of unwind sections for machine type MIPS R3000 is not currently supported.

No version information found in this file.
readelf: poc: Warning: Virtual address 0x34 not located in any PT_LOAD segment.
==28071== Invalid write of size 1
==28071==    at 0x4204F1: process_mips_specific (readelf.c:14710)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540de01 is 0 bytes after a block of size 1 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x43B167: xmalloc (xmalloc.c:148)
==28071==    by 0x420469: process_mips_specific (readelf.c:14692)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x4386B8: byte_get_little_endian (elfcomm.c:140)
==28071==    by 0x4204F9: process_mips_specific (readelf.c:14711)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540ddb3 is 1 bytes after a block of size 2 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x4052AE: get_data (readelf.c:391)
==28071==    by 0x42043D: process_mips_specific (readelf.c:14688)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x4386BC: byte_get_little_endian (elfcomm.c:139)
==28071==    by 0x4204F9: process_mips_specific (readelf.c:14711)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540ddb2 is 0 bytes after a block of size 2 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x4052AE: get_data (readelf.c:391)
==28071==    by 0x42043D: process_mips_specific (readelf.c:14688)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid write of size 2
==28071==    at 0x4204FE: process_mips_specific (readelf.c:14711)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540de02 is 1 bytes after a block of size 1 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x43B167: xmalloc (xmalloc.c:148)
==28071==    by 0x420469: process_mips_specific (readelf.c:14692)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x4386F0: byte_get_little_endian (elfcomm.c:149)
==28071==    by 0x42050C: process_mips_specific (readelf.c:14712)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540ddb5 is 3 bytes after a block of size 2 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x4052AE: get_data (readelf.c:391)
==28071==    by 0x42043D: process_mips_specific (readelf.c:14688)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x4386F4: byte_get_little_endian (elfcomm.c:150)
==28071==    by 0x42050C: process_mips_specific (readelf.c:14712)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540ddb6 is 4 bytes after a block of size 2 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x4052AE: get_data (readelf.c:391)
==28071==    by 0x42043D: process_mips_specific (readelf.c:14688)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x438704: byte_get_little_endian (elfcomm.c:148)
==28071==    by 0x42050C: process_mips_specific (readelf.c:14712)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540ddb4 is 2 bytes after a block of size 2 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x4052AE: get_data (readelf.c:391)
==28071==    by 0x42043D: process_mips_specific (readelf.c:14688)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x43870A: byte_get_little_endian (elfcomm.c:151)
==28071==    by 0x42050C: process_mips_specific (readelf.c:14712)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540ddb7 is 5 bytes after a block of size 2 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x4052AE: get_data (readelf.c:391)
==28071==    by 0x42043D: process_mips_specific (readelf.c:14688)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid read of size 1
==28071==    at 0x42050D: process_mips_specific (readelf.c:14715)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540de01 is 0 bytes after a block of size 1 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x43B167: xmalloc (xmalloc.c:148)
==28071==    by 0x420469: process_mips_specific (readelf.c:14692)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
==28071== Invalid write of size 8
==28071==    at 0x420511: process_mips_specific (readelf.c:14712)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071==  Address 0x540de08 is 7 bytes after a block of size 1 alloc'd
==28071==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==28071==    by 0x43B167: xmalloc (xmalloc.c:148)
==28071==    by 0x420469: process_mips_specific (readelf.c:14692)
==28071==    by 0x4244B7: process_arch_specific (readelf.c:16324)
==28071==    by 0x4244B7: process_object (readelf.c:16528)
==28071==    by 0x40217C: process_file (readelf.c:16905)
==28071==    by 0x40217C: main (readelf.c:16979)
==28071== 
readelf: poc: Error: Invalid size (0) for MIPS option
==28071== 
==28071== HEAP SUMMARY:
==28071==     in use at exit: 3 bytes in 2 blocks
==28071==   total heap usage: 124 allocs, 122 frees, 15,396 bytes allocated
==28071== 
==28071== LEAK SUMMARY:
==28071==    definitely lost: 3 bytes in 2 blocks
==28071==    indirectly lost: 0 bytes in 0 blocks
==28071==      possibly lost: 0 bytes in 0 blocks
==28071==    still reachable: 0 bytes in 0 blocks
==28071==         suppressed: 0 bytes in 0 blocks
==28071== Rerun with --leak-check=full to see details of leaked memory
==28071== 
==28071== For counts of detected and suppressed errors, rerun with: -v
==28071== ERROR SUMMARY: 11 errors from 10 contexts (suppressed: 0 from 0)
```

Comment 4 Scott Gayou 2019-03-20 21:36:40 UTC
Red Hat Enterprise Linux 6 segfaults on the same test.

Comment 8 Product Security DevOps Team 2020-05-20 21:19:09 UTC
This bug is now closed. Further updates for individual products will be reflected on the CVE page(s):

https://access.redhat.com/security/cve/cve-2019-9077