контекст selinux для ExecStart пользовательского сервиса systemd

Вопрос или проблема

У меня есть Type=simple /etc/systemd/system/custom.service.
В нем указано ExecStart=/root/scripts/custom.sh.
Я использую это, чтобы различные административные задачи выполнялись автоматически после загрузки.
Это хорошо работало до Redhat 7.9, проблем с selinux не было при установленном selinux=enforcing.

В RHEL 8.8 я получаю отказ вызова AVC в /var/log/messages.

systemd[1]: Запущен пользовательский сервис.
systemd[96691]: custom.service: Не удалось выполнить команду: Отказ в доступе
systemd[96691]: custom.service: Не удалось на этапе EXEC при порождении /root/scripts/custom.sh: Отказ в доступе
systemd[1]: custom.service: Основной процесс завершился, код=выход, статус=203/EXEC
systemd[1]: custom.service: Не удалось с результатом 'exit-code'.

SELinux предотвращает доступ к выполнению для /usr/lib/systemd/systemd к файлу custom.sh. 
Для получения полных сообщений SELinux выполните: sealert -l 84fa818f-e23a-4686-afb5-3f2399d0d6ea

setroubleshoot[96693]: SELinux предотвращает доступ к выполнению для /usr/lib/systemd/systemd к файлу custom.sh.#012#012
*****Plugin catchall (100. confidence) предлагает
**************************#012#012Если вы считаете, что systemd следует разрешить доступ к выполнению
к файлу custom.sh по умолчанию.#012Тогда вам следует сообщить об этом как об ошибке.#012Вы можете сгенерировать
локальный модуль политики, чтобы разрешить этот доступ.
#012Пока#012разрешите этот доступ, выполнив:
#012# ausearch -c '(ation.sh)' --raw | audit2allow -M my-ationsh#012# semodule -X 300 -i my-ationsh.pp#012

Так что я знаю, что мой скрипт /root/scripts/custom.sh не имеет правильного контекста selinux. Но что мне использовать?

Мой /etc/systemd/system/custom.service автоматически получил systemd_unit_file_t, так что я думаю, что это все настроено.

Мой /root/scripts/custom.sh в настоящее время имеет unconfined_u:object_r:admin_home_t:s0.

Проверяя другие элементы ExecStart с помощью ls -ldZ из других сервисов в этой папке, я вижу:

-rwxr-xr-x. 1 root root system_u:object_r:bluetooth_exec_t:s0      1375048 May 17  2022 /usr/libexec/bluetooth/bluetoothd
-rwxr-xr-x. 1 root root system_u:object_r:NetworkManager_exec_t:s0   67752 Feb 23 04:51 /usr/libexec/nm-dispatcher
-rwxr-xr-x. 1 root root system_u:object_r:avahi_exec_t:s0           146208 Nov  3  2020 /usr/sbin/avahi-daemon
-rwxr-xr-x. 1 root root system_u:object_r:xdm_exec_t:s0             471744 Dec 12  2022 /usr/sbin/gdm
-rwxr-xr-x. 1 root root system_u:object_r:modemmanager_exec_t:s0   2203464 Dec 13  2022 /usr/sbin/ModemManager
-rwxr-xr-x. 1 root root system_u:object_r:syslogd_exec_t:s0         742168 Jan 10 06:46 /usr/sbin/rsyslogd
-rwxr-xr-x. 1 root root system_u:object_r:timedatex_exec_t:s0        33984 Aug 12  2018 /usr/sbin/timedatex
  • Мне нужно создавать контекст типа customservice_exec_t? Если да, то как?
  • Я думал, что наткнулся на bin_t, когда не видел соответствующей синтаксической конструкции exec_t для некоторых сервисов, когда я искал. Является ли bin_t хорошим контекстом, который можно использовать, чтобы сэкономить время на создание контекста?
  • Какова правильная конвенция здесь для того, что я делаю, чтобы это не перестало работать в будущем из-за того, что я сделал что-то неправильно? Мне нужно иметь selinux=enforcing, так что установка его в режим permissive не является решением.

Мне нужно создавать контекст типа customservice_exec_t? Если да, то как?

Вам не нужно этого делать, это было бы необходимо только если вы хотите создать очень специфические правила и быть уверенным в контроле каждого типа, который к нему обращается, что требует много времени на создание и высоких затрат на обслуживание. Похоже, что вы просто хотите использовать лучшие практики selinux с низким обслуживанием.
Хотя вы можете проверить здесь, как это сделать.

Я думал, что наткнулся на bin_t, когда не видел соответствующей синтаксиса exec_t для некоторых сервисов, когда я искал. Является ли bin_t хорошим контекстом, чтобы сэкономить время на создание контекста?

Да, bin_t является хорошим контекстом для использования здесь, он используется для перехода сервисов в общий контекст для пользовательских сервисов (unconfined_service_t), который лишь слегка ограничен политикой SELinux:

# sesearch -T -s init_t -t bin_t -c process
type_transition init_t bin_t:process unconfined_service_t;

Какова правильная конвенция здесь для того, что я делаю, чтобы это не перестало работать в будущем из-за того, что я сделал что-то неправильно

Вы можете скопировать свой скрипт в /bin и затем выполнить restorecon -RF /bin/custom.sh, или предоставить вашей папке scripts правильный контекст с помощью:

# semanage fcontext -a -t bin_t "/root/scripts(/.*)?"

# restorecon -vRF /root/scripts

Ответ или решение

Контекст SELinux для ExecStart кастомного сервиса systemd

Ваша проблема с SELinux в RHEL 8.8 заключается в том, что ваш исполняемый скрипт /root/scripts/custom.sh не имеет правильного контекста SELinux. Вы получаете ошибки на уровне выполнения, что указывает на то, что доступ к файлу был запрещен политиками SELinux. В этом ответе мы подробно рассмотрим подходы к разрешению этой проблемы и лучшую практику применения SELinux.

1. Установление правильного контекста SELinux

Ваш текущий контекст файла /root/scripts/custom.sh:

unconfined_u:object_r:admin_home_t:s0

Этот контекст не позволяет системе выполнять скрипт через systemd из-за ограничений политики SELinux в RHEL 8.8. Чтобы решить эту проблему, необходимо применить правильный контекст для исполняемых файлов.

Рекомендация по контекстам:

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

2. Применение контекста bin_t

Чтобы применить контекст bin_t к вашему скрипту, выполните следующие команды:

# Добавьте правило для контекста
semanage fcontext -a -t bin_t "/root/scripts(/.*)?"

# Примените изменения контекста
restorecon -vRF /root/scripts

Эти команды добавят соответствующий контекст к файлам в директории /root/scripts и применят его ко всем существующим файлам.

3. Создание специфического контекста (по желанию)

Если вы всё же хотите создать специализированный контекст, вы можете создать новый тип, например customservice_exec_t. Для этого вам потребуются следующие шаги:

  1. Создать файл модуля политики SELinux.
  2. Скомпилировать и установить его с помощью команд:
# проблемы с аудированием
ausearch -c 'custom.sh' --raw | audit2allow -M customservice_exec_t

# установка модуля
semodule -X 300 -i customservice_exec_t.pp

Использование специализированного контекста может дать вам больше контроля, но потребует также большего внимания к управлению политиками.

4. Убедитесь в долговечности решения

Для обеспечения устойчивости вашего решения всегда используйте restorecon после изменения контекста, чтобы гарантировать, что в будущем изменения не потеряются. Также полезно:

  • Регулярно проверять логи SELinux.
  • Проводить аудит ваших пользовательских скриптов и запусков на наличие новых AVC-отказов.

Заключение

Лучшей практикой для вашего сценария будет использование bin_t для вашего скрипта, так как это обеспечит более низкие накладные расходы на администрирование политики SELinux в будущем. Если возникнет необходимость в более специфичном контроле, вы всегда сможете создать свой собственный контекст.

Следуйте этим рекомендациям, чтобы избежать проблем с SELinux, сохранив при этом безопасность вашего сервера, который работает под управлением политики SELinux в режиме принуждения (enforcing).

Оцените материал
Добавить комментарий

Капча загружается...