Linux AVC DeniedВысокая

Ошибка SELinux Permission Denied: причины и 4 способа исправления

Статья подробно разбирает ошибку 'Permission denied' от SELinux — механизма безопасности Linux. Вы узнаете, почему она возникает, как читать логи аудита и исправить проблему через корректировку контекстов или настройку политик.

Обновлено 8 апреля 2026 г.
15-30 мин
Средняя
FixPedia Team
Применимо к:RHEL 8/9CentOS 8/9Fedora 35+AlmaLinux/Rocky Linux 8/9

Что означает ошибка 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).

Причины возникновения

  1. Неправильный контекст безопасности файла. Файл, который должен быть доступен демону (веб-серверу, БД), имеет тип контекста по умолчанию (например, user_home_t для файлов в /home), а не специальный (например, httpd_sys_content_t).
  2. Неправильный контекст процесса. Демон запущен с нестандартным контекстом, который не имеет прав на доступ к нужным типам файлов.
  3. Нестандартное расположение файлов. Файлы сервисов размещены в каталогах, не предусмотренных политикой SELinux по умолчанию (например, веб-файлы в /srv/www вместо /var/www/html).
  4. Изменение политики или обновление ОС. После обновления пакета или ядра политика SELinux может измениться, и старые контексты перестанут быть валидными.
  5. Ошибка в пользовательской политике. Написанный вручную модуль политики (*.te файл) содержит ошибки или не покрывает все случаи.

Способ 1: Быстрая диагностика и восстановление контекста (restorecon)

Это основной и самый частый способ решения.

  1. Найдите проблемный файл. Используйте ausearch для поиска последних ошибок AVC:
    sudo ausearch -m avc -ts recent
    

    Или просмотрите лог напрямую:
    sudo cat /var/log/audit/audit.log | grep "avc:.*denied"
    

    В выводе найдите путь к файлу (name="...") и тип контекста (tcontext=...).
  2. Проверьте текущий контекст файла:
    ls -Z /полный/путь/к/файлу
    
  3. Восстановите правильный контекст. Чаще всего нужно применить контекст, который соответствует местоположению файла по политике. Для стандартных путей:
    sudo restorecon -v /полный/путь/к/файлу
    

    Если нужно применить ко всему каталогу рекурсивно:
    sudo restorecon -Rv /путь/к/каталогу
    
  4. Перезапустите сервис (если он уже был запущен) и проверьте, исчезла ли ошибка.
    sudo systemctl restart <имя_сервиса>
    

💡 Совет: Если restorecon не помог, возможно, файл находится в нестандартном месте. Вам нужно определить, какой тип контекста (-t) должен быть у этого типа файла для данного сервиса (например, httpd_sys_content_t для статики Apache).

Способ 2: Ручное изменение контекста (chcon)

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

  1. Определите нужный тип контекста. Для популярных сервисов типы известны:
    • Веб-сервер (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.
  2. Примените контекст к файлу или каталогу:
    sudo chcon -t httpd_sys_content_t /путь/к/файлу
    

    Для рекурсивного применения к каталогу:
    sudo chcon -Rt httpd_sys_content_t /путь/к/каталогу
    

⚠️ Важно: Изменения, сделанные через chcon, не являются постоянными. Они будут сброшены при следующем выполнении restorecon или перезагрузке системы. Для постоянного решения используйте Способ 3.

Способ 3: Создание постоянного правила (пользовательский модуль)

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

  1. Сгенерируйте модуль политики на основе логов аудита. Установите пакет policycoreutils-python-utils (если нет). Затем:
    sudo grep "denied" /var/log/audit/audit.log | audit2allow -M my_custom_policy
    

    Эта команда создаст два файла: my_custom_policy.pp (бинарный модуль) и my_custom_policy.te (исходный текст).
  2. Проверьте содержимое .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 };
    
  3. Установите модуль:
    sudo semodule -i my_custom_policy.pp
    
  4. Убедитесь, что модуль загружен:
    sudo semodule -l | grep my_custom_policy
    
  5. Перезапустите сервис. После этого правило будет действовать постоянно.

Способ 4: Временное отключение/перевод в Permissive (для диагностики)

Это не решение проблемы, а инструмент диагностики! Не оставляйте систему в этом режиме надолго.

  1. Временно (до перезагрузки) переведите SELinux в режим permissive:
    sudo setenforce 0
    

    В этом режиме SELinux только логирует нарушения, но не блокирует их. Проверьте, работает ли приложение. Если да — проблема точно в SELinux.
  2. Чтобы вернуть режим enforcing:
    sudo setenforce 1
    
  3. Для постоянного изменения режима (не рекомендуется без понимания последствий) отредактируйте файл /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 (если не установлен). Эта утилита преобразует сырые логи аудита в читаемые отчёты с рекомендациями.

  1. Запустите анализ:
    sudo sealert -a /var/log/audit/audit.log
    

    Или для последних сообщений:
    sudo sealert
    
  2. Изучите вывод. sealert часто предлагает конкретные команды для исправления, например:
    • sudo chcon -t <тип> <файл>
    • sudo semanage port -a -t <тип> -p <протокол> <порт>
    • Предложение создать модуль политики.
  3. Следуйте рекомендациям, но всегда проверяйте, что они соответствуют вашей архитектуре и не нарушают безопасность.

Этот способ особенно полезен, когда причина ошибки неочевидна (например, доступ к сетевому порту или нестандартному типу объекта).

Часто задаваемые вопросы

Чем ошибка SELinux Permission Denied отличается от обычной 'Permission denied' (chmod)?
Можно ли просто отключить SELinux, чтобы решить проблему?
Какой файл логов нужно смотреть при ошибке SELinux?
Что такое контекст безопасности (context) в SELinux?

Полезное

Определите источник ошибки в логах
Проверьте текущий контекст файла
Восстановите правильный контекст
Создайте локальную политику (если нужно)

Эта статья помогла вам решить проблему?