Короткий ответ
SELinux лечат чтением AVC, правкой контекста (restorecon, chcon только как тест, потом fcontext) или узким модулем политики. Не setenforce 0 и не SELINUX=disabled в /etc/selinux/config как решение. На Ubuntu 22.04/24.04 MAC по умолчанию — AppArmor, не SELinux: сначала aa-status и статья AppArmor. Если вы всё же включили SELinux на Ubuntu или чините Rocky/RHEL рядом — ниже команды обоих миров. Хост host.example (10.0.20.10), работы от admin с sudo. Сервис не обязан быть root: unit User=.
Симптомы и как отличить
- Приложение «Permission denied», unix-права
660правильные; - на RHEL
ausearch -m AVC -ts recentнепусто; - на Ubuntu
getenforcecommand not found — это не SELinux; - кто-то уже поставил Permissive в crontab.
| ОС | Что смотреть первым |
|---|---|
| Ubuntu | aa-status, `dmesg |
| Rocky/RHEL | getenforce, ausearch -m AVC |
| Контейнер | политика хоста + внутренний MAC |
Возможные причины
- Новый каталог данных без
semanage fcontext. - Сервис слушает нестандартный порт без
semanage port. - Boolean выключен (
httpd_can_network_connect). - После rsync нет
--xattrs, контекстunlabeled_t. - На Ubuntu ждут SELinux, а DENIED пишет AppArmor.
- Кастомный unit от root с типом
init_tvs confined.
Диагностика
Ubuntu (штатно AppArmor)
which getenforce sestatus aa-status
sudo aa-status
sudo dmesg | grep -iE 'apparmor|denied' | tail
sudo journalctl -k -n 50 | grep -i apparmorЕсли getenforce нет — не ставьте SELinux «для галочки» на боевой Ubuntu без проекта. Идите в AppArmor.
Если SELinux всё же активен (RHEL/Rocky или экспериментальный Ubuntu)
getenforce
sestatus
sudo ausearch -m AVC -ts recent --raw | tail
sudo ausearch -m AVC -ts today | aureport -a
sudo journalctl -t setroubleshoot -n 20 --no-pagerКонтекст файлов и порта:
ls -Z /var/lib/myservice
sudo ss -tlnp
sudo semanage port -l | grep 8080 || true
ps -eZ | grep myserviceНе запускайте audit2allow -M до чтения AVC: сгенерируете allow на всё.
Решение
Сценарий A. Ubuntu, это AppArmor
Не чините SELinux. Перейдите к профилю AppArmor: complain временно, aa-logprof, снова enforce. Не apparmor=0.
Сценарий B. Неверный файловый контекст (RHEL-семейство)
Тест:
sudo restorecon -Rv /var/lib/myserviceПостоянно:
sudo semanage fcontext -a -t httpd_sys_rw_content_t '/var/lib/myservice(/.*)?'
sudo restorecon -Rv /var/lib/myserviceТип берите из существующих аналогичных путей (matchpathcon), не выдумывайте. chcon без semanage слетит после restorecon.
Сценарий C. Порт
sudo semanage port -a -t http_port_t -p tcp 8080Если порт уже занят другим типом — читайте ошибку semanage, не disable.
Сценарий D. Boolean
getsebool -a | grep httpd
sudo setsebool -P httpd_can_network_connect 1Только нужный boolean, не пачка «все httpd_* 1».
Сценарий E. Кастомный модуль
sudo ausearch -m AVC -ts today --raw | audit2allow -m myserviceПрочитайте .te. Уберите allow, которые не про ваш путь. Затем checkmodule/semodule_package/semodule -i по доке вашей версии. Не -AllowAll.
Временный permissive домена (лучше глобального setenforce 0):
sudo semanage permissive -a myservice_tСнимите после фикса. Глобальный enforcing верните:
sudo setenforce 1
getenforceДолжно быть Enforcing.
Логи AVC берегите: удалённая копия, auditd.
Как не смешивать инструменты. На Ubuntu ausearch без auditd/SELinux даст пустоту — это не «AVC нет», это другой MAC. Не ставьте selinux-policy-default из universe на боевой Ubuntu «чтобы команды из RHEL-гайда заработали»: получите два MAC или сломанную загрузку. Если цель — учиться SELinux, берите Rocky/RHEL VM.
На RHEL после restorecon сервис всё ещё падает: смотрите ls -Z на unix-сокет в /run/myservice.sock. Сокеты часто system_u:object_r:var_run_t, а confined httpd ждёт httpd_var_run_t. semanage fcontext на /run/myservice(/.*)? + restart unit, чтобы сокет пересоздался.
audit2allow -w (если пакет setroubleshoot/policycoreutils-python) объясняет boolean человеческим языком. Это лучше слепого -M. Не игнорируйте «dontaudit»: тогда AVC нет, а доступ всё равно нет — semodule -DB на копии для отладки, потом верните dontaudit, не оставляйте «громкий» audit навсегда без нужды.
Контейнеры на RHEL: container_t vs привилегированный. :privileged снимает SELinux ограничения контейнера — это не «починить AVC», это выключить изоляцию. Используйте :Z/:z на volume корректно (знайте разницу shared vs private label).
Ubuntu-админ, который принёс setenforce 0 с прошлого места работы: верните enforcing если SELinux был включён; если это Ubuntu — удалите привычку, включите голову на AppArmor. Запрет в регламенте: «disabled MAC» как решение тикета = не принимается.
Как проверить, что проблема устранена
- Сервис отвечает (health).
getenforce→ Enforcing (если SELinux используется).- Новых AVC по этому ключу нет (
ausearchза 15 минут тишина при нагрузке). - На Ubuntu
aa-statusпрофили в enforce, не весь стек в complain. - Firewall не выключен.
Если не помогло
- AVC другие: новый путь, NFS
context=mount. unconfined_service_t— вы не в confined unit; это не повод disable, но и не «SELinux виноват».- Ubuntu пакеты
selinux-policyиз universe конфликтуют с AppArmor — не смешивайте без проекта. - Контейнер
:privileged«решил» AVC ценой root хоста — откатите, чините контекст.
Профилактика
- Деплой с restorecon в ansible.
- Не rsync без xattr.
- Мониторинг AVC.
- Запрет в политике: disabled MAC.
FAQ
Почему статья SELinux в разделе Ubuntu?
Поиск и чужие HOWTO приводят setenforce 0 на Ubuntu. Штатно там AppArmor. Команды RHEL — чтобы не отключать MAC, когда SELinux реально есть.
Permissive навсегда лучше disabled?
Оба снимают защиту. Permissive хотя бы пишет AVC. Цель — enforcing.
audit2allow без чтения
Получите allow myservice_t unlabeled_t:file { … } на полдиска. Нет.
Можно ли отключить только для Docker
sp_virt_use/container-selinux — отдельная политика. Не SELINUX=disabled на хосте.
setenforce 1 после отладки не держится
Значит в config permissive/disabled или GRUB. Исправьте на enforcing, reboot в окно.