나는 버그가있는 코드로 작업 중이며 충돌에 대한 자세한 정보를 얻기 위해 SIGSEGV 핸들러를 설치하려고합니다. 그러나 내 처리기가 호출되지 않은 것으로 나타났습니다.손상된 스택에 의해 트리거되었을 때 SIGSEGV 잡기
나는 이유를 찾고 있었고 손상된 스택 포인터 값과 관련이있는 것으로 보인다. 여기에 내가 확인하기 위해 쓴 몇 가지 개념 증명 코드입니다 :
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...
}
아이디어는 RSP를 0으로 설정하는 것입니다 (오프셋 무효) 다음 일을 위해 사용합니다. 그러나이 두 번째 SIGSEGV는 처리기에 의해 포착되지 않고 대신 프로세스를 종료합니다.
분명히 신호 처리기를 호출하려면 정상적인 스택 포인터가 있어야합니다.하지만 그 이유는 무엇입니까? 이것은 신호를 다루는 것에 반대하지 않습니까? 이 문제를 해결할 가능성은?
저는 Linux 버전 3.19.0-25-generic을 사용하고 있습니다. 대안 신호 스택 힙에 할당되고, sigaltstack(&ss,NULL)
을 사용하여 등록
#include <stdio.h>
#define __USE_GNU
#include <signal.h>
#include <stdlib.h>
#include <ucontext.h>
static long long int sbase;
static void catch_function(int sig, siginfo_t *info, void *cntxt)
{
puts("handler works");
/* reset RSP if invalid */
ucontext_t *uc_context = (ucontext_t *)cntxt;
if(!uc_context->uc_mcontext.gregs[REG_RSP])
{
puts("resetting RSP");
uc_context->uc_mcontext.gregs[REG_RSP] = sbase;
}
}
void main(int argc, char **argv)
{
/* RSP during main */
sbase = (long long int)&argv;
stack_t ss;
struct sigaction sa;
ss.ss_sp = malloc(SIGSTKSZ);
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
sigaltstack(&ss, NULL);
sa.sa_sigaction = (void *)catch_function;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
sigaction(SIGSEGV, &sa, NULL);
puts("testing handler");
raise(SIGSEGV);
puts("back");
__asm__ (
"xor %rax, %rax\n\t"
"mov %rax, %rsp\n\t"
"push %rax\n\t"
"pop %rax" );
puts("exiting.");
}
:
'sigaltstack()'. – EOF
@ EOF - 감사합니다. 그것은 유망 해 보인다. 성공하면 솔루션을 게시합니다. – HairyNopper
valgrind에서 프로그램을 실행할 수 있습니까? – bruceg