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
Created binutils tracking bugs for this issue: Affects: fedora-all [bug 1680676]
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.
``` ==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) ```
Red Hat Enterprise Linux 6 segfaults on the same test.
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