Разработка приложений в среде Linux. Второе издание
Шрифт:
Параметр
Многие операционные системы, поддерживающие
С временными файлами связана еще одна проблема, которая не рассматривалась до сих пор. Они содержат режимы состязаний, добавляемые временными каталогами, которые постоянно хранятся в сетевых (особенно NFS) файловых системах, а также программами, которые регулярно удаляют старые файлы из этих каталогов. При повторном открытии
22.3.6. Режимы состязаний и обработчики сигналов
Всякий раз когда взломщик может заставить программу вести себя неправильно, появляется потенциальная возможность для злоумышленной эксплуатации. Ошибки, кажущиеся безобидными, вроде двукратного освобождения одной и той же порции памяти успешно использовались злоумышленниками в прошлом, что еще раз указывает на необходимость быть очень внимательным при создании привилегированных программ.
Режимы состязаний и обработчики сигналов, которые легко могут стать причиной возникновения режима состязаний, являются щедрым источником программных ошибок. Самые общие ошибки при написании обработчиков сигналов описаны ниже.
• Выполнение динамического распределения памяти. Функции распределения памяти не являются реентерабельными и не должны применяться в обработчиках сигналов.
• Применение каких-либо функций, кроме перечисленных в табл. 12.2, всегда приводит к ошибке. Программы, вызывающие такие функции, как
• Неправильное блокирование остальных сигналов. Большинство обработчиков сигналов не являются реентерабельными, однако, довольно часто в обработчиках, управляющих несколькими сигналами, не блокируются автоматически остальные сигналы. Применение
• Неблокирование сигналов в тех областях кода, модифицирующих переменные, к которым обработчик сигналов также имеет доступ. (Такие зоны часто называются критическими областями.)
В то время как режимы состязаний, порожденные сигналами, могут показаться не опасными, сетевые коды, setuid- и setgid-программы могут использовать сигналы, посылаемые ненадежными пользователями. Передача экстренных данных в программу может стать причиной отправки
22.3.7. Закрытие файловых дескрипторов
В системах Linux и Unix файловые дескрипторы, как правило, наследуются через системные вызовы
165
Система Linux позволяет программам открывать очень большое количество файлов. Процессы, работающие как root, могут одновременно открывать сотни файлов, однако большинство дистрибутивов устанавливают предел ресурсов на количество файлов, который может открывать пользовательский процесс. Этот предел также ограничивает максимальный файловый дескриптор, который можно использовать, с помощью метода
166
Еще одним способом закрытия всех файлов, открытых программой, является прохождение через каталог файловой системы процесса
Наиболее удобным способом является установка флага закрытия после выполнения для каждого файла, который программа оставляет открытым на длительный период времени (включая сокеты и файловые устройства), что предотвращает получение доступа к данным файлам новыми запускаемыми программами. Описание флага закрытия после выполнения можно найти в главе 11.
22.4. Запуск в качестве демона
При разработке программ, создаваемых для работы в качестве системных демонов, нужно очень внимательно проводить их становление как демонов для правильного определения всех деталей. Ниже приведен перечень тех обстоятельств, на которые необходимо обратить внимание.
1. Большинство действий по инициализации должны быть произведены до того, как программа становится фактическим демоном. Это гарантирует, что пользователь при запуске не будет получать сообщения об ошибках, и будет возвращаться значащий код завершения. Этот вид деятельности включает в себя анализ конфигурационных файлов и открытие сокетов.
2. Текущий каталог должен быть изменен на какой-либо подходящий. Это может быть корневой каталог, но никогда не может быть тот каталог, из которого была запущена программа. Если демон этого не сделает, то, возможно, он будет работать соответствующим образом, но это не позволяет удалить тот каталог, из которого он был активизирован, поскольку он остается текущим каталогом программы. Если это возможно, то неплохо применить
3. Все ненужные файловые дескрипторы должны быть закрыты. Это может показаться очевидным, однако вы легко можете упустить закрытие тех дескрипторов, которые были унаследованы, а не открыты самой программой. Об этом речь шла в предыдущем разделе.
4. Затем программа должна вызвать
5. Дочерний процесс, продолжающий работу, должен закрыть stdin, stdout и stderr, поскольку он не будет больше использовать терминал. Вместо повторного применения файловых дескрипторов 0, 1 и 2 лучше открывать эти файлы как
6. Для полного разъединения с терминалом, из которого был запущен демон, он должен вызвать
Библиотека С предлагает функцию
Данная функция сразу осуществляет ветвление, и если оно прошло успешно, родительский процесс вызывает