I've been working on some buggy code and wanted to install a SIGSEGV handler to get more information about the crash. However, I noticed that my handler is not invoked.
I've been looking for a reason and it seems it has to do with a corrupt stack pointer value (it's not getting masked for sure). Here's some proof-of-concept code I wrote up to verify:
static void catch_function(int sig, siginfo_t *info, void *cntxt)
{
puts("handler works");
}
void main(int argc, char **argv)
{
struct sigaction sa;
sa.sa_sigaction = (void *)catch_function;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_NODEFER ;
sigaction(SIGSEGV, &sa, NULL);
puts("testing handler");
raise(SIGSEGV);
puts("back");
__asm__ ( "xor %rax, %rax\n\t"
"mov %rax, %rsp\n\t"
"push 0"
);
// never reached...
}
The idea is to set RSP to 0 (invalid offset) and then use it for something. However, this second SIGSEGV will not be caught by the handler but instead terminates the process.
Apparently, invoking the signal handler needs a sane stack pointer to begin with -- but why? Isn't this against the idea of handling signals? Any chance of getting around this?
I'm running Linux version 3.19.0-25-generic.