Почему программа Perl CGI не может записывать в файлы на Fedora 40 с Apache?

Вопрос или проблема

На прошлой неделе я обновил свой файл-сервер на 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), все работает как ожидается.
Это работало на прошлой неделе до обновления. Существует ли какая-то новая функция песочницы, которая мешает моим приложениям?

Это похоже на головную боль с SE Linux.

Проверьте, включен ли SE Linux, сделав это:

sestatus

Вывод должен выглядеть примерно так:

Статус SELinux:                 включен
Маршрут SELinuxfs:             /sys/fs/selinux
Корневая директория SELinux:    /etc/selinux
Загруженное имя политики:       targeted
Текущий режим:                  enforcing
Режим из файла конфигурации:    enforcing
Статус политики MLS:            включен
Статус политики deny_unknown:   разрешен
Проверка защиты памяти:         актуально (безопасно)
Максимальная версия политики ядра: 33

Если это так, вы можете включить доступ CGI для HTTPD так:

sudo setsebool -P httpd_enable_cgi on;

Затем измените файловую систему для SE Linux вот так:

sudo semanage fcontext -a -t httpd_sys_script_exec_t /var/www/cgi-bin/script.cgi
sudo restorecon -vR /var/www/cgi-bin/script.cgi

И все должно заработать.


Заметки: Просто имейте в виду, что вам может понадобиться установить policycoreutils-python, чтобы запустить эти команды. Я делаю это для установки этого пакета на Red Hat 7:

sudo yum install policycoreutils-python

В противном случае вы можете отключить SE Linux вот так, чтобы выполнить тесты на скрипте:

sudo setenforce permissive

Чтобы навсегда отключить SE Linux, отредактируйте конфигурацию SE Linux (/etc/selinux/config) и измените значение:

SELINUX=enforcing

На это:

SELINUX=permissive

И перезагрузите машину, чтобы это значение вступило в силу.

Ответ или решение

Почему CGI-программа на Perl не может записывать файлы на Fedora 40 с использованием Apache

Недавнее обновление с Fedora 39 до Fedora 40 могло повлиять на работу ваших CGI-приложений на Perl по нескольким причинам, среди которых ключевой является состояние SELinux. Давайте подробно рассмотрим, почему ваша CGI-программа не может записывать файлы, даже если она работала без сбоев до обновления.

1. Обновления и изменения в настройках безопасности

После обновления операционной системы возможно изменение настроек и политик безопасности, которые могут препятствовать нормальному выполнения ваших CGI-скриптов. SELinux (Security-Enhanced Linux) — это механизм управления доступом, который может блокировать определенные действия и доступ отдельных процессов к файловой системе.

2. Проверка состояния SELinux

Первый шаг — это проверить, активен ли SELinux на вашей системе. Для этого выполните команду:

sestatus

Если результатом будет сообщение о том, что SELinux включен и работает в режиме enforcing, это может означать, что ваши CGI-скрипты ограничены в доступе к файлам из-за текущих политик безопасности.

3. Конфигурация SELinux для CGI

Если вы установили, что SELinux активирован, следующим шагом будет включение поддержки для CGI в Apache. Введите следующую команду:

sudo setsebool -P httpd_enable_cgi on

Также необходимо убедиться, что ваш CGI-скрипт имеет правильный контекст безопасности. Выполните следующие команды:

sudo semanage fcontext -a -t httpd_sys_script_exec_t /var/www/cgi-bin/script.cgi
sudo restorecon -vR /var/www/cgi-bin/script.cgi

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

4. Проверка прав доступа

Вы упомянули, что файл /tmp/writetest.txt уже существует и имеет права доступа 666 (или -rw-rw-rw-), и что он принадлежит пользователю apache. Однако если Apache работает с другим пользователем (например, www-data или nobody), это также может быть причиной проблем с доступом. Проверьте, какой пользователь запускает Apache, и при необходимости измените права доступа к файлу или смените владельца файла на apache.

5. Тестирование и отладка

Чтобы протестировать, стали ли ваши файловые операции работать снова, вы можете временно установить SELinux в permissive режим, что позволит вам увидеть предупреждения о блокировке, не препятствуя выполнению скриптов:

sudo setenforce permissive

Если после этих изменений ваша программа заработает, это подтвердит, что проблема действительно заключалась в SELinux.

Заключение

Обновление вашей системы открыло новые аспекты управления безопасностью, которые влияют на работу CGI-приложений на Perl. SELinux может ограничивать доступ к файловой системе, что и произошло в вашем случае. Следуя данным рекомендациям и выполняя соответствующие команды, вы сможете восстановить работоспособность своих CGI-скриптов. Постоянный контроль за политиками безопасности будет полезен для предотвращения подобных инцидентов в будущем.

Оцените материал
Добавить комментарий

Капча загружается...