Есть ли какой-либо способ запретить пользователю регистрировать / использовать свой собственный обработчик сигналов и всегда использовать обработчик particlar?

#c #c #linux #signals #signal-handling

#c #c #linux #сигналы #обработка сигналов

Вопрос:

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

Теперь этот обработчик сигналов не должен разрешать регистрировать какой-либо другой обработчик после того, как этот обработчик однажды зарегистрирован. (Но это ограничение действует только на короткое время, означает, что после этого пользователь может свободно вызывать свой собственный обработчик)

Есть ли какой-либо способ добиться этого?

  sigset_t mask;
 struct sigaction sa;
 printf("Establishing handler for signal %dn", SIG);
 sa.sa_flags = SA_SIGINFO;
 sa.sa_sigaction = handler; // This handler should override all handlers
 sigaction(SIG, amp;sa, NULL);
 sev.sigev_notify = SIGEV_SIGNAL;
 sev.sigev_signo = SIGUSR1;
  

Примечание: Мой инструмент на самом деле написан на C , но концепции настолько близки, и поскольку с ним знакомо больше людей, я тоже добавляю тег C с помощью C
Пожалуйста, не стесняйтесь запрашивать дополнительные разъяснения (если вам нужно)

Ответ №1:

Я предполагаю, что вы пишете библиотеку. Ответ нет, нет, НЕТ, НЕТ! Просто напишите в документации, что клиентский код не должен регистрировать обработчик для этого сигнала. Если вы не можете доверять пользователям вашей библиотеки, чтобы они ничего не ломали, тогда вам следует писать приложения, а не библиотеки.

Независимо от того, что вы делаете, чтобы ваш обработчик был приоритетным по сравнению с другими, это не сработает, если другой код делает то же самое. Вот очень актуальный пост в блоге о разработчиках Windows, которые хотят создать «самое верхнее окно» (что-то вроде обработчика сигналов с «наивысшим приоритетом»).

https://devblogs.microsoft.com/oldnewthing/20110310-00/?p=11253

P.S. В Linux нет хорошего способа предоставить разные уровни полномочий на более тонком уровне, чем уровень процесса.

P.P.S. Чтобы уточнить, если мой код выполняется в вашем процессе, то вы ничего не можете сделать. Вы уже проиграли. Мой код может получить доступ к вашим частным переменным-членам, освободить вашу память, закрыть ваши файлы и выгрузить ваши библиотеки. (Вы можете написать код ядра или запустить все в виртуализации, но это было бы ужасно.)

Комментарии:

1. @Dietrich: Ваше предположение верно, я разрабатываю инструмент тестирования. Тестовый код пользователя связан с моим инструментом. После запуска моего таймера пользователю не должно быть разрешено вызывать его обработчик или регистрироваться, однако он может свободно отправлять конкретный сигнал. По истечении таймера пользователь может свободно вызывать или регистрировать свой обработчик. Неужели нет способа сделать это?

2. Нет способа сделать это. Если, конечно, вы не хотите написать драйвер ядра.

3. Извините, это выходит за рамки моей разработки : (

4. @kingsmasher1 Для ясности, нет, это невозможно. Похоже, что это может быть случай «проблемы XY». Чего именно вы пытаетесь достичь, не позволяя какому-либо случайному коду регистрировать обработчик сигналов?

5. Это зависит от того, какой уровень «не разрешено» вы имеете в виду. Вы могли бы выполнить уродливые взломы, обернув функции libc ( sigaction и т.д.), Чтобы они завершались сбоем при раннем вызове, но вредоносная программа могла бы обойти это, написав код системного вызова непосредственно в asm. Для запуска изолированного вредоносного кода вам действительно нужно либо отдельное пользовательское / адресное пространство и процесс супервизора, отслеживающий его, либо (лучше) полноценная виртуальная машина.

Ответ №2:

Если обработка signal является проблемой, то избавьтесь от signal ! Вы можете использовать select как способ перехода в спящий режим с той точностью, какую позволяет степень детализации вашей ОС. вызов selects с нулевыми значениями stes (без дескриптора в любых наборах) и допустимым таймаутом — это, по сути, блокирующий системный вызов с нижней границей по времени.

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

Ответ №3:

Самый простой ответ — не использовать сигналы для таймеров. Вы могли бы вместо этого просто создать таймер POSIX с SIGEV_THREAD доставкой (обработчик выполняется в новом потоке, а не в обработчике сигналов) или создать свой собственный поток и nanosleep находиться в нем в течение желаемого интервала. Преимущество этого заключается в том, что обработчик истечения срока действия таймера не ограничен только функциями, безопасными для асинхронного сигнала, и вам не нужно беспокоиться об установке конфликтующих обработчиков сигналов.

Комментарии:

1. SIGEV_THREAD не поддерживается в нашем дистрибутиве. Позже я вернулся к timerfd.

Ответ №4:

Этого можно достичь, и фактически я сделал это, написав оболочку sigaction вокруг реальной и используя технику dlsym и RTLD_NEXT .

Вот фрагмент кода моей оболочки:

 enter code here
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{

 struct sigaction sa;
 printf("My sigaction calledn");

 if((Timerflag==1)amp;amp;(sig==SIGUSR1))
 {
   sa.sa_sigaction=my_handler;
   sa.sa_flags=0;

   return LT_SIGACTION(sig,amp;sa,NULL);
  }
  else if(Timerflag==0)
    return LT_SIGACTION(sig, act, oact);  
}
  

Наконец, я думаю, все знают, как получить дескриптор libc с помощью dlsym 🙂
К сожалению, никто не смог подсказать мне эту идею в «stackoverflow».

Комментарии:

1. Это не будет работать с кодом, который выполняет системный вызов напрямую, а не через libc.

2. @Dietrich: Для меня это будет работать хорошо, потому что приложение будет подключаться через libc. Также, я думаю, нигде в моем вопросе я не упоминал, что приложение будет выполнять системный вызов напрямую.

3. @Dietrich: Также мне интересно, что вы подразумеваете под «прямым системным вызовом» 🙂 системные вызовы всегда выполняются через оболочку системного вызова, которая всегда подключается через libc.

4. На x86 есть код операции системного вызова. Libc — это просто библиотека. Другие системы похожи.

5. Я с радостью пожертвую очком репутации, чтобы отклонить такое наглое проявление невежества. Послушай, что говорят эксперты, kingsmasher.