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

在这个接口Linux信号文章之后,我一直试图在amd64中使用sys_rt_sigaction ,但是在发送信号时总是得到内存访问错误 。 当使用C / C ++函数sigaction时, struct 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` 

在x86-64 linux中,提供一个sa_restorer是必须的,而你没有这样做。

内核源码的相关部分 :

  /* 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库包装为你做这个:

  kact.sa_flags = act->sa_flags | SA_RESTORER; kact.sa_restorer = &restore_rt; 

随着更新的代码,你确实有一个恢复器,但你有两个问题:它是坏的,你传错了。 看看上面提到的C库源代码,你可以找到这个评论 :

 /* 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 ++函数作为恢复器。 此外,不支持从信号处理程序调用printf (但在这里工作)。 最后,正如大卫·沃尔弗德(David Wohlferd)指出的那样,你的破坏者是错误的。 总而言之,以下内容可能是一个重新修订的版本:

 #include<stdio.h> #include<unistd.h> #include<time.h> void handler(int){ const char msg[] = "handler\n"; write(0, msg, sizeof(msg)); } extern "C" void restorer(); asm volatile("restorer:mov $15,%rax\nsyscall"); struct kernel_sigaction { void (*k_sa_handler) (int); unsigned long sa_flags; void (*sa_restorer) (void); unsigned long sa_mask; }; struct kernel_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\ "::"i"(7),"p"(&act),"p"(0):"rax","rcx", "rdi","rsi","rdx","r8", "r9", "r10", "r11"); nanosleep(&ts,0); } 

这还是很不好,显然你不应该这样做。