SELinux-Module selber schreiben

Klar geregelt

In den letzten Jahren hat sich im Bereich SELinux viel getan. Die neuen Features betrafen meistens die Benutzbarkeit. Mit dem aktuellen Release lassen sich SELinux-Policy-Module einfacher selber schreiben.
Skripte können Administratoren das Leben deutlich leichter machen - besonders, wenn sich wiederholende Abläufe im Spiel sind. Dabei steht eine Vielzahl an ... (mehr)

SELinux wird den Ruf nicht los, dass es schwer zu verwalten ist und oft die Ursache für mögliche Probleme mit Anwendungen darstellt. Dabei hat sich in den letzten Jahren sehr viel zum Positiven entwickelt – gerade was den Bereich Usability angeht. Statt wie in den Anfangstagen mit einem monolithischen Regelwerk zu arbeiten, kommen mittlerweile Module zum Einsatz. Möchte ein Administrator ein neues SELinux-Modul entwickeln, so sind hierfür üblicherweise drei Dateien notwendig.

Drei Dateien für ein SELinux-Modul

In einer Type-Enforcement Datei (".te") steht das eigentliche Regelwerk. Es setzt sich zu einem großen Teil aus m4-Makros, den sogenannten Interfaces, zusammen. Soll der Zugriff auf Ressourcen eines bestimmten Services stattfinden, beispielsweise die Logdateien, so stellt der Service hierfür ein entsprechendes Interface zur Verfügung. Soll die eigene Anwendung auf diese Ressourcen zugreifen, so kann der Policy-Schreiber hierfür auf das Interface des Services zurückgreifen, ohne sich näher mit den Details der Logdateien auseinandersetzen zu müssen. So ist es beispielsweise gar nicht notwendig, das Security-Label der Logdateien zu kennen, da das Interface den Zugriff abstrahiert.

Neben dem eigentlichen Regelwerk ist noch eine zweite Datei notwendig. Diese definiert die Security-Label der Dateien der eigenen Anwendung, für die gerade eine Policy entwickelt wird. Die Datei wird als File-Context Datei (*.fc) bezeichnet. Optional lassen sich bei Bedarf auch Interfaces zur Verfügung stellen. Dies ist immer dann hilfreich, wenn andere Anwendungen oder Services auf die eigenen Ressourcen zurückgreifen müssen. Die m4-basierten Interfaces sind in einer Datei mit der Endung ".fc" zu speichern.

Um aus diesen Dateien ein Policy-Modul zu erzeugen, müssen Sie zuerst eine Datei in einem Zwischenformat (".mod") erzeugen. Hierfür kommt das Tool checkmodule zum Einsatz. Als Ergebnis erhalten Sie eine Datei, in der das komplette Regelwerk aus der Type-Enforcement Datei steht. Die m4-Makros sind nun bereits aufgelöst worden. Für das finale Policy-Modul fehlen allerdings noch die Informationen aus der File-Context-Datei. Sie lassen sich mittels semodule_package hinzufügen, sodass am Ende das fertige Policy-Modul herauskommt, das sich in den Security-Server des Linux-Kernels laden lässt. Um den Vorgang zu vereinfachen, stellen die SELinux-Entwicklunsgstools ein Makefile zur Verfügung, mit dem Sie ein fertiges Policy-Modul in einem einzelnen Vorgang erzeugen können.

Listing 1: SELinux-Modul



policy_module(mypegasus, 1.0)
require{
    type certmonger_t;
    type pegasus_conf_t;
}
allow certmonger_t pegasus_conf_t:file { ioctl read getattr lock open } ;
# make -f /usr/share/selinux/devel/Makefile mypegasus.pp
# semodule -i mypegasus.pp

Listing 1 zeigt ein Beispiel. Hier soll der certmonger-Service Zugriff auf das Verzeichnis des Pegasus CIM-Brokers erhalten. Dazu wird keine File- oder Interface-Datei benötigt. Mit dem Makefile können Sie das Policy-Modul sehr einfach erzeugen und es in den Security-Server laden. Mit Hilfe des Tool sesearch verifizieren Sie, dass der Kernel nun tatsächlich diese neue Regel kennt:

# sesearch --allow -s certmonger_t -t pegasus_conf_t
Found 1 semantic av rules: allow certmonger_t pegasus_conf_t : file { ioctl read getattr lock open } ;

Was im Hintergrund allerdings passiert, ist Folgendes: Der Kernel selbst verwendet gar nicht das soeben erzeugte Modul, sondern greift stattdessen auf eine Datei "policy.XX" zurück. Die Endung XX steht dabei für die SELinux-Version, die der Kernel unterstützt. Diese Datei basiert auf einer Basis-Policy und sämtlichen Policy-Modulen, die auf dem System vorhanden und aktiv sind. Gespeichert wird diese Datei unterhalb von "/etc/selinux":

# ls -lh /etc/selinux/targeted/policy/total 3.6M
-rw-r--r--. 1 root root 3.6M Mar 3 13:28 policy.29

Die Module liegen in einem Policy-Store unter "/var/lib/selinux/targeted/active/modules/" (ab der libselinux-Version 2.4). Auf älteren Systemen wurden sie noch unterhalb von "/etc/selinux/targeted/modules/active/" gespeichert.

Listing 2: Modul im CIL-Format



# cat mypegasus.pp | /usr/libexec/selinux/hll/pp | tee mypegasus.cil
(roleattributeset cil_gen_require system_r)
(typeattributeset cil_gen_require certmonger_t)
(typeattributeset cil_gen_require pegasus_conf_t)
(allow certmonger_t pegasus_conf_t (file (ioctl read getattr lock open)))

Kompilieren wird schneller

Da jede Änderung das Anlegen einer neuen Policy-Datei (policy.XX) erfordert, nimmt das Kompilieren des Moduls teilweise mehrere Minuten in Anspruch.

Mit der aktuellen libselinux-Version 2.4 sind die Entwickler dieses Problem angegangen. Policy-Module können nun in einer neuen Sprache, der Common Intermediate Language (CIL), entwickelt werden. Bestehende Module (*.pp-Dateien) lassen sich mittels eines Compilers in die CIL übersetzen und können dann direkt in den Security-Server geladen werden. Zwar müssen die einzelnen Module auch erst wieder in eine einzelne Policy-Datei zusammengeführt werden, jedoch funktioniert dieser Vorgang wesentlich schneller als mit den zuvor verwendeten pp-Modulen. Tests haben gezeigt, dass Module im CIL-Format bis zu 75 Prozent schneller geladen werden können. Listing 2 zeigt ein Beispiel, wie Sie das soeben erzeugte Policy-Modul in das CIL-Format umwandeln können. Die so erzeugte Datei können Sie bei Bedarf abändern oder direkt in den Security-Server laden:

# semodule -X 500 -i mypegasus.cil

Die Option "-X" legt eine Priorität für das Modul fest. Hierbei handelt es sich ebenfalls um ein neues Feature in der aktuellen libselinux-Version. So können Sie Module vom gleichen Typ in den Server laden, um so beispielsweise das Modul des Distributors zu überschreiben:

# semodule --list=full | grep mypegasus
500 mypegasus cil
400 mypegasus pp

Bei Bedarf können Sie das alte Modul auch entfernen (semodule -r) oder temporär deaktivieren (semodule -d).

Neben der verbesserten Performance beim Laden und Entladen der SELinux-Module im CIL-Format gibt es nebenbei noch einen weiteren Vorteil. Die bisher eingesetzten pp-Module basierten alle auf einer Art High-Level Sprache, die sich mit dem passenden Compiler in das CIL-Format übersetzen lässt. Das erlaubt es anderen Frameworks, ihre eigenen Regelwerke in einer beliebigen Sprache mitbringen zu können. Solange sie über einen Compiler verfügen, der das jeweilige Format in die CIL übersetzt, lassen sich diese Regelwerke problemlos vom SELinux-Security-Server verwenden (Bild 1). Natürlich können Sie Ihr Policy-Modul auch direkt im CIL-Format schreiben. Im SELinux-Wiki [1] finden Sie Informationen zu der Sprache und ihrer Syntax.

Bild 1: Policy-Module lassen sich nun im CIL-Format in den Security-Server laden.
comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023