【问题标题】:Making syscalls on Linux without a stack在没有堆栈的 Linux 上进行系统调用
【发布时间】:2011-02-10 23:51:57
【问题描述】:

在 Linux i386 上,int $0x80 系统调用 ABI 可以在没有有效用户空间堆栈的情况下轻松执行系统调用。另一方面,vdso/vsyscall 接口需要访问堆栈。其他 Linux 端口在这方面的表现如何,尤其是 x86_64?他们有办法在没有堆栈的情况下进行系统调用吗?是否有关于每个拱门的可用系统调用方法的参考?

【问题讨论】:

    标签: c linux assembly system-calls abi


    【解决方案1】:

    总的来说:不知道。即使在 i386 上,如果有第 6 个参数,它也必须在堆栈上传递(例如对于 mmap)。

    特别是对于 x86_64:将系统调用号放入 %rax(注意:系统调用号与 32 位的分配完全不同),%rdi%rsi%rdx 中最多 6 个参数, %r10%r8%r9(这与在寄存器中传递参数的常用 ABI 几乎但不完全相同 - 注意使用 %r10 而不是 %rcx),并使用 @987654332 @ 操作说明。结果在%rax 中返回,%rcx%r11 被破坏。

    x86_64 ABI 信息可以在http://www.x86-64.org/documentation/abi.pdf 找到; Linux ABI 记录在附录中。 (如果在其他地方寻找 x86_64 ABI 信息,请注意 64 位 Windows 使用自己不同的 ABI。)


    我不认为syscall 对用户堆栈框架有任何要求才能正常工作。在被信号中断的情况下,处理程序显然需要一个健全的堆栈;但是下面的实验,它使用了一个备用信号堆栈并故意在syscall 周围丢弃%rsp,对我来说效果很好:

    $ cat syscall_sig.c
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <time.h>
    #include <unistd.h>
    
    #define __NR_nanosleep 35
    
    static sig_atomic_t alrm = 0;
    
    void handler(int sig)
    {
        if (sig == SIGALRM)
            alrm = 1;
    }
    
    int main(void)
    {
        stack_t ss;
        struct sigaction sa;
        struct timespec req, rem;
        long ret;
    
        ss.ss_flags = 0;
        ss.ss_size = SIGSTKSZ;
        ss.ss_sp = malloc(ss.ss_size);
        sigaltstack(&ss, NULL);
    
        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = handler;
        sa.sa_flags = SA_ONSTACK;
        sigaction(SIGALRM, &sa, NULL);
    
        alarm(1);
    
        req.tv_sec = 5;
        req.tv_nsec = 0;
        asm("xorq $0x12345678, %%rsp ; syscall ; xorq $0x12345678, %%rsp"
            : "=a" (ret)
            : "0" (__NR_nanosleep), "D" (&req), "S" (&rem)
            : "rcx", "r11", "memory");
    
        printf("syscall return code %ld, alarm flag %d\n", ret, alrm);
    
        return 0;
    }
    
    $ gcc -Wall -o syscall_sig syscall_sig.c
    $ ./syscall_sig
    syscall return code -4, alarm flag 1
    $ 
    

    【讨论】:

    • 这就是我正在做的事情(间接通过其他人,因为我无法直接访问 x86_64 系统进行移植)。实际上现在我有一个筹码,但我知道以后我将不得不处理我不会的情况,但我已经遇到了麻烦。您描述的方法有效,除非系统调用被信号中断,但如果它被中断并尝试恢复,它会在syscall 指令上出现段错误...@ 987654341@ 是否需要设置特定的堆栈帧以防万一中断/恢复?
    • 如果您的信号处理程序上没有影子堆栈,它会使用主堆栈,如果它被冲洗掉,您就有麻烦了。
    猜你喜欢
    • 2010-11-08
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2016-08-05
    • 2010-10-03
    • 2014-07-21
    • 1970-01-01
    相关资源
    最近更新 更多