0

man 2 seccompSECCOMP_SET_MODE_STRICT部分中,据说:

请注意,虽然调用线程不能再调用 sigprocmask(2),但它可以使用 sigreturn(2) 来阻塞除 SIGKILL 和 SIGSTOP 之外的所有信号。

我无法弄清楚如何做到这一点。sigreturnsyscall那个

这个 sigreturn() 调用撤消了所有已完成的操作——更改进程的信号掩码、切换信号堆栈(参见 sigaltstack(2))——以便调用信号处理程序。

进一步来说:

使用之前保存在用户空间堆栈中的信息
sigreturn() 恢复进程的信号掩码、切换堆栈并恢复进程的上下文(处理器标志和寄存器,包括堆栈指针和指令指针),

信息通过以下方式存储:

保存的进程上下文信息放置在 ucontext_t 结构中(请参阅 参考资料)。该结构在信号处理程序中是可见的,作为通过 sigaction(2) 使用 SA_SIGINFO 标志建立的处理程序的第三个参数。

我认为这是不可能的,因为以下两个原因:

  1. 由于TERM信号的动作不需要返回到用户空间,所以没有办法dying通过使用atexit或类似的东西来阻止。

    ucontext_t2.虽然可以用man 2 getcontextman 3 makecontext填写 a ,但这无助于进程阻止信号,因为所有用于安装处理程序和屏蔽信号的系统调用都被禁用(除非sigreturn使用 siganl 掩码东西本身)

4

1 回答 1

1

是的,sigreturn()确实会导致内核更改调用线程的信号掩码。

以下是方法和原因:

  1. 该进程构建了一个堆栈帧,它看起来与内核在信号处理程序刚刚从传递的信号返回时所做的完全一样。

    此堆栈帧包含用于传递信号的线程的原始信号掩码,以及该线程被信号传递中断的地址。(在正常操作中,当前活动的信号掩码会阻止其他信号;包括正在传递的信号。)

    该过程将该信号掩码设置为它想要的掩码。
     

  2. 该过程调用sigreturn().

    内核检查堆栈帧,注意到旧的信号掩码,并恢复它。它还清理堆栈帧,并将控制权返回给用户空间代码。(堆栈帧包含要执行的下一条指令的地址。)
     

  3. 该线程继续在该堆栈帧中指定的地址处执行,现在已安装其首选信号掩码。
     

sigreturn()不能被 seccomp 阻止,因为它是正常操作所必需的。(但是,请注意,在传递信号后不需要sigreturn()调用;在某些限制下,用户空间进程可以继续执行。不是系统调用,只是一个用户空间函数。这意味着内核仅限于这种行为,除非它偏离 POSIX.1 行为。)siglongjmp()siglongjmp()

内核不区分用户空间进程本身创建的上下文和内核在进程堆栈中创建的上下文因为上下文包含由内核恢复的信号掩码,作为sigreturn()处理的一部分,sigreturn()将允许线程修改其信号掩码。

请注意SIGKILLSIGSTOP不受影响,因为它们是内核强制执行的两个信号。所有其他信号应仅被视为请求和通知,接收者始终能够阻止或忽略它们。

1除非使用信号 cookie或类似的 sigreturn 堆栈帧验证方法。

于 2018-12-02T06:26:20.887 回答