Memory access error sys_rt_sigaction (signal handler)

后端 未结 1 798
难免孤独
难免孤独 2020-12-11 07:54

Following this Interfacing Linux Signals article, i have been trying to use sys_rt_sigaction in amd64, but always get memory access err

相关标签:
1条回答
  • 2020-12-11 08:38

    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.

    0 讨论(0)
提交回复
热议问题