Heap corruption and crash reading syscall XML data

Dmitry Antipov
2017-10-17T10:07:13Z

HEAD at 0301ce1486b1450f219202677f30d0fa97335419,

configure --prefix=/home/dantipov/.local/gdb-8.0.50 --with-python=no --with-guile=no \
--disable-nls --disable-binutils --disable-gprof --disable-gold --disable-gas --disable-ld

$ ~/.local/gdb-8.0.50/bin/gdb
GNU gdb (GDB) 8.0.50.20171017-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) catch syscall [TAB]

==>

*** Error in `/home/dantipov/.local/gdb-8.0.50/bin/gdb': double free or corruption (!prev): 0x00000000025bce50 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7c8dc)[0x7ff7336848dc]
/lib64/libc.so.6(+0x87789)[0x7ff73368f789]
/lib64/libc.so.6(cfree+0x16e)[0x7ff7336950ee]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5aca4c]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x433c5c]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x439bf1]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7ace7b]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7aebc9]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7aed1f]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7af2de]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x55c235]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5afa69]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5afdcc]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5aff23]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5b03b3]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5b12a6]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x5b137e]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7c3bb7]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7c5504]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7c2c86]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7bcd26]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7bcb76]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7bc81b]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x7d55c4]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63cd82]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63cdde]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63d48b]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63b94c]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63bed7]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63adec]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x63ae24]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x6b5811]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x6b6b2c]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x6b6bf2]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x407a2e]
/lib64/libc.so.6(__libc_start_main+0xea)[0x7ff73362850a]
/home/dantipov/.local/gdb-8.0.50/bin/gdb[0x40793a]
[...memory map skipped...]

Backtrace:

#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007fc9cdeb54a0 in __GI_abort () at abort.c:89
#2 0x00007fc9cdef98e1 in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7fc9ce016140 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007fc9cdf04789 in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, str=0x7fc9ce016558 "double free or corruption (!prev)", action=<optimized out>)
at malloc.c:5077
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3873
#5 0x00007fc9cdf0a0ee in __GI___libc_free (mem=<optimized out>) at malloc.c:2947
#6 0x00000000005aca4c in xfree (ptr=0x1aeee50) at ../../gdb/common/common-utils.c:101
#7 0x0000000000433c5c in gdb::xfree_deleter<char>::operator() (this=0x7fff98a23c68, ptr=0x1aeee50 "8\213$\316\311\177") at ../../gdb/common/gdb_unique_ptr.h:34
#8 0x0000000000439bf1 in std::unique_ptr<char, gdb::xfree_deleter<char> >::reset (this=0x7fff98a23c68, __p=0x1aeee50 "8\213$\316\311\177")
at /usr/include/c++/7/bits/unique_ptr.h:376
#9 0x00000000007ace7b in xml_fetch_content_from_file (filename=0x92129a "syscalls/i386-linux.xml", baton=0x19c5370) at ../../gdb/xml-support.c:1042
#10 0x00000000007aebc9 in xml_init_syscalls_info (filename=0x92129a "syscalls/i386-linux.xml") at ../../gdb/xml-syscall.c:366
#11 0x00000000007aed1f in init_syscalls_info (gdbarch=0x1ad3f30) at ../../gdb/xml-syscall.c:398
#12 0x00000000007af2de in get_syscall_names (gdbarch=0x1ad3f30) at ../../gdb/xml-syscall.c:618
#13 0x000000000055c235 in catch_syscall_completer (cmd=0x1a7eef0, tracker=..., text=0x7fff98a23e4e "", word=0x7fff98a23e4e "") at ../../gdb/break-catch-syscall.c:585
#14 0x00000000005afa69 in complete_line_internal_normal_command (tracker=..., command=0x7fff98a23e40 "catch syscall ", word=0x7fff98a23e4e "", cmd_args=0x7fff98a23e4e "",
reason=handle_completions, c=0x1a7eef0) at ../../gdb/completer.c:1209
#15 0x00000000005afdcc in complete_line_internal_1 (tracker=..., text=0x1a71720 "", line_buffer=0x1adec50 "catch syscall ", point=14, reason=handle_completions)
at ../../gdb/completer.c:1372
#16 0x00000000005aff23 in complete_line_internal (tracker=..., text=0x1a71720 "", line_buffer=0x1adec50 "catch syscall ", point=14, reason=handle_completions)
at ../../gdb/completer.c:1443
#17 0x00000000005b03b3 in complete_line (tracker=..., text=0x1a71720 "", line_buffer=0x1adec50 "catch syscall ", point=14) at ../../gdb/completer.c:1558
#18 0x00000000005b12a6 in gdb_rl_attempted_completion_function_throw (text=0x1a71720 "", start=14, end=14) at ../../gdb/completer.c:2096
#19 0x00000000005b137e in gdb_rl_attempted_completion_function (text=0x1a71720 "", start=14, end=14) at ../../gdb/completer.c:2132
#20 0x00000000007c3bb7 in gen_completion_matches (text=0x1a71720 "", start=14, end=14, our_func=0x7c5df5 <rl_filename_completion_function>, found_quote=0, quote_char=0)
at ../../readline/complete.c:1081
#21 0x00000000007c5504 in rl_complete_internal (what_to_do=9) at ../../readline/complete.c:1849
#22 0x00000000007c2c86 in rl_complete (ignore=1, invoking_key=9) at ../../readline/complete.c:408
#23 0x00000000007bcd26 in _rl_dispatch_subseq (key=9, map=0xc639c0 <emacs_standard_keymap>, got_subseq=0) at ../../readline/readline.c:774
#24 0x00000000007bcb76 in _rl_dispatch (key=-840223077, map=0xc639c0 <emacs_standard_keymap>) at ../../readline/readline.c:724
#25 0x00000000007bc81b in readline_internal_char () at ../../readline/readline.c:552
#26 0x00000000007d55c4 in rl_callback_read_char () at ../../readline/callback.c:201
#27 0x000000000063cd82 in gdb_rl_callback_read_char_wrapper_noexcept () at ../../gdb/event-top.c:175
#28 0x000000000063cdde in gdb_rl_callback_read_char_wrapper (client_data=0x19c5bb0) at ../../gdb/event-top.c:192
#29 0x000000000063d48b in stdin_event_handler (error=0, client_data=0x19c5bb0) at ../../gdb/event-top.c:511
#30 0x000000000063b94c in handle_file_event (file_ptr=0x1adf690, ready_mask=1) at ../../gdb/event-loop.c:733
#31 0x000000000063bed7 in gdb_wait_for_event (block=1) at ../../gdb/event-loop.c:859
#32 0x000000000063adec in gdb_do_one_event () at ../../gdb/event-loop.c:347
#33 0x000000000063ae24 in start_event_loop () at ../../gdb/event-loop.c:371
#34 0x00000000006b5811 in captured_command_loop () at ../../gdb/main.c:324
#35 0x00000000006b6b2c in captured_main (data=0x7fff98a24400) at ../../gdb/main.c:1147
#36 0x00000000006b6bf2 in gdb_main (args=0x7fff98a24400) at ../../gdb/main.c:1163
#37 0x0000000000407a2e in main (argc=1, argv=0x7fff98a24508) at ../../gdb/gdb.c:32

It doesn't crash if 'text' buffer in xml_fetch_content_from_file () is large enough to avoid xrealloc (), e.g.

diff --git a/gdb/xml-support.c b/gdb/xml-support.c
index 76d03b90c7..4004f86e30 100644
--- a/gdb/xml-support.c
+++ b/gdb/xml-support.c
@@ -1016,7 +1016,7 @@ xml_fetch_content_from_file (const char *filename, void *baton)
return NULL;

/* Read in the whole file, one chunk at a time. */
- len = 4096;
+ len = 131072;
offset = 0;
gdb::unique_xmalloc_ptr<char> text ((char *) xmalloc (len));
while (1)

Dmitry