2017-01-27 4 views
0

Я пытаюсь изменить адрес возврата в стеке в обработчике ошибок сегмента, чтобы он пропускал инструкцию по сбою. Тем не менее, я получаю ошибку сегмента, когда я пытаюсь изменить обратный адрес, если я не вызываю обработчик сигнала напрямую.Различия в стеке между обработчиком сигнала, вызываемым напрямую, и raise()?

gdb не подходит для отладки, когда программа выполняет segfault, но когда я делаю info frame Я вижу, что после segfault есть «уровень кадра 2», а не «уровень кадра 0»? Я не знаю, где GDB получает эту информацию, потому что, когда я пытаюсь x/12xw $ebp или как бы много слов, я не вижу обратный адрес main() ...

Скомпилировано с -m32 -z execstack -fno-stack- протектор на CentOS Linux

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

void segment_fault_handler(int signum) 
{ 
    char* ret = (char*)(&signum)-4; 
    *(ret) += 8; 
} 

int main() 
{ 
    int phail = 0; 

    signal(SIGSEGV, segment_fault_handler); 

    segment_fault_handler(7); //Only by using this can I skip the next instruction 

    phail = *((int *) 0); 

    printf("Win!\n"); 

    return 0; 
} 

причина, по которой я увеличиваю на 8, потому что команда phail в main() составляет 8 байт:

0x080484e2 <+37>: movl $0x7,(%esp) 
0x080484e9 <+44>: call 0x8048480 <segment_fault_handler> 
0x080484ee <+49>: mov $0x0,%eax 
0x080484f3 <+54>: mov (%eax),%eax 
0x080484f5 <+56>: mov %eax,0x1c(%esp) 
0x080484f9 <+60>: movl $0x80485b4,(%esp) 
0x08048500 <+67>: call 0x8048350 <[email protected]> 

мне нужно увеличить смещение немного ли? Является ли мой метод доступа к стеку (который, как мне кажется, соответствует EBP + 4), необходимо изменить при работе с ситуацией сбоя сегмента?

+1

Вам необходимо изменить сохраненный ПК в структуре 'ucontext_t', переданный обработчику, * не * непосредственный обратный адрес функции обработки сигналов. (И * не * вызывайте его напрямую.) Пример программы на странице https://stackoverflow.com/questions/5119288/getting-fault-address-that-generated-a-unix-signal/5120984 показывает, как получить доступ к 'ucontext_t'. – zwol

ответ

0

Регистрация обработчика сигналов с sigaction, не signal и использовать SA_SIGINFO флаг, чтобы получить siginfo_t, описывающий причину сигнала. Это позволит вам обрабатывать SIGSEGV, вызванные ошибкой, отличной от той, которая указана явно raise d или отправлена ​​kill, sigqueue и т. Д. Это также дает вам ucontext_t, необходимый для проверки состояния во время сбоя и, при необходимости, его изменения перед возвратом.

BTW, в общем signal это плохая идея использовать в любом случае, потому что это не указано, установлен ли флаг SA_RESTART - и вы почти всегда хотите SA_RESTART. Получите привычку использовать sigaction и обрабатывая signal как устаревший.

Смежные вопросы