Что означает ошибка SELinux Permission Denied
Ошибка с текстом AVC denied (Access Vector Cache) или Permission denied в контексте SELinux означает, что механизм обязательного контроля доступа (MAC) блокирует операцию, хотя стандартные права доступа (chmod/chown) могут быть настроены корректно. Сообщение обычно выглядит так:
type=AVC msg=audit(1617890123.456:123): avc: denied { read } for pid=1234 comm="nginx" name="config.php" dev="dm-0" ino=123456 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file
Ошибка возникает при попытке процесса (например, nginx, mysqld) получить доступ к файлу, сокету или другому объекту с неразрешённым для его домена SELinux (например, httpd_t) типом контекста (например, user_home_t).
Причины возникновения
- Неправильный контекст безопасности файла. Файл, который должен быть доступен демону (веб-серверу, БД), имеет тип контекста по умолчанию (например,
user_home_tдля файлов в/home), а не специальный (например,httpd_sys_content_t). - Неправильный контекст процесса. Демон запущен с нестандартным контекстом, который не имеет прав на доступ к нужным типам файлов.
- Нестандартное расположение файлов. Файлы сервисов размещены в каталогах, не предусмотренных политикой SELinux по умолчанию (например, веб-файлы в
/srv/wwwвместо/var/www/html). - Изменение политики или обновление ОС. После обновления пакета или ядра политика SELinux может измениться, и старые контексты перестанут быть валидными.
- Ошибка в пользовательской политике. Написанный вручную модуль политики (
*.teфайл) содержит ошибки или не покрывает все случаи.
Способ 1: Быстрая диагностика и восстановление контекста (restorecon)
Это основной и самый частый способ решения.
- Найдите проблемный файл. Используйте
ausearchдля поиска последних ошибок AVC:sudo ausearch -m avc -ts recent
Или просмотрите лог напрямую:sudo cat /var/log/audit/audit.log | grep "avc:.*denied"
В выводе найдите путь к файлу (name="...") и тип контекста (tcontext=...). - Проверьте текущий контекст файла:
ls -Z /полный/путь/к/файлу - Восстановите правильный контекст. Чаще всего нужно применить контекст, который соответствует местоположению файла по политике. Для стандартных путей:
sudo restorecon -v /полный/путь/к/файлу
Если нужно применить ко всему каталогу рекурсивно:sudo restorecon -Rv /путь/к/каталогу - Перезапустите сервис (если он уже был запущен) и проверьте, исчезла ли ошибка.
sudo systemctl restart <имя_сервиса>
💡 Совет: Если
restoreconне помог, возможно, файл находится в нестандартном месте. Вам нужно определить, какой тип контекста (-t) должен быть у этого типа файла для данного сервиса (например,httpd_sys_content_tдля статики Apache).
Способ 2: Ручное изменение контекста (chcon)
Если файл должен иметь особый, нестандартный контекст, который не покрывается политикой по умолчанию, используйте chcon.
- Определите нужный тип контекста. Для популярных сервисов типы известны:
- Веб-сервер (Apache/Nginx):
httpd_sys_content_t(файлы),httpd_sys_rw_content_t(директории для записи). - FTP-сервер (vsftpd):
public_content_rw_t. - NFS-шары:
nfs_t. Полный список типов можно найти в/etc/selinux/targeted/contexts/categorized_contexts.
- Веб-сервер (Apache/Nginx):
- Примените контекст к файлу или каталогу:
sudo chcon -t httpd_sys_content_t /путь/к/файлу
Для рекурсивного применения к каталогу:sudo chcon -Rt httpd_sys_content_t /путь/к/каталогу
⚠️ Важно: Изменения, сделанные через
chcon, не являются постоянными. Они будут сброшены при следующем выполненииrestoreconили перезагрузке системы. Для постоянного решения используйте Способ 3.
Способ 3: Создание постоянного правила (пользовательский модуль)
Это правильный способ, если файл должен всегда иметь нестандартный контекст или требуется разрешить специфическое действие.
- Сгенерируйте модуль политики на основе логов аудита. Установите пакет
policycoreutils-python-utils(если нет). Затем:sudo grep "denied" /var/log/audit/audit.log | audit2allow -M my_custom_policy
Эта команда создаст два файла:my_custom_policy.pp(бинарный модуль) иmy_custom_policy.te(исходный текст). - Проверьте содержимое
.teфайла. Убедитесь, что правила логичны и не открывают излишних прав. Пример содержимого:module my_custom_policy 1.0; require { type httpd_t; type user_home_t; class file { read open }; } #============= httpd_t ============== allow httpd_t user_home_t:file { read open }; - Установите модуль:
sudo semodule -i my_custom_policy.pp - Убедитесь, что модуль загружен:
sudo semodule -l | grep my_custom_policy - Перезапустите сервис. После этого правило будет действовать постоянно.
Способ 4: Временное отключение/перевод в Permissive (для диагностики)
Это не решение проблемы, а инструмент диагностики! Не оставляйте систему в этом режиме надолго.
- Временно (до перезагрузки) переведите SELinux в режим
permissive:sudo setenforce 0
В этом режиме SELinux только логирует нарушения, но не блокирует их. Проверьте, работает ли приложение. Если да — проблема точно в SELinux. - Чтобы вернуть режим
enforcing:sudo setenforce 1 - Для постоянного изменения режима (не рекомендуется без понимания последствий) отредактируйте файл
/etc/selinux/config:SELINUX=disabled # или permissive
и перезагрузите систему.
⚠️ Важно: Отключение SELinux (
disabled) — крайняя мера, которая сводит на нет всю систему защиты. Всегда ищите решение через настройку политик (Способы 1-3).
Профилактика
- Размещайте файлы сервисов в стандартных каталогах (
/var/www,/srv/ftp,/home/*/public_htmlс правильным контекстом). - При создании новых каталогов для сервисов сразу задавайте правильный контекст с помощью
semanage fcontext:sudo semanage fcontext -a -t httpd_sys_rw_content_t "/my_app/data(/.*)?" sudo restorecon -Rv /my_app/data - Регулярно проверяйте логи аудита (
/var/log/audit/audit.log) на наличие новых AVC-сообщений после обновлений системы или ПО. - Используйте утилиты
audit2whyиaudit2allowдля понимания, почему доступ был запрещён, прежде чем просто разрешать всё. - Не отключайте SELinux на production-серверах. Настройка политики — единственно верный путь.
Способ 5: Использование утилиты sealert для анализа
Установите пакет setroubleshoot (если не установлен). Эта утилита преобразует сырые логи аудита в читаемые отчёты с рекомендациями.
- Запустите анализ:
sudo sealert -a /var/log/audit/audit.log
Или для последних сообщений:sudo sealert - Изучите вывод.
sealertчасто предлагает конкретные команды для исправления, например:sudo chcon -t <тип> <файл>sudo semanage port -a -t <тип> -p <протокол> <порт>- Предложение создать модуль политики.
- Следуйте рекомендациям, но всегда проверяйте, что они соответствуют вашей архитектуре и не нарушают безопасность.
Этот способ особенно полезен, когда причина ошибки неочевидна (например, доступ к сетевому порту или нестандартному типу объекта).