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

How can sigreturn block all signal except SIGKILL and SIGSTOP in SECCOMP_SET_MODE_STRICT?

man 2 seccompSECCOMP_SET_MODE_STRICT 部分,据说:

Note that although the calling thread can no longer call sigprocmask(2), it can use sigreturn(2) to block all signals apart from SIGKILL and SIGSTOP.

我不知道该怎么做。 sigreturnsyscall

This sigreturn() call undoes everything that was done—changing the process's signal mask, switching signal stacks (see sigaltstack(2))—in order to invoke the signal handler.

更具体地说:

Using the information that was earlier saved on the user-space stack
sigreturn() restores the process's signal mask, switches stacks, and restores the process's context (processor flags and registers, including the stack pointer and instruction pointer),

信息存储于:

The saved process context information is placed in a ucontext_t structure (see ). That structure is visible within the signal handler as the third argument of a handler established via sigaction(2) with the SA_SIGINFO flag.

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

  1. 由于信号的 TERM 操作不需要 return 给用户 space,因此无法通过使用来阻止 dying atexit 或类似的东西。

    2.Although 可以用 man 2 getcontext or man 3 makecontext 填充 ucontext_t,这不会帮助进程阻止信号,因为所有系统调用都需要安装处理程序和屏蔽信号被禁用 (除非 sigreturn 自己做信号掩码).

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

这是方法和原因:

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

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

    进程将该信号掩码设置为它喜欢的掩码。

  2. 进程调用sigreturn().

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

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

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

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

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

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