8.2. Création et application d'une politique SELinux pour une application personnalisée
Cet exemple de procédure fournit les étapes pour confiner un simple démon par SELinux. Remplacez le démon par votre application personnalisée et modifiez la règle de l'exemple en fonction des exigences de cette application et de votre politique de sécurité.
Conditions préalables
-
Le paquetage
policycoreutils-devel
et ses dépendances sont installés sur votre système.
Procédure
Pour cet exemple de procédure, préparez un simple démon qui ouvre le fichier
/var/log/messages
en écriture :Créez un nouveau fichier et ouvrez-le dans l'éditeur de texte de votre choix :
$ vi mydaemon.c
Insérer le code suivant :
#include <unistd.h> #include <stdio.h> FILE *f; int main(void) { while(1) { f = fopen("/var/log/messages","w"); sleep(5); fclose(f); } }
Compiler le fichier :
$ gcc -o mydaemon mydaemon.c
Créez un fichier d'unité
systemd
pour votre démon :$ vi mydaemon.service [Unit] Description=Simple testing daemon [Service] Type=simple ExecStart=/usr/local/bin/mydaemon [Install] WantedBy=multi-user.target
Installer et démarrer le démon :
# cp mydaemon /usr/local/bin/ # cp mydaemon.service /usr/lib/systemd/system # systemctl start mydaemon # systemctl status mydaemon ● mydaemon.service - Simple testing daemon Loaded: loaded (/usr/lib/systemd/system/mydaemon.service; disabled; vendor preset: disabled) Active: active (running) since Sat 2020-05-23 16:56:01 CEST; 19s ago Main PID: 4117 (mydaemon) Tasks: 1 Memory: 148.0K CGroup: /system.slice/mydaemon.service └─4117 /usr/local/bin/mydaemon May 23 16:56:01 localhost.localdomain systemd[1]: Started Simple testing daemon.
Vérifiez que le nouveau démon n'est pas limité par SELinux :
$ ps -efZ | grep mydaemon system_u:system_r:unconfined_service_t:s0 root 4117 1 0 16:56 ? 00:00:00 /usr/local/bin/mydaemon
Générer une politique personnalisée pour le démon :
$ sepolicy generate --init /usr/local/bin/mydaemon Created the following files: /home/example.user/mysepol/mydaemon.te # Type Enforcement file /home/example.user/mysepol/mydaemon.if # Interface file /home/example.user/mysepol/mydaemon.fc # File Contexts file /home/example.user/mysepol/mydaemon_selinux.spec # Spec file /home/example.user/mysepol/mydaemon.sh # Setup Script
Reconstruire la politique du système avec le nouveau module de politique en utilisant le script d'installation créé par la commande précédente :
# ./mydaemon.sh Building and Loading Policy + make -f /usr/share/selinux/devel/Makefile mydaemon.pp Compiling targeted mydaemon module Creating targeted mydaemon.pp policy package rm tmp/mydaemon.mod.fc tmp/mydaemon.mod + /usr/sbin/semodule -i mydaemon.pp ...
Notez que le script d'installation renomme la partie correspondante du système de fichiers à l'aide de la commande
restorecon
:restorecon -v /usr/local/bin/mydaemon /usr/lib/systemd/system
Redémarrez le démon et vérifiez qu'il fonctionne désormais dans le respect de SELinux :
# systemctl restart mydaemon $ ps -efZ | grep mydaemon system_u:system_r:mydaemon_t:s0 root 8150 1 0 17:18 ? 00:00:00 /usr/local/bin/mydaemon
Étant donné que le démon est désormais confiné par SELinux, SELinux l'empêche également d'accéder à
/var/log/messages
. Affichez le message de refus correspondant :# ausearch -m AVC -ts recent ... type=AVC msg=audit(1590247112.719:5935): avc: denied { open } for pid=8150 comm="mydaemon" path="/var/log/messages" dev="dm-0" ino=2430831 scontext=system_u:system_r:mydaemon_t:s0 tcontext=unconfined_u:object_r:var_log_t:s0 tclass=file permissive=1 ...
Vous pouvez également obtenir des informations supplémentaires en utilisant l'outil
sealert
:$ sealert -l "*" SELinux is preventing mydaemon from open access on the file /var/log/messages. Plugin catchall (100. confidence) suggests * If you believe that mydaemon should be allowed open access on the messages file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c 'mydaemon' --raw | audit2allow -M my-mydaemon # semodule -X 300 -i my-mydaemon.pp Additional Information: Source Context system_u:system_r:mydaemon_t:s0 Target Context unconfined_u:object_r:var_log_t:s0 Target Objects /var/log/messages [ file ] Source mydaemon ...
Utilisez l'outil
audit2allow
pour suggérer des changements :$ ausearch -m AVC -ts recent | audit2allow -R require { type mydaemon_t; } #============= mydaemon_t ============== logging_write_generic_logs(mydaemon_t)
Les règles suggérées par
audit2allow
pouvant être incorrectes dans certains cas, n'utilisez qu'une partie de ses résultats pour trouver l'interface de politique correspondante :$ grep -r "logging_write_generic_logs" /usr/share/selinux/devel/include/ | grep .if /usr/share/selinux/devel/include/system/logging.if:interface(`logging_write_generic_logs',`
Vérifier la définition de l'interface :
$ cat /usr/share/selinux/devel/include/system/logging.if ... interface(`logging_write_generic_logs',` gen_require(` type var_log_t; ') files_search_var($1) allow $1 var_log_t:dir list_dir_perms; write_files_pattern($1, var_log_t, var_log_t) ') ...
Dans ce cas, vous pouvez utiliser l'interface proposée. Ajoutez la règle correspondante à votre fichier d'application des types :
$ echo "logging_write_generic_logs(mydaemon_t)" >> mydaemon.te
Vous pouvez également ajouter cette règle au lieu d'utiliser l'interface :
$ echo "allow mydaemon_t var_log_t:file { open write getattr };" >> mydaemon.te
Réinstaller la politique :
# ./mydaemon.sh Building and Loading Policy + make -f /usr/share/selinux/devel/Makefile mydaemon.pp Compiling targeted mydaemon module Creating targeted mydaemon.pp policy package rm tmp/mydaemon.mod.fc tmp/mydaemon.mod + /usr/sbin/semodule -i mydaemon.pp ...
Vérification
Vérifiez que votre application fonctionne dans le cadre de SELinux, par exemple :
$ ps -efZ | grep mydaemon system_u:system_r:mydaemon_t:s0 root 8150 1 0 17:18 ? 00:00:00 /usr/local/bin/mydaemon
Vérifiez que votre application personnalisée ne provoque pas de refus SELinux :
# ausearch -m AVC -ts recent <no matches>
Ressources supplémentaires
-
sepolgen(8)
,ausearch(8)
,audit2allow(1)
,audit2why(1)
,sealert(8)
, etrestorecon(8)
pages de manuel