gfriloux/botman

Segfault in GDB module.

Closed this issue · 2 comments

In some cases, GDB will fail to extract backtrace.
A case happenned here where GDB will even segfault trying to read the coredump (maybe were we trying to read it while being written ?).

So we had a case where gdb module crashed while trying to retrieve backtrace.
Here is the backtrace created :

(gdb) bt
# 0 0x0000000806c2ed1c in _backtrace_data (data=0x805bf3840, type=, > event=0x805bb3d40) at src/modules/gdb/backtrace.c:51
# 1 0x000000080082cb8d in _ecore_call_handler_cb (func=0x806c2ecd0 <_backtrace_data>, data=0x805bf3840, type=8, event=0x805bb3d40) at ecore_private.h:335
# 2 0x000000080082c936 in _ecore_event_call () at ecore_events.c:559
# 3 0x00000008008337b5 in _ecore_main_loop_iterate_internal (once_only=0) at ecore_main.c:1936
# 4 0x00000008008338c4 in ecore_main_loop_begin () at ecore_main.c:960
# 5 0x00000000004018b5 in main (argc=, argv=) at src/bin/botman/main.c:142

(gdb) p *(Ecore_Exe_Event_Data *)event
$3 = {
exe = 0x8059128e0,
data = 0x805b56d28,
size = 7,
lines = 0x0
}
(gdb) x/7c 0x805b56d28
0x805b56d28: 79 'O' 78 'N' 76 'L' 73 'I' 78 'N' 69 'E' 10 '\n'

We obviously have a problem here.
To mitigate the issue, we should check event->lines that is NULL.

here is the faulting code :

Eina_Bool
_backtrace_data(void *data,
                int type EINA_UNUSED,
                void *event)
{
   Backtrace *b = data;
   Ecore_Exe_Event_Data *d = (Ecore_Exe_Event_Data *)event;
   unsigned int i;

   DBG("b[%p]", b);

   for (i = 0; d->lines[i].line; i++)
     {
        eina_array_push(b->lines, strdup(d->lines[i].line));
     }
   return EINA_TRUE;
}

It is crashing on the for loop, doing lines[0].line while lines is a NULL pointer.

So there is a problem in this module.
Any ecore_exe event will make _backtrace_data() to be called and try to extract a backtrace from it.

There is a missing data check !

So there are two possible scenarios there :

  • GDB fails to extract backtrace and even segfaults doing it, resulting in no data to be read.
  • We try to retrieve a backtrace at the exact same time another module is running a command, thinking its backtrace data to handle !

The most usual scenari is having GDB module to run GDB and recieve ECORE_EXE_EVENT_DATA from other modules.

Another server had botman to segfault from receiving the raid status inside the GDB module.

To reproduce, you need to have an app to generate a coredump, and by the same time, having another botman module to run a command using ecore_exe.
As GDB module wont listen to ecore_exe events while not getting a backtrace, this is truelly a race.