Fehlerbehebung bei Problemen im Zusammenhang mit SELinux

Mat McCabe, Joe Walker, Peter Boy (pboy) Version F36 and newer Last review: 2023-06-18

Wenn Sie SELinux auf Systemen aktivieren möchten, auf denen es zuvor deaktiviert war, oder wenn Sie einen Dienst in einer nicht standardmäßigen Konfiguration betreiben, müssen Sie möglicherweise Situationen beheben, die von SELinux blockiert werden. Beachten Sie, dass SELinux-Verweigerungen in den meisten Fällen auf eine Fehlkonfiguration hinweisen.

Identifizieren von SELinux-Verweigerungen

Befolgen Sie nur die notwendigen Schritte dieser Vorgehensweise; in den meisten Fällen müssen Sie nur Schritt 1 durchführen.

Vorgehensweise

  1. Wenn Ihr Szenario durch SELinux blockiert wird, sollten Sie zunächst die Datei /var/log/audit/audit.log überprüfen, um weitere Informationen zur Zugriffsverweigerung zu erhalten. Verwenden Sie das Werkzeug ausearch, um Audit-Protokolle abzufragen. Da SELinux-Entscheidungen, wie z. B. das Erlauben oder Verweigern des Zugriffs, zwischengespeichert werden (dieser Zwischenspeicher wird als Access Vector Cache (AVC) bezeichnet), verwenden Sie für den Parameter message type die Werte AVC und USER_AVC, zum Beispiel:

    $ sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent

    Falls keine Treffer gefunden werden, prüfen Sie, ob der Audit-Daemon läuft. Falls nicht, wiederholen Sie das Szenario mit der verweigerten Eingabe, nachdem Sie auditd gestartet haben, und prüfen Sie das Audit-Protokoll erneut.

  2. Falls auditd ausgeführt wird, aber keine Treffer in der Ausgabe von ausearch gefunden werden, überprüfen Sie die Meldungen im systemd-Journal:

    $ sudo journalctl -t setroubleshoot
  3. Wenn SELinux aktiv ist und der Audit-Daemon auf Ihrem System nicht läuft, suchen Sie in der Ausgabe des Befehls dmesg nach bestimmten SELinux-Meldungen:

    $ sudo dmesg | grep -i -e type=1300 -e type=1400
  4. Selbst nach den drei vorangegangenen Prüfungen ist es möglich, dass Sie nichts gefunden haben. In diesem Fall können AVC-Ablehnungen aufgrund von dontaudit-Regeln unterdrückt werden.

    Um die dontaudit-Regeln vorübergehend zu deaktivieren und so zu ermöglichen, dass alle Ablehnungen protokolliert werden,können Sie Folgendes tun:

    $ sudo semodule -DB

    Nachdem Sie Ihr abgelehntes Szenario erneut ausgeführt und mithilfe der vorherigen Schritte Ablehnungsmeldungen gefunden haben, aktiviert der folgende Befehl die dontaudit-Regeln in der Richtlinie wieder:

    $ sudo semodule -B
  5. Wenn Sie alle vier vorherigen Schritte angewendet haben und das Problem weiterhin unidentifiziert bleibt, sollten Sie prüfen, ob SELinux Ihr Szenario tatsächlich blockiert:

    • Wechseln Sie in den permissiven Modus:

      $ sudo setenforce 0
      $ getenforce
      Permissive
    • Wiederholen Sie Ihr Szenario.

Wenn das Problem weiterhin besteht, blockiert etwas anderes als SELinux Ihr Szenario.

Analyse von SELinux-Verweigerungsmeldungen

Nachdem Sie festgestellt haben, dass SELinux Ihr Szenario blockiert, müssen Sie möglicherweise die Ursache analysieren, bevor Sie eine Lösung auswählen.

Voraussetzungen

  • Die Pakete policycoreutils-python-utils und setroubleshoot-server sind auf Ihrem System installiert.

Vorgehensweise

  1. Weitere Details zu einer protokollierten Ablehnung können Sie mit dem Befehl sealert auflisten, zum Beispiel:

    $ sealert -l "*"
    SELinux is preventing /usr/bin/passwd from write access on the file
    /root/test.
    
    *****  Plugin leaks (86.2 confidence) suggests *****************************
    
    Falls Sie ignorieren möchten, dass `passwd` versucht, schreibend auf die
    Testdatei zuzugreifen, weil Sie der Ansicht sind, dass es diesen Zugriff
    nicht benötigen sollte, dann sollten Sie dies als Fehler melden.
    Sie können ein lokales Richtlinienmodul erstellen, um diesen Zugriff mittels
    `dontaudit` zu unterdrücken.
    Führen Sie Folgendes aus:
    # ausearch -x /usr/bin/passwd --raw | audit2allow -D -M my-passwd
    # semodule -X 300 -i my-passwd.pp
    
    *****  Plugin catchall (14.7 confidence) suggests **************************
    
    ...
    
    Raw Audit Messages
    type=AVC msg=audit(1553609555.619:127): avc:  denied  { write } for
    pid=4097 comm="passwd" path="/root/test" dev="dm-0" ino=17142697
    scontext=unconfined_u:unconfined_r:passwd_t:s0-s0:c0.c1023
    tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0
    
    ..
    
    Hash: passwd,passwd_t,admin_home_t,file,write
  2. Falls die im vorherigen Schritt erhaltenen Ergebnisse keine eindeutigen Vorschläge enthalten:

    • Aktivieren Sie die vollständige Pfadüberwachung, um die vollständigen Pfade zu den aufgerufenen Objekten anzuzeigen und zusätzliche Linux-Überwachungsereignisfelder sichtbar zu machen:

      $ sudo auditctl -w /etc/shadow -p w -k shadow-write
    • Leeren Sie den setroubleshoot-Zwischenspeicher:

      $ sudo rm -f /var/lib/setroubleshoot/setroubleshoot.xml
    • Reproduzieren Sie das Problem.

    • Wiederholen Sie Schritt 1.

      Deaktivieren Sie nach Abschluss des Vorgangs die vollständige Pfadüberwachung:

      $ sudo auditctl -W /etc/shadow -p w -k shadow-write
  3. Falls sealert lediglich catchall-Vorschläge liefert oder das Hinzufügen einer neuen Regel mittels des Werkzeugs audit2allow empfiehlt, gleichen Sie Ihr Problem mit den Beispielen ab, die in den SELinux-Verweigerungen im Audit-Protokoll aufgeführt und erläutert sind.

Weitere Ressourcen

  • Handbuchseite sealert(8)

Behebung analysierter SELinux-Verweigerungen

In den meisten Fällen liefern die vom Werkzeug sealert bereitgestellten Vorschläge die richtige Anleitung zur Behebung von Problemen im Zusammenhang mit der SELinux-Richtlinie. Informationen zur Verwendung von sealert für die Analyse von SELinux-Verweigerungsmeldungen finden Sie unter „Analyse von SELinux-Verweigerungsmeldungen“.

Seien Sie vorsichtig, wenn das Werkzeug die Verwendung von audit2allow für Konfigurationsänderungen vorschlägt. Sie sollten audit2allow nicht als erste Option nutzen, um ein lokales Richtlinienmodul zu generieren, sobald Sie eine SELinux-Verweigerung (Denial) feststellen. Die Fehlersuche sollte stattdessen mit der Überprüfung beginnen, ob ein Problem mit der Kennzeichnung (Labeling) vorliegt. Der zweithäufigste Fall ist, dass Sie die Konfiguration eines Prozesses geändert haben, dabei jedoch vergessen haben, SELinux darüber zu informieren.

Probleme mit Kennzeichnungen

Eine häufige Ursache für Probleme bei der Kennzeichnung ist die Verwendung eines nicht standardmäßigen Verzeichnisses für einen Dienst. Ein Administrator könnte beispielsweise für eine Website anstelle von /var/www/html/ das Verzeichnis /srv/myweb/ verwenden wollen. Unter Red Hat Enterprise Linux ist das Verzeichnis /srv mit dem Typ var_t gekennzeichnet. In /srv erstellte Dateien und Verzeichnisse erben diesen Typ. Zudem können neu erstellte Objekte in Verzeichnissen der obersten Ebene – wie etwa /myserver – mit dem Typ default_t gekennzeichnet werden. SELinux hindert den Apache HTTP-Server (httpd) daran, auf Objekte dieser beiden Typen zuzugreifen. Um den Zugriff zu ermöglichen, muss SELinux bekannt sein, dass die Dateien in /srv/myweb/ für httpd zugänglich sein sollen:

$ sudo semanage fcontext -a -t httpd_sys_content_t "/srv/myweb(/.*)?"

Dieser semanage-Befehl fügt den Kontext für das Verzeichnis /srv/myweb/ sowie für alle darin enthaltenen Dateien und Unterverzeichnisse zur SELinux-Dateikontext-Konfiguration hinzu. Das Dienstprogramm semanage ändert den Kontext dabei nicht. Wenden Sie die Änderungen als Benutzer root mithilfe des Dienstprogramms restorecon an:

$ sudo restorecon -R -v /srv/myweb

Falscher Kontext Das Dienstprogramm matchpathcon überprüft den Kontext eines Dateipfads und vergleicht ihn mit der Standardkennzeichnung für diesen Pfad. Das folgende Beispiel veranschaulicht die Verwendung von matchpathcon auf einem Verzeichnis, das falsch gekennzeichnete Dateien enthält:

$ matchpathcon -V /var/www/html/*
/var/www/html/index.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0
/var/www/html/page1.html has context unconfined_u:object_r:user_home_t:s0, should be system_u:object_r:httpd_sys_content_t:s0

In diesem Beispiel sind die Dateien index.html und page1.html mit dem Typ user_home_t gekennzeichnet. Dieser Typ wird für Dateien in Benutzer-Home-Verzeichnissen verwendet. Wenn Sie Dateien mithilfe des Befehls mv aus Ihrem Home-Verzeichnis verschieben, kann dies dazu führen, dass diese Dateien mit dem Typ user_home_t gekennzeichnet werden. Dieser Typ sollte außerhalb von Home-Verzeichnissen nicht vorkommen. Verwenden Sie das Dienstprogramm restorecon, um solchen Dateien wieder ihren korrekten Typ zuzuweisen:

$ sudo restorecon -v /var/www/html/index.html
restorecon reset /var/www/html/index.html context unconfined_u:object_r:user_home_t:s0->system_u:object_r:httpd_sys_content_t:s0

Um den Kontext für alle Dateien in einem Verzeichnis wiederherzustellen, verwenden Sie die Option -R:

$ sudo restorecon -R -v /var/www/html/
restorecon reset /var/www/html/page1.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/html/index.html context unconfined_u:object_r:samba_share_t:s0->system_u:object_r:httpd_sys_content_t:s0

Eingeschränkte Anwendungen, die auf nicht standardmäßige Weise konfiguriert wurden

Dienste können auf verschiedene Arten ausgeführt werden. Um dies zu berücksichtigen, müssen Sie die Ausführungsmethode Ihrer Dienste festlegen. Dies erreichen Sie mithilfe von booleschen SELinux-Werten, die es ermöglichen, Teile der SELinux-Richtlinie zur Laufzeit zu ändern. So können Sie beispielsweise den Zugriff von Diensten auf NFS-Datenträgern erlauben, ohne die SELinux-Richtlinie neu laden oder kompilieren zu müssen. Die Ausführung von Diensten auf nicht standardmäßigen Portnummern erfordert zudem eine Aktualisierung der Richtlinienkonfiguration mit dem Befehl semanage.

Um beispielsweise dem Apache HTTP-Server die Kommunikation mit MariaDB zu ermöglichen, aktivieren Sie die boolesche Variable httpd_can_network_connect_db:

$ sudo setsebool -P httpd_can_network_connect_db on

Beachten Sie, dass die Option -P dafür sorgt, dass die Einstellung auch nach einem Neustart des Systems erhalten bleibt.

Falls der Zugriff auf einen bestimmten Dienst verweigert wird, verwenden Sie die Dienstprogramme getsebool und grep, um zu prüfen, ob boolesche Werte verfügbar sind, die den Zugriff ermöglichen. Verwenden Sie beispielsweise den Befehl getsebool -a | grep ftp, um nach FTP-bezogenen booleschen Werten zu suchen:

$ getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_nfs --> off

ftpd_connect_db --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off

Um eine Liste von booleschen Werten abzurufen und festzustellen, ob diese aktiviert oder deaktiviert sind, verwenden Sie den Befehl getsebool -a. Um eine Liste von booleschen Werten – einschließlich ihrer Bedeutung – abzurufen und festzustellen, ob diese aktiviert oder deaktiviert sind, installieren Sie das Paket selinux-policy-devel und verwenden Sie als Root den Befehl semanage boolean -l.

*Portnummern

Je nach Konfiguration der Richtlinien ist es Diensten möglicherweise nur gestattet, auf bestimmten Portnummern ausgeführt zu werden. Der Versuch, den Port zu ändern, auf dem ein Dienst läuft, ohne gleichzeitig die Richtlinien anzupassen, kann dazu führen, dass der Dienst nicht gestartet werden kann. Führen Sie beispielsweise den Befehl semanage port -l | grep http als Root aus, um die mit http verknüpften Ports aufzulisten:

$ sudo semanage port -l | grep http
http_cache_port_t              tcp      3128, 8080, 8118
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

Der Port-Typ http_port_t definiert die Ports, an denen der Apache HTTP-Server lauschen kann – in diesem Fall die TCP-Ports 80, 443, 488, 8008, 8009 und 8443. Konfiguriert ein Administrator die Datei httpd.conf so, dass httpd an Port 9876 lauscht (Listen 9876), die Richtlinie jedoch nicht entsprechend aktualisiert wird, schlägt der folgende Befehl fehl:

$ sudo systemctl start httpd.service
Job for httpd.service failed. See 'systemctl status httpd.service' and 'journalctl -xn' for details.

$ sudo systemctl status httpd.service
httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
   Active: failed (Result: exit-code) since Thu 2013-08-15 09:57:05 CEST; 59s ago
  Process: 16874 ExecStop=/usr/sbin/httpd $OPTIONS -k graceful-stop (code=exited, status=0/SUCCESS)
  Process: 16870 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)

Eine SELinux-Verweigerungsmeldung, ähnlich der folgenden, wird in /var/log/audit/audit.log protokolliert:

type=AVC msg=audit(1225948455.061:294): avc:  denied  { name_bind } for  pid=4997 comm="httpd" src=9876 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket

Damit httpd an einem Port lauschen kann, der nicht für den Port-Typ http_port_t aufgeführt ist, verwenden Sie den Befehl semanage port, um dem Port eine andere Kennzeichnung zuzuweisen:

$ sudo semanage port -a -t http_port_t -p tcp 9876

Die Option -a ` fügt einen neuen Datensatz hinzu; die Option `-t definiert einen Typ; und die Option -p definiert ein Protokoll. Das letzte Argument ist die hinzuzufügende Portnummer.

Sonderfälle, sich entwickelnde oder fehlerhafte Anwendungen und kompromittierte Systeme

Anwendungen können Fehler enthalten, die dazu führen, dass SELinux den Zugriff verweigert. Zudem unterliegen die SELinux-Regeln einer ständigen Weiterentwicklung – es ist möglich, dass SELinux eine Anwendung noch nie in einer bestimmten Ausführungsweise beobachtet hat; dies kann eine Zugriffsverweigerung zur Folge haben, selbst wenn die Anwendung erwartungsgemäß funktioniert. Wird beispielsweise eine neue Version von PostgreSQL veröffentlicht, führt diese unter Umständen Aktionen aus, die in der aktuellen Richtlinie noch nicht berücksichtigt sind; dies kann dazu führen, dass der Zugriff verweigert wird, obwohl er eigentlich gestattet sein sollte.

Verwenden Sie in diesen Situationen – nachdem der Zugriff verweigert wurde – das Dienstprogramm audit2allow, um ein benutzerdefiniertes Richtlinienmodul zu erstellen, das den Zugriff gewährt. Fehlende Regeln in den SELinux-Richtlinien können Sie im Red Hat Bugzilla melden. Erstellen Sie für Red Hat Enterprise Linux 8 entsprechende Fehlerberichte für das Produkt „Red Hat Enterprise Linux 8“ und wählen Sie dabei die Komponente selinux-policy aus. Fügen Sie solchen Fehlerberichte die Ausgaben der Befehle audit2allow -w -a und audit2allow -a bei.

Fordert eine Anwendung weitreichende Sicherheitsberechtigungen an, könnte dies ein Hinweis darauf sein, dass die Anwendung kompromittiert ist. Setzen Sie Intrusion-Detection-Tools (Einbruchserkennungswerkzeuge) ein, um solch verdächtiges Verhalten zu überprüfen.

Die Solution Engine im Red Hat Customer Portal kann ebenfalls Hilfestellung bieten – in Form eines Artikels, der eine mögliche Lösung für genau das Problem (oder ein sehr ähnliches) enthält, mit dem Sie konfrontiert sind. Wählen Sie das entsprechende Produkt sowie die Version aus und verwenden Sie SELinux-bezogene Schlüsselwörter – wie etwa „selinux“ oder „avc“ – in Kombination mit dem Namen des blockierten Dienstes oder der blockierten Anwendung; zum Beispiel: selinux samba.

SELinux-Verweigerungen im Audit-Protokoll

Das Linux-Audit-System speichert Protokolleinträge standardmäßig in der Datei /var/log/audit/audit.log.

Um ausschließlich SELinux-bezogene Einträge aufzulisten, verwenden Sie den Befehl ausearch, wobei der Parameter für den Meldungstyp auf mindestens AVC und AVC_USER gesetzt ist – zum Beispiel:

$ sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR

Ein SELinux-Verweigerungseintrag in der Audit-Protokolldatei kann wie folgt aussehen:

type=AVC msg=audit(1395177286.929:1638): avc:  denied  { read } for  pid=6591 comm="httpd" name="webpages" dev="0:37" ino=2112 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:nfs_t:s0 tclass=dir

Die wichtigsten Teile dieses Eintrags sind:

  • avc: denied – die von SELinux durchgeführte und im Access Vector Cache (AVC) protokollierte Aktion

  • { read } – die verweigerte Aktion

  • pid=6591 – die Prozesskennung des Subjekts, das versucht hat, die verweigerte Aktion auszuführen

  • comm="httpd" – der Name des Befehls, der zum Aufrufen des analysierten Prozesses verwendet wurde

  • httpd_t – der SELinux-Typ des Prozesses

  • nfs_t – der SELinux-Typ des Objekts, das von der Prozessaktion betroffen ist

  • tclass=dir – die Klasse des Zielobjekts

Der vorherige Protokolleintrag lässt sich wie folgt übersetzen:

SELinux hat dem Prozess httpd mit der PID 6591 und dem Typ httpd_t das Lesen aus einem Verzeichnis mit dem Typ nfs_t verweigert.

Die folgende SELinux-Fehlermeldung tritt auf, wenn der Apache HTTP-Server versucht, auf ein Verzeichnis zuzugreifen, das mit einem Typ für die Samba-Suite gekennzeichnet ist:

type=AVC msg=audit(1226874073.147:96): avc:  denied  { getattr } for  pid=2465 comm="httpd" path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file
  • { getattr } – der Eintrag getattr zeigt an, dass der Quellprozess versucht hat, die Statusinformationen der Zieldatei zu lesen. Dies geschieht vor dem eigentlichen Lesen von Dateien. SELinux verweigert diese Aktion, da der Prozess auf die Datei zugreift, aber nicht über die entsprechende Berechtigung verfügt. Häufig vorkommende Berechtigungen sind getattr, read und write.

  • path="/var/www/html/file1" – der Pfad zu dem Objekt (Ziel), auf das der Prozess zugreifen wollte.

  • scontext="unconfined_u:system_r:httpd_t:s0" – der SELinux-Kontext des Prozesses (Quelle), der die verweigerte Aktion versucht hat. In diesem Fall handelt es sich um den SELinux-Kontext des Apache HTTP-Servers, der mit dem Typ httpd_t ausgeführt wird.

  • tcontext="unconfined_u:object_r:samba_share_t:s0" – der SELinux-Kontext des Objekts (Ziels), auf das der Prozess zuzugreifen versuchte. In diesem Fall handelt es sich um den SELinux-Kontext von file1.

Diese SELinux-Verweigerung lässt sich wie folgt übersetzen:

SELinux hat dem Prozess httpd mit der PID 2465 den Zugriff auf die Datei /var/www/html/file1 vom Typ samba_share_t verweigert, da diese für Prozesse, die in der httpd_t-Domäne ausgeführt werden, nicht zugänglich ist, sofern nichts anderes konfiguriert ist.

Zusätzliche Ressourcen

  • Handbuchseiten auditd(8) und ausearch(8)