Linux/SELinux/Regeln anpassen: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| (2 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 243: | Zeile 243: | ||
Sobald die 3 Dateien (example.if, example.fc und example.te) Ihren Erwartungen für die neuen Regeln entsprechen, benennen Sie sie in myapp''Endung'' um und führen Sie make NAME=devel aus, um ein Modul in der Datei myapp.pp zu erzeugen (Sie können es sofort mit semodule -i myapp.pp laden) | Sobald die 3 Dateien (example.if, example.fc und example.te) Ihren Erwartungen für die neuen Regeln entsprechen, benennen Sie sie in myapp''Endung'' um und führen Sie make NAME=devel aus, um ein Modul in der Datei myapp.pp zu erzeugen (Sie können es sofort mit semodule -i myapp.pp laden) | ||
* Wenn mehrere Module definiert sind, erzeugt make alle entsprechenden .pp-Dateien | * Wenn mehrere Module definiert sind, erzeugt make alle entsprechenden .pp-Dateien | ||
[[Kategorie:Linux/SELinux]] | |||
Aktuelle Version vom 29. März 2026, 16:19 Uhr
Regeln anpassen
Da das SELinux-Regelwerk modular ist, könnte es interessant sein, neue Module für (möglicherweise maßgefertigte) Anwendungen zu entwickeln, für die es diese noch nicht gibt
- Diese neuen Module würden dann die Referenzrichtlinien ergänzen
Zur Erstellung neuer Module werden die Pakete selinux-policy-dev und selinux-policy-doc benötigt
- Letzteres enthält die Dokumentation der Standardregeln (/usr/share/doc/selinux-policy-doc/html/) und Beispieldateien, die als Vorlagen für die Erstellung neuer Module verwendet werden können
- Installieren Sie diese Dateien und untersuchen Sie sie genauer:
$ cp /usr/share/doc/selinux-policy-doc/Makefile.example Makefile $ cp /usr/share/doc/selinux-policy-doc/example.fc ./ $ cp /usr/share/doc/selinux-policy-doc/example.if ./ $ cp /usr/share/doc/selinux-policy-doc/example.te ./
Die Datei .te ist die wichtigste
- Sie legt die Regeln fest
- Die Datei .fc bestimmt die „Dateikontexte“, das heißt, die Typen, die den auf diese Module bezogenen Dateien zugeordnet sind
- Die in der Datei .fc befindlichen Daten werden während des Dateikennzeichnungsschrittes benutzt
- Schließlich legt die Datei .if die Schnittstelle der Module fest: es ist ein Satz „öffentlicher Funktionen“, die andere Module verwenden können, um ordnungsgemäß mit dem Modul, das Sie erstellen, zu interagieren
Eine .fc-Datei schreiben
Das Lesen des unten stehenden Beispiels sollte genügen, um die Struktur einer derartigen Datei zu verstehen
- Sie können reguläre Ausdrücke verwenden, um denselben Sicherheitskontext mehreren Dateien zuzuordnen oder auch einem ganzen Verzeichnisbaum
Beispiel beispiel.fc-Datei
# myapp executable will have: # label: system_u:object_r:myapp_exec_t # MLS sensitivity: s0 # MCS categories: <none>
/usr/sbin/myapp -- gen_context(system_u:object_r:myapp_exec_t,s0)
Eine .if-Datei schreiben
In unten stehendem Beispiel kontrolliert die erste Schnittstelle („myapp_domtrans“), wer die Anwendung ausführen kann
- Die zweite („myapp_read_log“) gewährt Schreibzugriff auf die Protokolldateien der Anwendung
Jede Schnittstelle muss einen gültigen Regelsatz erzeugen, der in eine .te-Datei eingegliedert werden kann
- Sie sollten daher alle Typen, die Sie verwenden, festlegen (mit dem Makro gen_require) und Standardanweisungen benutzen, um Berechtigungen zu vergeben
- Beachten Sie jedoch, dass Sie auch Schnittstellen benutzen können, die von anderen Modulen bereitgestellt werden
- Der nächste Abschnitt gibt weitere Erläuterungen darüber, wie diese Berechtigungen ausgedrückt werden können
- Beispiel beispiel.if-Datei
## <summary>Myapp example policy</summary> ## <desc>
##
## More descriptive text about myapp. The desc ## tag can also use p, ul, and ol ## html tags for formatting ##
##
## This policy supports the following myapp features: ##
-
##
- Feature A ##
- Feature B ##
- Feature C ##
##
## </desc> #
######################################## ## <summary> ## Execute a domain transition to run myapp ## </summary> ## <param name="domain"> ## <summary> ## Domain allowed to transition ## </summary> ## </param> # interface(`myapp_domtrans',` gen_require(` type myapp_t, myapp_exec_t; ') domtrans_pattern($1,myapp_exec_t,myapp_t) ')
######################################## ## <summary> ## Read myapp log files ## </summary> ## <param name="domain"> ## <summary> ## Domain allowed to read the log files ## </summary> ## </param> # interface(`myapp_read_log',` gen_require(` type myapp_log_t; ')
logging_search_logs($1) allow $1 myapp_log_t:file read_file_perms; ')
- DOKUMENTATION
Erläuterungen zu den Referenzrichtlinien
Die Referenzrichtlinien entwickeln sich wie jedes freie Softwareprojekt: auf der Grundlage freiwilliger Beiträge
- Das Projekt wird von Tresys gehostet, einem der aktivsten Unternehmen im Bereich SELinux
- Sein Wiki enthält Erläuterungen darüber, wie die Regeln strukturiert sind und wie Sie neue erstellen können
- https://github.com/SELinuxProject/refpolicy/wiki/GettingStarted
Eine .te-Datei schreiben
Sehen Sie sich die example.te-Datei an:
- WEITERE SCHRITTE
Die Makrosprache m4
Die SELinux-Entwickler verwendeten einen Makro-Befehlsprozessor, um die Richtlinien ordentlich zu strukturieren
- Anstatt viele ähnliche allow-Anweisungen zu duplizieren, haben sie „Makrofunktionen“ erstellt, um eine Logik auf höherer Ebene zu verwenden, die auch zu viel leichter lesbaren Richtlinien führt
Konkret wird m4 benutzt, um diese Regeln zu kompilieren
- Es führt den umgekehrten Vorgang durch: es erweitert alle diese auf hoher Ebene befindlichen Anweisungen zu einer großen Datenbank von allow-Anweisungen
Die SELinux-„Schnittstellen“ sind lediglich Makrofunktionen, die bei der Kompilierung durch einen Regelsatz ersetzt werden
- Desgleichen sind einige Berechtigungen in Wirklichkeit Sätze von Berechtigungen, die bei der Kompilierung durch ihre Werte ersetzt werden
policy_module(example,0) # a non-base module name must match the file name
######################################## # # Declarations #
type myapp_t; type myapp_exec_t; domain_type(myapp_t) domain_entry_file(myapp_t, myapp_exec_t)
type myapp_log_t; logging_log_file(myapp_log_t)
type myapp_tmp_t; files_tmp_file(myapp_tmp_t)
######################################## # # Myapp local policy #
allow myapp_t myapp_log_t:file { read_file_perms append_file_perms };
allow myapp_t myapp_tmp_t:file manage_file_perms; files_tmp_filetrans(myapp_t,myapp_tmp_t,file)
Das Modul muss mit seinem Namen und seiner Versionsnummer gekennzeichnet sein
| |
Falls das Modul neue Typen einführt, muss es sie mit Anweisungen wie dieser festlegen
| |
Diese Schnittstellen legen den Typ myapp_t als Prozess-Domain fest, die von jeder mit myapp_exec_t gekennzeichneten ausführbaren Datei benutzt werden sollte
| |
logging_log_file ist eine von den Referenzrichtlinien bereitgestellte Schnittstelle
| |
Die allow-Anweisung ist die grundlegende Anweisung zur Genehmigung eines Vorgangs
Berechtigungen sind als Satz erlaubter Vorgänge festgelegt und entsprechen diesem Schema: { vorgang1 vorgang2 }
Die folgende Webseite bietet eine recht vollständige Liste von Objektklassen und von Berechtigungen, die gewährt werden können |
Jetzt müssen Sie lediglich den kleinsten Regelsatz finden, der erforderlich ist, damit die Anwendung oder der Dienst, auf die er abzielt, ordnungsgemäß funktionieren
- Um dies zu erreichen, sollten Sie sich gut damit auskennen, wie die Anwendung funktioniert und welche Art von Daten sie verarbeitet oder erzeugt
Jedoch ist auch eine auf Erfahrung beruhende Vorgehensweise möglich
- Nachdem die relevanten Objekte richtig gekennzeichnet sind, können Sie die Anwendung im permissive-Modus benutzen: die Vorgänge, die verboten würden, werden protokolliert, werden aber weiterhin ausgeführt
- Durch eine Analyse der Protokolle können Sie nun die Vorgänge identifizieren, die erlaubt werden sollen
- Hier ist ein Beispiel eines derartigen Protokolleintrags:
avc: denied { read write } for pid=1876 comm="syslogd" name="xconsole" dev=tmpfs ino=5510 scontext=system_u:system_r:syslogd_t:s0 tcontext=system_u:object_r:device_t:s0 tclass=fifo_file permissive=1
Um diese Mitteilung besser verstehen zu können, gehen wir sie Schritt für Schritt durch
Tabelle Analyse eines SELinux-Ablaufs
| Meldung | Beschreibung |
|---|---|
| avc: denied | Ein Vorgang wurde abgelehnt |
| { read write } | Dieser Vorgang erforderte die Berechtigungen read und write |
| pid=1876 | Der Prozess mit der PID 1876 hat den Vorgang ausgeführt (oder hat versucht, ihn auszuführen) |
| comm="syslogd" | Der Prozess war eine Ausführung des Programms syslogd |
| name="xconsole" | Das Zielobjekt wurde xconsole genannt
|
| dev=tmpfs | Das Gerät, auf dem sich das Zielobjekt befindet, ist ein tmpfs (ein im Arbeitsspeicher befindliches Dateisystem)
|
| ino=5510 | Das Objekt ist mit der Inode-Nummer 5510 bezeichnet |
| scontext=system_u:system_r:syslogd_t:s0 | Dies ist der Sicherheitskontext des Prozesses, der den Vorgang ausgeführt hat |
| tcontext=system_u:object_r:device_t:s0 | Dies ist der Sicherheitskontext des Zielobjekts |
| tclass=fifo_file | Das Zielobjekt ist eine FIFO-Datei |
Durch Betrachtung dieses Protokolleintrags ist es möglich, eine Regel zu erstellen, die diesen Vorgang erlauben würde
- Zum Beispiel: allow syslogd_t device_t:fifo_file { read write }
- Dieser Prozess kann automatisiert werden und genau dies bietet der Befehl audit2allow (aus dem Paket policycoreutils)
- Diese Herangehensweise ist nur sinnvoll, wenn die verschiedenen Objekte bereits in Übereinstimmung mit den erforderlichen Einschränkungen richtig gekennzeichnet sind
- In jedem Fall müssen Sie die erzeugten Regeln sorgfältig überprüfen und sie auf der Grundlage ihrer Kenntnis der Anwendung bewerten
- Faktisch tendiert diese Herangehensweise dazu, mehr Berechtigungen zu erteilen, als tatsächlich erforderlich sind
- Die richtige Lösung besteht häufig darin, neue Typen zu erstellen und dann nur diesen Typen Berechtigungen zu gewähren
- Es kommt auch vor, dass ein verweigerter Vorgang für die Anwendung keine Folgen hat
- In diesem Fall kann es besser sein, einfach eine „dontaudit“-Regel hinzuzufügen, um einen Protokolleintrag zu vermeiden, obwohl eine Verweigerung stattgefunden hat
- ERGÄNZUNGEN
Keine Rollen in den Richtlinien
Es mag seltsam erscheinen, dass bei der Erstellung neuer Regeln Rollen überhaupt nicht auftreten
- SELinux verwendet nur die Domains um herauszufinden, welche Vorgänge erlaubt sind
- Die Rolle kommt nur indirekt zum Tragen, indem sie es dem Benutzer erlaubt, zu einer anderen Domain zu wechseln
- SELinux basiert auf einer Theorie, die Type Enforcement heißt und der Typ ist das einzige Element, das bei der Gewährung von Berechtigungen zählt
Die Dateien kompilieren
Sobald die 3 Dateien (example.if, example.fc und example.te) Ihren Erwartungen für die neuen Regeln entsprechen, benennen Sie sie in myappEndung um und führen Sie make NAME=devel aus, um ein Modul in der Datei myapp.pp zu erzeugen (Sie können es sofort mit semodule -i myapp.pp laden)
- Wenn mehrere Module definiert sind, erzeugt make alle entsprechenden .pp-Dateien