内存访问错误sys_rt_sigaction(信号处理程序) [英] Memory access error sys_rt_sigaction (signal handler)

查看:137
本文介绍了内存访问错误sys_rt_sigaction(信号处理程序)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这篇接口Linux信号文章之后,我有一直尝试在 amd64 中使用sys_rt_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`

解决方案

在x86-64 linux中,必须提供sa_restorer,而您尚未提供.

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)所指出的那样,您的clo语是错误的.总而言之,以下内容可能是重做的版本:

#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);
}

它仍然很笨拙,显然,您实际上不应该这样做.

Following this Interfacing Linux Signals article, i have been trying to use sys_rt_sigaction in amd64, but always get memory access error when sending the signal. struct sigaction works when using C/C++ function sigaction.

What is wrong in sys_rt_sigaction call?

C/C++ with ASM code:

#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);
}

Compile

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

Send signal

kill -7 `pidof bin`

解决方案

In x86-64 linux, it's mandatory to supply a sa_restorer and you haven't done so.

The 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;
            }

The C library wrapper does this for you:

  kact.sa_flags = act->sa_flags | SA_RESTORER;

  kact.sa_restorer = &restore_rt;

With the updated code you do indeed have a restorer, but you have two problems: it's broken and you pass it wrong. Looking at the above mentioned C library source you can 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.  */

Also, you can't have a C++ function as restorer due to the function prologue. Furthermore, calling printf from a signal handler is not supported (but works here). Finally, as David Wohlferd pointed out, your clobbers are wrong. All in all, the following could be a reworked version:

#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);
}

It's still hacky, and you shouldn't really be doing it this way, obviously.

这篇关于内存访问错误sys_rt_sigaction(信号处理程序)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆