Вопрос или проблема
На прошлой неделе я обновил свой файловый сервер на базе Linux с Fedora 39 до Fedora 40, и несколько CGI-приложений, написанных на Perl, перестали работать. Я впервые заметил это, когда Foswiki не смог показать никаких страниц, так как не смог открыть свой лог-файл. После неудачной попытки выяснить, что обновление системы привело к несовместимости между (обновлёнными) библиотеками perl и (старым) приложением Foswiki, я обнаружил, что приложение, которое я написал сам, имеет ту же проблему.
Теперь я свёл это к очень маленькой программе, основной частью которой являются всего несколько строк:
my $file_to_write = "/tmp/writetest.txt";
unless (open(OUTFILE, ">>", $file_to_write)) {
print "Не удалось открыть (для добавления) $file_to_write.<BR>\n";
}
printf "%s %s Письмо теста в $file_to_write\n", ljpDate(), ljpTime();
printf OUTFILE "%s %s Письмо теста\n", ljpDate(), ljpTime();
close OUTFILE;
print "Запись завершена<BR>\n";
Кажется, что открытие проходит успешно (я не получаю сообщение “Не удалось ..”), но ничего не записывается в файл, хотя он имеет режим 666 (-rw-rw-rw-) и принадлежит apache:apache. Если файл существует, он не затрагивается, а если его нет, он не создаётся.
Если я запускаю скрипт из командной строки (./writetest.cgi), всё работает, как и ожидалось.
Это работало на прошлой неделе до обновления. Есть ли какая-то новая функция песочницы, которая убивает мои приложения?
Я должен добавить, что SElinux отключён на этой системе, как подтверждено командой sestatus
.
Ответ оказался простым, но его трудно было найти.
Fedora использует systemd, и systemd реализовал много функций песочницы вокруг httpd
и других элементов службы. Это не совсем ново, но кажется, что Fedora только недавно включила их для httpd
(Apache).
Результат в том, что с текущими настройками по умолчанию каждая инстанция httpd
получает свою собственную временную версию /tmp. Любая CGI-программа, которая записывает в /tmp, видит, что это успешно, но в следующий раз, когда вы вызываете ту же CGI-программу, этого файла уже нет.
Аналогично, всё дерево файлов под /home
является только для чтения для CGI-программ.
В моей установке каждое приложение установлено под псевдопользователем под /home
. Например, система, которую я написал для отслеживания серийных номеров продуктов и клиентов, которым они отгружаются, расположена под /home/sales/serial
. Аналогично, служба Foswiki расположена под /home/foswiki2
.
Чтобы решить проблему, я использовал sudo systemctl edit httpd
, чтобы создать файл параметров переопределения для httpd.service
, содержащий
[Service]
PrivateTmp=false
ProtectHome=no
Затем я выполнил команды
sudo systemctl reload-daemons
и sudo systemctl restart httpd
Теперь всё работает так, как я привык.
Ответ или решение
Проблема с разрешениями на запись в CGI-приложениях после обновления Fedora 40
После обновления с Fedora 39 до Fedora 40 у вас возникли проблемы с работой CGI-приложений на Perl. Конкретно, приложение Foswiki не могло открыть файл журнала, а собственный CGI-скрипт не записывал данные в файл, даже несмотря на то, что файл имел корректные права доступа. Это повлияло на функциональность ваших приложений, что, безусловно, озадачило вас.
Условия проблемы
Основной код вашего тестового скрипта представляет собой простую операцию записи в файл:
my $file_to_write = "/tmp/writetest.txt";
unless (open(OUTFILE, ">>", $file_to_write)) {
print "Failed to open (for append) $file_to_write.<BR>\n";
}
printf "%s %s Write test to $file_to_write\n", ljpDate(), ljpTime();
printf OUTFILE "%s %s Write test\n", ljpDate(), ljpTime();
close OUTFILE;
print "Write completed<BR>\n";
Скрипт работал корректно при запуске из командной строки, однако, когда он выполнялся через Apache, файл не создавался и не записывался. Вы также отметили, что /tmp
стал недоступен для записи, и подозревали, что возникли проблемы с новыми функциями изоляции или безопасностью.
Причина проблемы
Как удалось выяснить, проблема заключалась в новых настройках безопасности, внедренных в систему systemd
с недавних обновлений Fedora, касающихся работы httpd
(Apache). В частности, httpd
стал использовать собственную временную директорию /tmp
, а изменения в ProtectHome
теперь делают директорию /home
доступной только для чтения для CGI-программ.
Это значит, что ваш CGI-скрипт, который пытается записывать в /tmp
или /home
, будет сталкиваться с ограничениями, что приводит к несоответствию между тем, что вы видите при тестировании и тем, что происходит в рабочем серверном окружении.
Решение проблемы
Чтобы устранить эту проблему, вам необходимо изменить параметры системы для Apache. Для этого выполните следующие шаги:
-
Создайте файл переопределения для службы
httpd
:sudo systemctl edit httpd
-
В открывшемся редакторе добавьте следующие строки:
[Service] PrivateTmp=false ProtectHome=no
Эти изменения отключат использование приватного временного хранилища, а также разрешат доступ к файловой системе
/home
для записей. -
Примените изменения и перезапустите сервис
httpd
:sudo systemctl daemon-reload sudo systemctl restart httpd
После выполнения этих команд ваши CGI-приложения должны снова работать корректно, позволяя записи в файлы, как это было до обновления.
Заключение
Обновление операционной системы может неожиданно повлиять на работу ваших приложений, особенно когда новые функции безопасности начинают действовать по умолчанию. В таких ситуациях важно анализировать изменения в конфигурации системы и адаптироваться к ним. Применяя вышеуказанные рекомендации, вы сможете вернуть ваше приложение в рабочее состояние и избежать повторных проблем в будущем.