LINUX:SELinux-Module

De WIKI sur Linux (ADB)
Aller à la navigation Aller à la recherche

retour à SELinux


But

Un module est un ensemble cohérent des différentes composantes de SELinux: Types, règles, Fcontext,... Il se présente sous une forme ayant beaucoup d'analogie avec un programme.


Listage

On peut lister tous les modules déjà intégrés dans la stratégie globale de sécurité de SELinux de la machine.

Voici la commande:

semanage module -l

ou

semodule -lfull 

En voici un extrait:


Nom de module             Priorité  Langue
 
BackupPC                  400       pp
amanda                    100       pp
apache                    100       pp
apcupsd                   100       pp
apm                       100       pp
application               100       pp
arpwatch                  100       pp
auditadm                  100       pp
authconfig                100       pp
...
my-gw                     300       pp
my-httpd-nagios           300       pp
my-logrotate-wazuh        300       pp

En première colonne nous avons le nom du module et en seconde sa priorité.

On peut également les lister en parcourant le répertoire "/var/lib/selinux/targeted/active/modules".


Le nom du module doit être unique dans la stratégie globale de sécurité de SELinux de la machine. Au pire, si on installe un nouveau module portant le même nom qu'un module existant et ayant la même priorité, le nouveau module va écraser l'existant et l'ancien sera perdu. S'ils n'ont pas la même priorité, celui ayant la plus grande sera utilisé et l'autre inactivé. Vous comprendrez que si vous écrasez un module existant d'un paquet du système, vous aller perturber grandement l'exécution de ce logiciel.

Il est donc impératif de donner à nos modules un nom bien spécifique. Par exemple, on utilise un préfixe personnel tel "my-" ou "adebast-".


Etapes de mise en oeuvre

La constitution d'un module passe par trois étapes:

  • la rédaction des sources du module; elles sont constituées de trois parties dans trois fichiers distincts.
  • la compilation de ces sources.
  • l'intégration de ce module dans la stratégie globale de sécurité de SELinux de la machine.


Sources

Elles sont constituées de trois fichiers. Tous les fichiers portent le même nom que celui du module. Ils se distinguent par leur extension.

  • <nom du module>.te: C'est le fichier principal et nécessaire. Il contient le nom du module, les déclaratives des types, les classes, permissions, des attributs,... , des règles et d'appels de macros-interfaces globales ou personnelles.
  • <nom du module>.if: Ce fichier contient les sources de macros-interfaces personnelles, locales. Elles ne sont pas nécessaire. Ce fichier sera vide dans notre cas car nous n'en créerons pas.
  • <nom du module>.tc: Ce fichier contient les liaisons entre les "Context" et les fichiers ("Fcontext"). Il remplace la commande vue précédemment "semanage fcontext ...". Elle ne sont pas nécessaires, Ce fichier peut être vide.


Source TE

Nous allons présenter sous forme d'un exemple, les composantes principales de la source TE du module. C'est cette structure que nous rencontrerons lors de la mise en route de SELinux. Si nous devions créer un module complet pour une application personnelle, il faudra y ajouter d'autres notions.

Voici un exemple de source; il a été conçu lors de l'intégration du programme Web de généalogie (voir l'article sur GeneWeb).

Ce fichier porte le nom "my-gw.te":


module my-gw 1.0;
 
require {
       type httpd_sys_content_t;
       type init_t;
       class file { execute execute_no_trans map open read write append create lock setattr rename unlink };
}
 
allow init_t httpd_sys_content_t:file { execute execute_no_trans open read write append create lock setattr map rename unlink };

Celui qui est habitué à la programmation y retrouvera les quelques grandes notions de base.

La première ligne définit le nom du module qui est le même que le nom du fichier hors extension: "my-gw".

Le second groupe concerne les déclaratives; dans ce cas, elles sont requises car elles doivent préexister dans la stratégie globale de sécurité de SELinux de la machine. Mais elles pourraient être nouvelles. On y retrouve les différentes composantes du "Context" expliquées dans l'article sur le Concept de SELinux.

Le dernier groupe reprend les règles.

Dans ce dernier groupe, toute utilisation d'une composante du "Concept" doit être repris dans la seconde partie déclarative sinon la compilation ne se fera pas.


Source IF

Ce fichier peut contenir des fonctions nommées "interface". Ces routines peuvent être appelées dans la source TE. Leur rôle est de rassembler diverses déclaratives et actions et ainsi de faciliter le travail de programmation. Dans ce fichier, ces fonctions sont personnelles; elle ne sont valables que pour ce module. Mais le système en fourni tout un ensemble. On peut les trouver sous le répertoire "/usr/share/selinux/devel/include". Leur description peut être consultée dans le répertoire "/usr/share/doc/selinux-policy/html". Elle est sous format HTML. Nous ne les utiliserons pas.


Source TC

Ce fichier contient les liaisons entre les "Context" et les fichiers ("Fcontext"). Il remplace la commande vue précédemment "semanage fcontext ...". Il n'est donc pas nécessaires. Nous l'utiliserons lors de la création d'un module lié à un programme personnel développé en exemple.


Voici cet exemple:


/gestion/bin/lireecrire.py   -- gen_context(system_u:object_r:gestion_exec_t,s0)
/gestion/data(/.*)?             gen_context(system_u:object_r:gestion_data_t,s0)

Chaque ligne est constituée de trois zones:

  • la zone de listage des fichiers
  • le type de fichier: Il en existe plusieurs. Son absence désigne tout type de fichier; le code "--" désigne un fichier classique; le code "-d" désigne un répertoire;...
  • la fonction "gen_context()" qui fournit le "Context"


Les commandes équivalentes sont:

semanage fcontext -a -t gestion_exec_t '/gestion/bin/lireecrire.py'
semanage fcontext -a -t gestion_data_t '/gestion/data(/.*)?'


Création de sources

La manière usuelle est de créer ces fichiers à partir de rien à l'aide d'un éditeur de texte.

Mais il existe une autre manière que nous utiliserons abondamment. De prime abord, nous n'allons pas créer un module de notre cru. Nous serons confrontés à de multiples alertes bloquant un logiciel installé. Nous allons utiliser un outil qui permet de générer la source de type TE à partir de ces alertes.


A partir du fichier journal des audits, on extrait les lignes concernant les alertes qui concernent notre application.

Par exemple, voici les lignes générées lorsque nous voulions utiliser le programme GeneWeb:


type=AVC msg=audit(1702911730.037:105900): avc:  denied  { execute } for  pid=903874 comm="(gwd)" name="gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911730.037:105901): avc:  denied  { read open } for  pid=903874 comm="(gwd)" path="/application/web/geneweb/gw/gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911730.038:105903): avc:  denied  { execute_no_trans } for  pid=903874 comm="(gwd)" path="/application/web/geneweb/gw/gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911730.038:105904): avc:  denied  { read } for  pid=903874 comm="(gwd)" name="gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911730.040:105905): avc:  denied  { map } for  pid=903874 comm="gwd" path="/application/web/geneweb/gw/gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911730.040:105906): avc:  denied  { execute } for  pid=903874 comm="gwd" path="/application/web/geneweb/gw/gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911730.227:105907): avc:  denied  { open } for  pid=903874 comm="gwd" path="/application/web/geneweb/gw/gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1
type=AVC msg=audit(1702911835.650:105924): avc:  denied  { execute } for  pid=904030 comm="(gwd)" name="gwd" dev="dm-1" ino=2497529 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=1

Nous les mettons dans le fichier "gw.log".

Ensuite on fait appel au programme "audit2allow":

cat gw.log | audit2allow -M my-gw

En lui injectant les alertes, il va générer les fichiers "my-gw.te" et "my-gw.pp" correspondant au module "my-gw". Le contenu du fichier "my-gw.te" correspond à celui présenté ci-dessus sous la section "Source TE". Le second fichier correspond au module compilé.


Il est important de traiter ensemble que les alertes concernant un logiciel ou une de ses parties principales. De cette façon, vous pourrez appliquer ce module à d'autres machines et le code généré vous semblera plus logique et homogène. Dans notre exemple, c'est un exécutable indépendant s'exécutant dans le contexte d'un service Web.


Il vous arrivera régulièrement qu'une nouvelle alerte apparaisse liée à une application déjà traitée. Autre cas courant, une alerte traitée libère le blocage; le programme peut aller plus loin et rencontre un nouveau blocage. Vous allez traiter ces alertes séparément dans un espace de travail temporaire. Dans la source TE générée, vous individualisez les nouvelles lignes générées et vous les intégrez au module de référence créé auparavant.

Pour information, si vous rencontrez la ligne de commentaire suivante:


#!!!! This avc is allowed in the current policy

Ceci veut dire que la règle qui suit est déjà intégrée dans votre stratégie globale de sécurité SELinux. Normalement c'est une ligne que vous avez déjà intégrée dans votre module de référence. On la met de côté.


On se retrouve dans le premier cas de figure où on crée son propre module. La compilation devra se faire individuellement.


Compilation

L'étape suivante consiste en la compilation des sources. Cette action consiste à vérifier qu'il n'y a pas d'erreur dans les sources et enfin de créer un fichier de forme "<nom du module>.pp". C'est ce fichier qui pourra être intégré à la stratégie globale de sécurité SELinux des machines Linux.

Voici un exemple de commande de compilation correspondant au module "my-gw":

 rm -f my-gw.pp ; make -f /usr/share/selinux/devel/Makefile my-gw.pp

Il est important que le fichier de type ".pp" n'existe pas. Si les fichiers sources de type IF et TC n'existent pas, elle va les créer à vide. Un sous-répertoire "tmp" sera créé. Il pourra être détruit par la suite.

Si la phase proprement dite de compilation affiche des erreurs, le fichier de type ".pp" ne sera pas créé. Il vous faut corriger ces erreurs qui résident souvent dans l’absence d'une déclarative ou à un module qintermédiaire qu'on a oublié d'intégrer à la stratégie de sécurité. Et on relance la compilation.


Installation

Pour être effective, ce module doit être intégré à la stratégie globale de sécurité SELinux.

Voici un exemple de commande d'ajout du module correspondant à celui de "my-gw":

semodule -X 300 -i my-gw.pp

On a utilisé arbitrairement le niveau de priorité "300". Lors de cette dernière étape, il y a une dernière vérification d'intégrité. Par exemple, si on installe le module sur une autre machine et qu'une des composante du "Context" n'est pas implémentée, l'intégration sera refusée.


On peut vérifier que le module a bien été intégré avec la commande vue plus haut:

semanage module -l

Il nous reste à relancer l'application afin de vérifier que tout se passe bien sans alerte.


On peut désinstaller ce module de la façon suivante:

semodule -X 300 -r my-gw





retour à SELinux