Linux 内存访问错误系统操作(信号处理程序)

Linux 内存访问错误系统操作(信号处理程序),linux,assembly,x86-64,system-calls,Linux,Assembly,X86 64,System Calls,在本文之后,我一直尝试在amd64中使用sys\u rt\u sigaction,但在发送信号时总是出现内存访问错误struct sigaction在使用C/C++函数sigaction时工作 sys\u rt\u sigaction调用有什么问题 C/C++与ASM代码: 发送信号 在x86-64 linux中,必须提供sau恢复程序,但您还没有这样做 委员会: 为您提供以下服务: kact.sa_flags = act->sa_flags | SA_RESTORER; kac

在本文之后,我一直尝试在amd64中使用
sys\u rt\u sigaction
,但在发送信号时总是出现内存访问错误struct sigaction在使用C/C++函数
sigaction
时工作

sys\u rt\u sigaction
调用有什么问题

C/C++与ASM代码: 发送信号
在x86-64 linux中,必须提供
sau恢复程序
,但您还没有这样做

委员会:

为您提供以下服务:

  kact.sa_flags = act->sa_flags | SA_RESTORER;

  kact.sa_restorer = &restore_rt;
使用更新后的代码,您确实有一个恢复程序,但您有两个问题:它已损坏,并且您传递的代码错误。查看上述C库源代码,您可以:

此外,由于函数序言,不能将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);
}
#包括
#包括
#包括
无效处理程序(int){
const char msg[]=“处理程序\n”;
写入(0,msg,sizeof(msg));
}
外部“C”无效恢复程序();
asm volatile(“恢复者:mov$15,%rax\nsyscall”);
结构内核操作{
无效(*k_sa_handler)(int);
未签名的长萨乌旗;
无效(*sa_恢复人)(无效);
无符号长萨乌面具;
};
结构内核_sigactionact{handler};
timespects{10,0};
int main(){
act.sa_标志=0x04000000;
行为恢复人=&恢复人;
asm volatile(“\
mov$13,%%rax\n\
mov%0,%%rdi\n\
mov%1,%%rsi\n\
mov%2,%%rdx\n\
mov$8,%%r10\n\
系统调用\n\
“:“i”(7),“p”(&act),“p”(0):“rax”,“rcx”,“rdi”,“rsi”,“rdx”,“r8”,“r9”,“r10”,“r11”);
纳米睡眠(&ts,0);
}

很明显,这仍然是一个黑客问题,你不应该这样做。

嗨,非常感谢你的帮助:D在发布这个问题之前,我已经尝试过使用
恢复程序
,在很多方面都有相同的结果:(可能除了
恢复程序
,还缺少其他东西?我怀疑与
掩码
标志
有关,但从未找到什么。我无法对未显示的代码进行评论。您确实需要一个恢复程序,否则您将点击该
默认值
。可能是您在使用该恢复程序时编写了错误的代码。好的,我知道了。)在暂停之后,为了让大脑休息,我会继续工作,呵呵:谢谢,内核可能会对它们进行重击。所有的文档都说,除了
rcx
更改和添加的
r11
重击之外,在用户空间中也适用相同的约定。至少在我的系统上,这个值似乎保留了下来,但比抱歉更好:)事实上,我得到了纠正。我删除了最后两条注释。当我阅读ABI中的异常部分(之前)时,我假设是寄存器保存的常规约定(异常)——RCX和R11(以及用于返回值的RAX)ABI有点模棱两可,但在查看Linux内核源代码后,很明显,常规用户土地调用约定中所有其他调用方保留的寄存器(易失性寄存器)似乎都适用。Linux的
syscall
clobber rcx和r11不是吗?确实适用,这一点很好。
kill -7 `pidof bin`
            /* 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;
            }
  kact.sa_flags = act->sa_flags | SA_RESTORER;

  kact.sa_restorer = &restore_rt;
/* 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.  */
#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);
}