paulfloyd / freebsd_valgrind

Git repo used to Upstream the FreeBSD Port of Valgrind
GNU General Public License v2.0
15 stars 4 forks source link

SIGSEGVs in signal handlers [amd64] #117

Closed paulfloyd closed 4 years ago

paulfloyd commented 4 years ago

A quick grep of the diff files shows

./memcheck/tests/sigaltstack.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./memcheck/tests/signal2.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/amd64/ssse3_misaligned.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/faultstatus.stderr.diff-s390x:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/faultstatus.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/sigstackgrowth.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/mq.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/pending.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./none/tests/coolo_sigaction.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./drd/tests/sigaltstack.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./gdbserver_tests/mcsignopass.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)
./gdbserver_tests/mcsigpass.stderr.diff:+Process terminating with default action of signal 11 (SIGSEGV)

From what I can tell the common factor for all of these is that they setup a signal handler, the handler contains some sort of printf and when printf is called there is a SIGSEGV.

To debug this I built libc with "-g -O0" and used the following code (run with and without an argument for comparing crash/no crash).

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static int something;

void handle_no_printf(int sig)
{
    ++something;
}

void handle_printf(int sig)
{
    printf("In handle_printf\n");
}

int main(int argc, char** argv)
{
   // Set a signal handler for SIGUSR1
   if (argc >= 2)
   {    
      signal(SIGUSR1, &handle_printf);
   }
   else
   {
       signal(SIGUSR1, &handle_no_printf);
   }

  printf("before raise\n");

  raise(SIGUSR1);

  printf("back in main, something is %d\n", something);

  return 0;
}

I ran this under vgdb and I saw

0x20130b <handle_printf+11>     movabs $0x200585,%rdi
0x201315 <handle_printf+21>     mov    $0x0,%al
0x201317 <handle_printf+23>     callq  0x201470 <printf@plt>

Address 0x200585 does point to the "In handle printf\n" string. This all looks OK.

But in printf

printf (fmt=0xee22cdaf <error: Cannot access memory at address 0xee22cdaf>) at stdio/printf.c:52

0xee22cdaf ??? Looks like junk memory.

paulfloyd commented 4 years ago

Fixed with push (change seen in freebsd-hackers mail archive!) To https://github.com/paulfloyd/freebsd_valgrind.git 56f677589..8002159ac freebsd -> freebsd