chmod 755, chown au bon utilisateur, et pourtant Permission denied persiste pour un service comme nginx ou Apache qui tente d’accéder à un fichier pourtant correctement configuré selon les permissions Unix classiques. Sur une distribution RHEL, CentOS, Fedora ou Rocky Linux avec SELinux actif, les permissions Unix ne sont qu’une des deux couches de contrôle d’accès à satisfaire, jamais la seule.
Ce que SELinux ajoute par-dessus les permissions Unix
SELinux applique un contrôle d’accès obligatoire (MAC) qui s’ajoute au contrôle d’accès discrétionnaire (DAC) des permissions Unix classiques : même avec des droits rwx parfaitement corrects, un processus dont le contexte de sécurité SELinux ne correspond pas à celui attendu pour cette ressource se voit refuser l’accès, un refus qui s’ajoute à la vérification Unix plutôt que de la remplacer.
# -Z révèle le contexte SELinux, invisible
# dans un ls -l classique limité aux permissions Unix
ls -lZ /var/www/html/index.html
# -rw-r--r--. user user unconfined_u:object_r:user_home_t:s0 index.html
Le piège classique : un fichier déplacé au mauvais endroit
Un fichier copié ou déplacé vers /var/www/html/ depuis un répertoire personnel (/home/user/, par exemple) conserve souvent le contexte SELinux de son emplacement d’origine (user_home_t), plutôt que d’hériter automatiquement du contexte attendu pour son nouvel emplacement (httpd_sys_content_t). nginx ou Apache, dont le contexte de processus n’est autorisé à lire que httpd_sys_content_t, se voit alors refuser l’accès malgré des permissions Unix par ailleurs impeccables.
restorecon : remettre le contexte attendu, pas en inventer un
restorecon corrige le contexte d’un fichier en le remettant à la valeur attendue par défaut pour son emplacement actuel, selon les règles de politique SELinux déjà définies pour ce chemin, plutôt que d’assigner un contexte arbitraire.
# Remet le contexte SELinux attendu pour ce chemin,
# selon les règles déjà définies pour /var/www/html
restorecon -v /var/www/html/index.html
audit2allow : comprendre un refus avant d’écrire une règle
Un refus SELinux est systématiquement journalisé, permettant de diagnostiquer précisément quelle règle manque plutôt que de désactiver SELinux entièrement par frustration, une pratique qui élimine la protection sans en comprendre la cause.
# Génère une règle de politique SELinux suggérée,
# à partir des refus effectivement journalisés
sudo ausearch -m avc -ts recent | audit2allow -M mapolicy
Pourquoi désactiver SELinux n’est jamais la bonne réponse
Désactiver SELinux (setenforce 0, ou pire, au niveau du bootloader) supprime une couche de défense en profondeur conçue précisément pour limiter les dégâts si un service compromis (une vulnérabilité applicative dans nginx, par exemple) tente d’accéder à des ressources hors de son périmètre légitime : le même principe de moindre privilège déjà appliqué au RBAC Kubernetes, mais au niveau du système d’exploitation plutôt que de l’orchestrateur.
À retenir
Un Permission denied sur un système RHEL/CentOS/Fedora avec SELinux actif ne se résout jamais uniquement en vérifiant chmod/chown : SELinux applique une seconde couche de contrôle, le contexte de sécurité, visible via ls -lZ et invisible dans un ls -l classique. Un fichier déplacé conserve souvent le contexte de son emplacement d’origine plutôt que d’hériter de celui attendu à destination, restorecon corrigeant ce contexte selon la politique déjà définie. Désactiver SELinux face à un refus frustrant élimine une protection de moindre privilège au niveau système plutôt que de la comprendre, audit2allow offrant un chemin pour diagnostiquer et autoriser précisément ce qui doit l’être.