1

I'm learning Linux syscalls and I have a problem with invoking syscall 13:

rt_sigaction(int sig, const struct sigaction __user * act, struct sigaction __user * oact, size_t sigsetsize)

on 64 bit Linux in assembly. I have used the C wrapper for this function (sigaction()) and it worked fine, but when I tried to make a direct syscall with the code below it failed. I have made other direct syscalls with this approach and only this syscall has failed to work.

I suspect that the pointer to sigint_handler() function is being passed incorrectly to the kernel but I'm not sure.

I can't use C system libraries in my project so getting this specific syscall to work with assembly invocation is my goal here.

The C code I'm running:

#define _POSIX_SOURCE
        
#include <stddef.h>
#include <stdint.h>
#include <linux/signal.h>
#include <linux/unistd.h>
#include <string.h>
#include <syscall.h>

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

// SYSCALL_4 simply injects the assembly to make the syscall directly
#define SYSCALL_4(sys_num, a1,a2,a3,a4) \ ({ \
    int64_t sys_ret; \
    __asm __volatile ( \
    "movq %1, %%rax\n\t"\
    "movq %2, %%rdi\n\t"\
    "movq %3, %%rsi\n\t"\
    "movq %4, %%rdx\n\t"\
    "movq %5, %%r10\n\t"\
    "syscall\n\t" \
    "movq %%rax, %0\n\t"\
    : "=g" (sys_ret)\
    : "g"(sys_num), "g" (a1) , "g" (a2), "g" (a3), "g" (a4)\
    : "cc", "memory", "%rax", "%rdi", "%rsi", "%rdx", "%rcx", "%r11", "%r10"\       );\
    sys_ret; \ })

struct kernel_sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};
        
void sigint_handler(int signo) {
    printf("In SIGINT handler ...\n"); 
} 

int main(void) {
    struct kernel_sigaction sig;
    
    int64_t ret = SYSCALL_4(13, SIGINT, 0, &sig, sizeof(sigset_t)); //__NR_rt_sigaction
    if (ret < 0)
    {
        fprintf(stderr,"Unable to install SIGINT handler\n");
        errno = -ret;
        perror(0);
        exit(1);
    }
    
    sig.sa_handler = sigint_handler;
    
    ret = SYSCALL_4(13, SIGINT, &sig, 0, sizeof(sigset_t)); //__NR_rt_sigaction
    if (ret < 0) //doesnt fail here
    {
        fprintf(stderr,"Unable to install SIGINT handler\n");
        errno = -ret;
        perror(0);
        exit(1);
    }
    
    printf("Sleeping for 30 seconds ...\n");
    sleep(30); //seems to fail here
    printf("Waking up ...\n"); //supposed to print after SIGINT handler
    exit(0);
}

and on console:

> gcc -Wall -march=native -std=c11 -O0 P1c_inline.c -o P1c_inline.out 
> ./P1c_inline.out 
Sleeping for 30 seconds ...
^CSegmentation fault (core dumped)
Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23
Rossman
  • 119
  • 1
  • 5

0 Answers0