sigreturn如何阻止SECCOMP_SET_MODE_STRICT中SIGKILL和SIGSTOP以外的所有信号?

时间:2018-11-29 14:32:38

标签: linux linux-kernel signals system-calls seccomp

man 2 seccomp SECCOMP_SET_MODE_STRICT 部分中,据说:

  

请注意,尽管调用线程无法再调用   sigprocmask(2),可以使用sigreturn(2)将所有信号分开   来自SIGKILL和SIGSTOP。

我不知道该怎么做。 sigreturnsyscall

  

此sigreturn()调用撤消已完成的所有操作-更改   进程的信号掩码,切换信号堆栈(请参见sigaltstack(2))—在   为了调用信号处理程序。

更具体地说:

  

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

信息存储于:

  

已保存的流程上下文信息放置在ucontext_t中   结构(请参阅)。该结构在内部可见   信号处理程序作为通过建立的处理程序的第三个参数   带有SA_SIGINFO标志的sigaction(2)。

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

  1. 由于信号的TERM操作不需要返回用户空间,因此无法通过使用dying或类似方法来阻止atexit

  2. >

    2。尽管可以用man 2 getcontextman 3 makecontext来填充ucontext_t,但是由于所有系统都要求安装处理程序,所以这不会帮助阻塞信号并且屏蔽信号已被禁用(除非sigreturn自己进行siganl屏蔽)

1 个答案:

答案 0 :(得分:1)

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

这是如何以及为什么:

  1. 该过程将构建一个堆栈帧,该堆栈帧看起来与内核刚从传递的信号返回信号处理程序时内核执行的堆栈帧一样。

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

    该过程将信号掩码设置为所需的信号掩码。

  2. 该过程调用sigreturn()

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

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

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

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

请注意,sigreturn()SIGKILL不会受到影响,因为它们是内核强制执行的两个信号。所有其他信号都应仅视为请求和通知,而接收者始终可以阻止或忽略它们。

1 除非使用signal cookies或类似的sigreturn堆栈帧验证方法。