Короткий ответ

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 getenforce command not found — это не SELinux;
  • кто-то уже поставил Permissive в crontab.
ОСЧто смотреть первым
Ubuntuaa-status, `dmesg
Rocky/RHELgetenforce, ausearch -m AVC
Контейнерполитика хоста + внутренний MAC

Возможные причины

  1. Новый каталог данных без semanage fcontext.
  2. Сервис слушает нестандартный порт без semanage port.
  3. Boolean выключен (httpd_can_network_connect).
  4. После rsync нет --xattrs, контекст unlabeled_t.
  5. На Ubuntu ждут SELinux, а DENIED пишет AppArmor.
  6. Кастомный unit от root с типом init_t vs 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 в окно.