【问题标题】:sigprocmask returns -22 in assemblysigprocmask 在汇编中返回 -22
【发布时间】:2016-01-08 07:08:23
【问题描述】:

我想在程序集中使用 sigprocmask 阻止函数中的所有信号。

以下代码在 C 中工作:

#include <stdio.h>
#include <signal.h>
int main() {
    sigset_t n={(unsigned long int) 0xffffffff};
    sigprocmask (SIG_BLOCK, &n, 0);

    for (int i=0; i<0x8ffff; i++) printf(".");
}

当代码执行并开始在终端上打印点时,我无法使用 Ctrl+C 中断它。到目前为止一切顺利。

SIG_BLOCK 的值显然是 0; sys_rt_sigprocmask 的系统调用号为 14: http://blog.rchapman.org/post/36801038863/linux-system-call-table-for-x86-64

所以我写:

[BITS 64]
    [section .text align=1]

    global main

        main:

            mov r10, 32
            mov rdx, 0
            mov rsi, newmask
            mov rdi, 0

            mov rax, 14
            syscall


            dotPrintLoop:
                mov rdi, dotstring
                mov rax, 0
                syscall
                jmp dotPrintLoop


    [section .data align=1]

        dotstring:  db ".",0

        newmask:    dd 0xffffffff
                    dd 0xffffffff
                    dd 0xffffffff
                    ...

而且它不起作用。 gdb 表明 rax 在第一次系统调用之后的值为 -22(EINVAL - “无效参数”);而第二个系统调用(sys_write)工作得很好。

我做错了什么?

【问题讨论】:

    标签: linux assembly linux-kernel signals x86-64


    【解决方案1】:

    显然 r10 应该保存值 8 而不是 32。

    我在内核代码中遇到了 4 种不同的 sigset_t 定义;对于它们中的每一个,sizeof() 函数都会返回不同的结果(我记得是 32、128、4 和 8)。只有最后一个与系统调用相关。

    内核首先检查$r10 == sizeof(sigset_t);如果不成立,则返回EINVAL (-22)。对于 32 位和 64 位版本,sizeof(sigset_t) 的值都等于 8。

    【讨论】:

    • 您可以通过单步进入 libc 包装器以查看它作为 args 传递给系统调用的确切内容,或者更简单地从 strace 输出中弄清楚这一点。 strace -e rt_sigprocmask ls 2&gt;&amp;1 | m 表明实际底层系统调用的最终参数是 8
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多