Как sigreturn может блокировать все сигналы, кроме SIGKILL и SIGSTOP в SECCOMP_SET_MODE_STRICT?

В разделе SECCOMP_SET_MODE_STRICT документа man 2 seccomp сказано, что:

Обратите внимание, что хотя вызывающий поток больше не может вызывать sigprocmask(2), он может использовать sigreturn(2) для блокировки всех сигналов, кроме SIGKILL и SIGSTOP.

Я не могу понять, как это сделать. sigreturn это syscall что

Этот вызов sigreturn() отменяет все, что было сделано — изменение маски сигнала процесса, переключение стеков сигналов (см. sigaltstack(2)) — для того, чтобы вызвать обработчик сигнала.

Более конкретно:

Используя информацию, которая ранее была сохранена в стеке пользовательского пространства,
sigreturn() восстанавливает маску сигнала процесса, переключает стеки и восстанавливает контекст процесса (флаги и регистры процессора, включая указатель стека и указатель инструкций),

Информация хранится:

Сохраненная информация о контексте процесса помещается в структуру ucontext_t (см. Ресурсы). Эта структура видна в обработчике сигнала как третий аргумент обработчика, установленного с помощью sigaction(2) с флагом SA_SIGINFO.

Я считал это невозможным по следующим 2 причинам:

  1. Поскольку действие TERM для сигнала не требует возврата в пользовательское пространство, нет способа предотвратить dying с помощью atexit или чего-то подобного.

    2. Хотя можно заполнить ucontext_t с помощью man 2 getcontext или man 3 makecontext, это не помогите процессу заблокировать сигнал, поскольку все системные вызовы для установки обработчика и маскирования сигнала отключены (если только sigreturn не выполняет саму маскировку сигнала).


person JiaHao Xu    schedule 29.11.2018    source источник


Ответы (1)


Да, sigreturn() действительно заставляет ядро ​​изменить маску сигнала для вызывающего потока.

Вот как и почему:

  1. Процесс создает кадр стека, который выглядит точно так же, как тот, который делает ядро, когда обработчик сигнала только что вернулся из доставленного сигнала.

    Этот кадр стека содержит исходную маску сигнала для потока, используемого для доставки сигнала, и адрес, по которому этот поток был прерван доставкой сигнала. (При нормальной работе в текущей активной маске сигналов заблокированы дополнительные сигналы, включая доставляемый сигнал.)

    Процесс устанавливает для этой маски сигнала значение, которое он предпочитает.

  2. Процесс вызывает sigreturn().

    Ядро проверяет кадр стека, замечает старую маску сигнала и восстанавливает ее. Он также очищает фрейм стека и возвращает управление коду пользовательского пространства. (Кадр стека содержал адрес следующей выполняемой инструкции.)

  3. Этот поток продолжает выполнение по адресу, указанному в этом кадре стека, теперь с установленной предпочтительной маской сигнала.

sigreturn() нельзя заблокировать seccomp, потому что это необходимо для нормальной работы. (Однако обратите внимание, что вызов sigreturn() не требуется после доставки сигнала; с некоторыми ограничениями процесс пользовательского пространства может продолжать выполнение через siglongjmp() вместо этого. siglongjmp() — это не системный вызов, а просто функция пользовательского пространства. означает, что ядро ​​ограничено таким поведением, если оно не отличается от поведения POSIX.1.)

Ядро не различает1 контекст между контекстом, созданным самим процессом пользовательского пространства, и контекстом, созданным ядром в стеке процессов. Поскольку контекст содержит маску сигнала, восстановленную ядром как часть обработки sigreturn(), sigreturn() позволит потоку изменить свою маску сигнала.

Обратите внимание, что SIGKILL и SIGSTOP не затрагиваются, потому что это два сигнала, которые использует ядро. Все остальные сигналы следует рассматривать только как запросы и уведомления, при этом получатель всегда может их заблокировать или проигнорировать.

1 Если только сигнальные файлы cookie или аналогичный фрейм стека sigreturn используется метод проверки.

person Nominal Animal    schedule 02.12.2018
comment
Спасибо, нормальное животное! Но почему ядро ​​не хранит это внутри себя, чтобы этот хак не мог произойти. Я имею в виду, это ошибка, верно? - person JiaHao Xu; 02.12.2018
comment
@JiaHaoXu: это не считается ошибкой, потому что нет разумной причины пытаться помешать процессу изменить свою собственную сигнальную маску. Это похоже на попытку помешать программе изменить свои собственные переменные среды или аргументы командной строки. Проще говоря, это то, что процесс должен уметь делать всегда, даже когда используется strict seccomp. Во всяком случае, возможно, ошибка заключается в том, что строгий seccomp не разрешает sigprocmask() (или exit_group()). - person Nominal Animal; 02.12.2018
comment
Спасибо, что нашли время ответить на мой комментарий, Nominal Animal! - person JiaHao Xu; 03.12.2018