Bug 14855 - GDB crashes when processing DWARF information [dwarf2read.c] (malformed file_entry structure)
Summary: GDB crashes when processing DWARF information [dwarf2read.c] (malformed file_...
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: 7.5
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-11-19 01:15 UTC by Alejandro Hernandez H.
Modified: 2014-11-12 00:26 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alejandro Hernandez H. 2012-11-19 01:15:09 UTC
I was creating malformed ELF executables with my Frixyon fuzzer (an ELF file format fuzzer still in development) and I found a vulnerability in the DWARF information parsing which makes gdb unable to load an ELF executable for debugging due to a NULL pointer dereference. Evidently, it could be used to patch malicious executables (e.g. rootkits, 0day exploits, malware, etc.) not to allow to be analyzed by gdb.

I reproduced this flaw in the latest stable version (7.5) and the latest snapshot (18-nov-12).

In gdb-7.5/gdb/dwarf2read.c is the following data structure:
struct line_header
{
...
  unsigned int num_include_dirs, include_dirs_size;
  char **include_dirs;
...
  struct file_entry
  {
    char *name;
    unsigned int dir_index;
    unsigned int mod_time;
    unsigned int length;
    int included_p; /* Non-zero if referenced by the Line Number Program.  */
    struct symtab *symtab; /* The associated symbol table, if any.  */
  } *file_names;
}

The problem exists when trying to open a malformed ELF that contains a file_entry.dir_index > 0 and char **include_dirs pointing to NULL. The following lines illustrate this concept:

nitr0us@chatsubo:~$ gcc foo.c -o foo -ggdb
nitr0us@chatsubo:~$ ./foo
It could be a malicious program }:)
nitr0us@chatsubo:~$ objdump -s -j .debug_line ./foo

./foo:     file format elf32-i386

Contents of section .debug_line:
 0000 32000000 02001c00 00000101 fb0e0d00  2...............
 0010 01010101 00000001 00000100 666f6f2e  ............foo.
 0020 63000000 00000005 02d48304 081591bc  c...............
 0030 59020200 0101                        Y.....

The byte after "foo.c\00" corresponds to dir_index, so changing it to another value, for example, 0x0F, gdb crashes:

nitr0us@chatsubo:~$ objdump -s -j .debug_line ./dwarf_gdb_dir_index0F

./dwarf_gdb_dir_index0F:     file format elf32-i386

Contents of section .debug_line:
 0000 32000000 02001c00 00000101 fb0e0d00  2...............
 0010 01010101 00000001 00000100 666f6f2e  ............foo.
 0020 63000f00 00000005 02d48304 081591bc  c...............
 0030 59020200 0101                        Y.....

Now, debugging gdb trying to open that malformed file:

nitr0us@chatsubo:~$ gdb -q gdb-7.5/gdb/gdb
Reading symbols from /home/nitr0us/gdb-7.5/gdb/gdb...done.
(gdb) r -q ./dwarf_gdb_dir_index0F
Starting program: /home/nitr0us/gdb-7.5/gdb/gdb -q ./dwarf_gdb_dir_index0F
Reading symbols from /home/nitr0us/dwarf_gdb_dir_index0F...

Program received signal SIGSEGV, Segmentation fault.
0x081e87bd in psymtab_include_file_name (lh=0x8594420, file_index=0, pst=0x8583650, comp_dir=0x858362c "/home/nitr0us") at dwarf2read.c:13970
13970       dir_name = lh->include_dirs[fe.dir_index - 1];
(gdb) p/x fe
$1 = {name = 0x8583718, dir_index = 0xf, mod_time = 0x0, length = 0x0, included_p = 0x1, symtab = 0x0}
(gdb) p lh->include_dirs
$2 = (char **) 0x0
(gdb) x/i $eip
=> 0x81e87bd <psymtab_include_file_name+111>:   mov    (%eax),%eax
(gdb) i r $eax
eax            0x38     56


The root cause of the problem is that there's no validation in the line 13970 of gdb-7.5/gdb/dwarf2read.c to verify if include_dirs is different from NULL before referencing it:

  if (fe.dir_index)
    dir_name = lh->include_dirs[fe.dir_index - 1];

This same problem exists in different points of the code:
Line 7777  setup_type_unit_groups()
Line 14085 dwarf_decode_lines_1()
Line 14265 dwarf_decode_lines_1()
Line 14395 dwarf_decode_lines()
Line 16778 file_full_name()

Best Regards !