TGViewer
LinuxCamp | DevOps LinuxCamp | DevOps @linuxcamp_tg · 13.6K subscribers
Post #145 6.59K
Защита от незваных гостей: сигнальная маска

Для каждого процесса ядро хранит специальную маску, которая определяет те сигналы, которые будут временно заблокированы и необработаны.

Если в процесс отправляется заблокированный сигнал, то доставка этого сигнала откладывается до тех пор, пока он не будет разблокирован путем удаления из сигнальной маски.

Как же нам определить эту чудо-маску и замутить пару сигналов?) Использовать системный вызов sigprocmask():


#include <signal.h>
int sigprogmask(int how, const sigset_t *set, sigset_t *oldset);


Аргумент how определяет то, каким образом набор сигналов, передаваемый в set, изменит текущую маску процесса:

1. SIG_BLOCK — сигналы, включенные set, добавляются в сигнальную маску. Другими словами, блокируемые сигналы остаются таковыми, а новые добавляются к ним;

2. SIG_UNBLOCK — сигналы, включенные set, исключаются из сигнальной маски;

3. SIG_SETMASK — сигналы, включенные set, переопределяют текущую маску. Сигналы, не включённые в новое множество, больше не блокируются;

Если аргумент oldset не равен NULL, то он указывает на переменную типа sigset_t, в которую записывается текущее значение сигнальной маски (до изменения).

Если мы хотим через oldset получить сигнальную маску без каких-то изменений, можно установить значение NULL для аргумента set, в этом случае аргумент how будет проигнорирован.

Ну все, давайте, ближе к делу, ближе к коду. Сейчас используем вообще все наши знания по сигналам: напишем перехватчик, отправим сигнал самому себе, определим маску и посмотрим на результат:


#include <signal.h>
#include <unistd.h>

void handler (int num) {
write(STDOUT_FILENO, "I won't die!\n", 13);
}

int main() {
signal(SIGINT, handler);

sigset_t blockSet, prevMask;

sigemptyset(&blockSet);
sigaddset(&blockSet, SIGINT);
sigprocmask(SIG_BLOCK, &blockSet, &prevMask);

raise(SIGINT);

return 0;
}


Теперь скомпилим и запустим прогу:


$ gcc -o prog main.c
$ ./prog


И что... Бам, никакого вывода мы не увидим - маска успешно отработала.

А теперь го еще прикол. Помните, ранее речь заходила о том, что отправленные сигналы не отменяются, а откладываются - как только мы уберем его из маски, процесс его примет и обработает.

Проверить мы это сможем, если добавим следующий код после вызова "raise(SIGINT);":


sleep(5);
sigprocmask(SIG_SETMASK, &prevMask, NULL);


Ждем 5 сек и наблюдаем лог:


$ ./prog
I won't die!


Теперь пару слов про сигналы: SIGKILL и SIGSTOP. Их мы игнорировать не можем, УВЫ и АХ. Если мы попытаемся заблокировать эти сигналы, функция sigprocmask() ошибку не выдаст, но и желаемого результата мы также не получим.

Для того чтобы добавить все сигналы в маску, кроме SIGKILL и SIGSTOP, мы можем использовать следующий вызов:


sigfillset(&blockSet);


LinuxCamp
  • 👍 25
  • 🔥 12
  • ❤‍🔥 5
  • ✍ 2
  • ❤ 1
More from @linuxcamp_tg
  1. Sep 28, 2026Проекту GNU вчера исполнилось 43 года 1983 год: Ричард Столлман объявил планы разработать…
  2. Sep 25, 2026Linux будет работать на ноутах с Snapdragon X2. Qualcomm добавляет полноценную поддержку L…
  3. Sep 24, 2026Так все по делу)) Советует же самый быстрый фикс LinuxCamp | #memes
  4. Sep 23, 2026Планы на 3 октября — прийти на RWB Infra x Security Meetup Мы направим прожекторы на инфра…
  5. Sep 22, 2026Ещё одна рекордная неделя для AI-разработки в Linux. На прошлой неделе в ядро попало 1 634…
  6. Sep 17, 2026Открыл плейлист, а как выйти - непонятно 😁 LinuxCamp | #memes
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →