В процессе эксплуатации систем с SELinux я выделил несколько интересных кейсов, решения которых вряд-ли описаны в Интернете. Сегодня я решил поделиться с вами своими наблюдениями в надежде, что число сторонников SELinux еще немного возрастет :)
0. Переустановка policy package
Если вы не знали, то сообщаю: весь SELinux насквозь файловый, и никакой магии там нет. Поэтому можно прям при включенном SELinux переустановить пакет полиси, если что-то пошло не так.
Пример для centos 7 & selinux-policy-minimum
#!/bin/sh
setenforce 0
semanage export > exports.semanage
yum remove -y selinux-policy-minimum
rm -rf /etc/selinux/minimum
yum install -y selinux-policy-minimum
semodule -RB
semanage import -f exports.semanage
1. SELinux в permissive mode, но часть команд не работает
Invalid process context
Причина в том, что некоторые программы пытаются изменить контекст ( по аналогии с setuid/setgid ) перед exec(3), но используют неверный контекст для этого.
Пример: демон crond, который обрабатывает crontab пользователя user, контекст которого неизвестен. В этом случае он execlp(3) вернет ошибку 'Invalid context'.
Решение
- Сделать policy reload ( semodule -R )
- Посмотреть какой пользователь используется
- Посмотреть какой для него selinux-пользователь (semanage login -l)
- Убедиться в наличии файла /etc/selinux/$type/contexts/users/$username
- Если файла нет — сбросить на дефолт настройки при помощи переустановки policy package.
Invalid file context
Если по каким-то причинам авторелейбл не произошел и файл остался вообще без контекста, либо с мусором вместо контекста, доступ к нему так-же может быть заблокирован из-за того, что open(3) упадет при попытке сравнить контексты.
Решение
- Сделать restorecon /path -Rv
- Убедиться в правильности контекстов и в том, что загружены все модули
- Сделать policy reload ( semodule -R )
- Если не помогло — сбросить на дефолт настройки при помощи переустановки policy package.
2. После включения SELinux и перезагрузки все процессы запущены от kernel_t / В логах много ошибок про доступ к kernel_t
Как происходит включение SELinux?
- Создание файла /.autorelabel
- Перезагрузка, ядро видит этот файл и запускает autorelabeling
- Перезагрузка еще раз и запуск ядра с контекстом kernel_t.
Проблемы наступают на этапе два: ядро знает только о контекстах модулей, которые были явно включены до перезагрузки. Например, если не был включен модуль systemd, то:
- Ядро запущено с контекстом kernel_t
- Правил перехода контекста от kernel_t к systemd не срабатывают, т.к. relabel не назначил ему контекст init_exec_t, systemd наследует контекст kernel_t
- Для демонов, которые запускает systemd, тоже не срабатывают правила перехода контекста, поскольку правила написаны для контекста init_t, а не kernel_t. Все демоны запущены от kernel_t.
- ....
- FAIL
Решение
- Перед созданием /.autorelabel вручную включить все нужные модули командой semodule -e $module, или
- Сделать restorecon -R / после перезагрузки и перезагрузить систему еще раз, или
- Сделать systemctl daemon-reexec и перезапустить всех демонов вручную, если вторая перезагрузка неприемлима
- Воспользоваться утилитой offrestorecon* вместо /.autorelabel
3. После обновления policy package ничего не работает, все команды пишут ошибки
Это проблема возникает тогда, когда после обновления не могут быть решены циклические зависимости между модулями или контекстами. Например:
- В версии 1.0 были сделаны настройки и добавлен модуль local_module
- local_module проэкспортировал контекст local_module_file_t
- Этот контекст при помощи semanage был назначен для "/opt/local(/.*)?"
При обновлении до версии 1.1 модуль local_module будет установлен после того, как будут применены настройки контекста для "/opt/local", что может привести к циклической зависимости. На самом деле от одного модуля это бывает редко, а вот когда их 30 и они ссылаются друг на друга и несут часть настроек "снаружи" ( через semanage fcontext или semanage port например ) — вот тогда проблемы почти гарантированы.
Решение
- Переставить policy package ( см. пункт 0 ), или
- Выполнить последовательно ДО обновления
semanage export > outfile semanage fcontext -D semanage user -D semanage port -D semanage login -D # update your packages semanage import -f outfile
4. Долгая перезагрузка при включении SELinux
Autorelabeling — боль для владельцев больших серверов. Средний сервер с базой данных может перезагружаться 3-4 часа из-за включения SELinux, что абсолютно неприемлемо для бизнеса.
Решение
На самом деле метки на файлах лежат в extended-атрибутах файловой системы, доступ к которым можно получить при помощи команд getfattr(1)/setfattr(1)/attr(1). Атрибут называется security.selinux и содержит контекст в виде строки. При этом даже на выключенном SELinux работает команда matchpathcon из libselinux-utils, которая показывает дефолтный контекст для того или иного пути.
Совмещая оба этих факта, получаем возможность сделать audorelabel прямо во время работы сервера, не тратя на это время при перезагрузке.
Сегодня днем я выложил свой код на github, утилита называется offrestorecon. Не забудьте предварительно включить все нужные модули и удалить файл /.autorelabel!
5. После перезагрузки слетели все настройки переменных
Решение
Используйте ключ -P для setsebool, либо semanage boolean
Вместо послесловия
Если вам интересна тема SELinux, присылайте комментарии по своим странным кейсам и их решениям, я буду добавлять их в эту статью. Возможно, что это сделает жизнь следующих security-админов немного проще.
Автор: kreon