# SELinux и AppArmor - Mandatory Access Control _Процессы и ресурсы · LinuxLab Knowledge Base_ **TL;DR:** SELinux и AppArmor - это MAC: дополнительный слой контроля поверх обычных permissions. Запрещают процессу делать что не входит в его профиль/тип. ## DAC vs MAC - **DAC** (Discretionary Access Control) - обычные [file-permissions](/kb/file-permissions.md), UID/GID/rwx. «Владелец решает кому что можно». - **MAC** (Mandatory Access Control) - system-wide политика, юзеры её обойти не могут. «Этот процесс может писать ТОЛЬКО в эти пути, биндить ТОЛЬКО эти порты - независимо от того что в DAC». Обе работают одновременно. Чтобы что-то разрешить - должны разрешить **и DAC и MAC**. Запретить - достаточно одного. Реализация - Linux Security Modules (LSM): SELinux, AppArmor, SMACK, TOMOYO, Landlock. На системе обычно активен **один**. ## SELinux Распространён в RHEL/CentOS/Fedora/CoreOS. Работает с **labels**: - Каждый процесс имеет **context**: `user:role:type:level` - Каждый файл/сокет имеет такой же **context** - Политика говорит «этот type может делать ЭТО с этим type'ом» Самое важное - **type** (например, `httpd_t` для nginx, `var_log_t` для логов). Бесчисленные правила вроде «`httpd_t` may write `httpd_log_t`». ### Просмотр ```bash getenforce # Enforcing / Permissive / Disabled sestatus # подробно ls -Z /var/log/messages # увидеть SELinux-context файла ps -eZ | head # context процессов id -Z # мой context ausearch -m AVC -ts recent # недавние denials в audit log ``` ### Режимы - **Enforcing** - правила применяются, нарушения блокируются - **Permissive** - правила НЕ применяются, но нарушения логируются (для отладки и сборки своего профиля) - **Disabled** - отключено (требует ребута) ```bash sudo setenforce 0 # на лету в permissive sudo setenforce 1 # обратно в enforcing # Постоянно - /etc/selinux/config: SELINUX=enforcing|permissive|disabled ``` ### Когда что-то ломается Симптом: «обычный chmod 755 правильный, всё проверено, но nginx не читает файл». Подозрение SELinux: ```bash sudo ausearch -m AVC -ts recent | tail -5 # type=AVC msg=audit(...): avc: denied { read } for pid=1234 comm="nginx" # ... scontext=system_u:system_r:httpd_t:s0 # ... tcontext=unconfined_u:object_r:user_home_t:s0 ``` Видим: `httpd_t` пытается читать `user_home_t` - запрещено. Решения: - Перевесить правильный label: `sudo chcon -t httpd_sys_content_t /path/file` - Постоянно: `sudo semanage fcontext -a -t httpd_sys_content_t '/path(/.*)?'` + `sudo restorecon -Rv /path` - Создать кастомное правило (audit2allow): ```bash sudo ausearch -m AVC -ts recent | audit2allow -M mymodule sudo semodule -i mymodule.pp ``` ## AppArmor Распространён в Ubuntu/Debian/SUSE. Работает с **path-based** профилями (а не labels). Профиль - это файл в `/etc/apparmor.d/`: ``` /usr/sbin/nginx { /etc/nginx/** r, /var/log/nginx/* w, /var/www/** r, network tcp, capability net_bind_service, } ``` Бинарь привязан к профилю; что не разрешено - запрещено. ### Просмотр ```bash sudo aa-status # сводка: загруженные профили, режимы cat /sys/kernel/security/apparmor/profiles ``` ### Режимы - **enforce** - блокирует - **complain** - логирует но не блокирует (= SELinux permissive для одного профиля) - **disabled** ```bash sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx sudo aa-complain /etc/apparmor.d/usr.sbin.nginx sudo aa-disable /etc/apparmor.d/usr.sbin.nginx ``` ### Дебаг Denials в kern.log / journal: ```bash sudo dmesg | grep apparmor= sudo journalctl -k | grep DENIED ``` Утилита `aa-genprof ` - запускает программу в complain-режиме, собирает доступы, превращает в профиль. Очень удобно для написания своих профилей. ## SELinux vs AppArmor | | SELinux | AppArmor | |---|---|---| | Подход | labels на каждом объекте | path-based профили | | Гранулярность | очень высокая | средняя | | Сложность | высокая | средняя | | Default | RHEL family | Ubuntu / SUSE | | Reload | sometimes требует relabel ФС | hot-reload профилей | В контейнерах (Docker, podman, k8s) используются **оба**: профиль применяется к контейнерному процессу. ## Когда отключают (и почему это плохо) Соблазн: «не работает, выключу». Это снимает целый слой защиты. Лучше: 1. Перевести в permissive/complain (даст логи без блока) 2. Понять что именно denied 3. Скорректировать политику или label Полное отключение разумно только если у тебя другая система изоляции (контейнеры + namespaces + seccomp + capabilities). ## Связь со стеком - **MAC** (SELinux/AppArmor) - что МОЖНО открыть/слушать/писать - **DAC** ([file-permissions](/kb/file-permissions.md)) - обычные права - **[capabilities](/kb/capabilities.md)** - какие привилегии root есть - **[seccomp](/kb/seccomp.md)** - какие syscall'ы разрешены Это четыре независимых слоя. Прод-серверы используют все четыре. ## Команды ```bash getenforce ``` Текущий режим SELinux (Enforcing/Permissive/Disabled) ```bash sudo aa-status ``` Сводка по AppArmor - загруженные профили и их режимы ```bash ls -Z /var/log/messages ``` SELinux-context файла (после обычных permissions) ```bash sudo ausearch -m AVC -ts recent | audit2allow -M mymod ``` Сгенерировать SELinux-policy module из недавних denials ```bash sudo journalctl -k | grep -i 'denied\|apparmor=' ``` Denials в логе ядра - отладка MAC-нарушений ## См. также - [File permissions: rwx и chmod](/kb/file-permissions.md) - [Linux capabilities - биты привилегий](/kb/capabilities.md) - [seccomp - фильтр системных вызовов](/kb/seccomp.md) - [Kernel modules - LKM, modprobe, signing, DKMS](/kb/kernel-modules.md) - [SELinux policy - типы, домены, audit2allow](/kb/selinux-policy.md) - [auditd - syscall и file audit](/kb/auditd.md)