内存访问错误sys_rt_sigaction(信号处理程序)

时间:2017-02-21 00:03:38

标签: linux assembly x86-64 system-calls

在这篇Interfacing Linux Signals文章之后,我一直尝试在 amd64 中使用sys_rt_sigaction,但在发送信号时始终会出现内存访问错误 struct sigaction 在使用 C / C ++ 函数sigaction时有效。

sys_rt_sigaction来电有什么问题?

带有ASM代码的

C / C ++:

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

void handler(int){printf("handler\n");}
void restorer(){asm volatile("mov $15,%%rax\nsyscall":::"rax");}

struct sigaction act{handler};
timespec ts{10,0};

int main(){
 act.sa_flags=0x04000000;
 act.sa_restorer=&restorer;
 //*
 asm volatile("\
 mov $13,%%rax\n\
 mov %0,%%rdi\n\
 mov %1,%%rsi\n\
 mov %2,%%rdx\n\
 mov $8,%%r10\n\
 syscall\n\
 mov %%rax,%%rdi\n\
 mov $60,%%rax\n\
#syscall\n\
 "::"i"(7),"p"(&act),"p"(0):"rax","rdi","rsi","rdx","r10");
 /**/

 /*
 sigaction(7,&act,0);
 /**/

 nanosleep(&ts,0);
}

编译

g++ -o bin -std=c++11
g++ -o bin -std=c++11 -no-pie

发送信号

kill -7 `pidof bin`

1 个答案:

答案 0 :(得分:7)

在x86-64 linux中,提供sa_restorer是强制性的,但您还没有这样做。

relevant part of kernel source

            /* x86-64 should always use SA_RESTORER. */
            if (ksig->ka.sa.sa_flags & SA_RESTORER) {
                    put_user_ex(ksig->ka.sa.sa_restorer, &frame->pretcode);
            } else {
                    /* could use a vstub here */
                    err |= -EFAULT;
            }

C library wrapper为您完成此任务:

  kact.sa_flags = act->sa_flags | SA_RESTORER;

  kact.sa_restorer = &restore_rt;

使用更新后的代码确实有一个恢复器,但是你有两个问题:它已经坏了,你传了错。查看上面提到的C库源代码,您可以find this comment

/* The difference here is that the sigaction structure used in the
   kernel is not the same as we use in the libc.  Therefore we must
   translate it here.  */

此外,由于函数序言,您无法将C ++函数用作还原器。此外,不支持从信号处理程序调用{​​{1}}(但在这里工作)。最后,正如David Wohlferd指出的那样,你的咒语是错误的。总而言之,以下可能是一个返工版本:

printf

它仍然是hacky,显然你不应该这样做。