Nginx 403 Fehler durch SELinux beheben
Nginx liefert trotz korrekter Dateirechte einen 403 Fehler. Erfahren Sie, wie Sie SELinux Denials analysieren und mit semanage sowie restorecon die Labels korrekt setzen.
Warum nginx bei einer Datei mit korrekten Berechtigungen einen 403-Fehler zurückgibt
Wenn nginx einen 403-Fehler für eine Datei ausgibt, obwohl die Berechtigungsbits korrekt gesetzt sind, verweigert fast immer SELinux (Security-Enhanced Linux) den Lesezugriff. SELinux prüft einen zweiten Regelsatz, nachdem die normalen Dateiberechtigungen erfolgreich validiert wurden. Der Webserver darf nur Dateien lesen, die mit einem Label für Webinhalte versehen sind. Ihre Datei trägt ein anderes Label, weshalb das Öffnen fehlschlägt und nginx keine Daten senden kann.
Prüfen Sie nicht nur den Modus, sondern auch das Label:
ls -ldZ /data/www /data/www/index.htmldrwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /data/www
-rw-r--r--. root root unconfined_u:object_r:default_t:s0 /data/www/index.htmlDer Punkt, der nach drwxr-xr-x ausgegeben wird, bedeutet, dass die Datei ein SELinux-Label trägt. default_t ist das Label, das ein Pfad erhält, wenn die Policy ihn nicht kennt, und keine Regel des Webservers das Lesen dieses Typs erlaubt. Das Fehlerprotokoll zeigt einen gewöhnlichen Unix-Fehler an, weshalb dies wie ein Berechtigungsfehler aussieht:
2026/08/11 09:14:02 [error] 1183#1183: *1 open() "/data/www/index.html" failed (13: Permission denied), client: 203.0.113.9, server: _, request: "GET / HTTP/1.1"Der Kernel gibt für beide Arten der Verweigerung, sowohl für die gewöhnliche als auch für die durch SELinux, 13: Permission denied zurück. Die erste Aufgabe besteht daher darin, herauszufinden, welche Ebene den Zugriff verweigert hat. Beginnen Sie nicht mit setenforce 0.
Der benötigte Teil des Modells
SELinux ist eine Form der obligatorischen Zugriffskontrolle, meist als MAC bezeichnet. Jeder Prozess läuft in einer Domäne, wie etwa httpd_t für den Webserver. Jede Datei und jeder Netzwerkport besitzt einen Typ, wie beispielsweise httpd_sys_content_t. Die Richtlinie ist eine Liste zulässiger Kombinationen aus Domäne, Typ und Aktion; alles, was nicht auf dieser Liste steht, wird verweigert. Sie wird nach der klassischen Unix-Prüfung ausgeführt, daher müssen die Berechtigungsbits in drwxr-xr-x den Zugriff ebenfalls zuerst erlauben. Beide Ebenen müssen zustimmen.
Ein vollständiger Kontext besteht aus vier durch Doppelpunkte getrennten Feldern, wie system_u:system_r:httpd_t:s0: der SELinux-Benutzer, die Rolle, der Typ und die Ebene. Auf einem Server verbringen Sie fast die gesamte Zeit mit dem dritten Feld, dem Typ. Zwei Befehle zeigen die aktuellen Werte an:
ps -eZ | grep nginx
id -ZDie nginx-Worker zeigen einen Kontext, der auf httpd_t endet. Ihre Login-Shell zeigt unconfined_u:unconfined_r:unconfined_t:s0, da die standardmäßige targeted-Richtlinie Dienste einschränkt, interaktive Benutzer jedoch unangetastet lässt. Das ist wichtig zu wissen, da SELinux nicht das Ausführen von Diensten unter Benutzern mit minimalen Rechten ersetzt. Es begrenzt lediglich, was ein Dienst erreichen kann, nachdem jemand in ihn eingedrungen ist.
Die drei Modi und welche Images SELinux enthalten
sestatus
getenforceEnforcing blockiert und protokolliert. Permissive erlaubt alles und protokolliert, was blockiert worden wäre. Disabled lädt überhaupt keine Richtlinie. getenforce gibt den aktuellen Modus aus. sestatus gibt zusätzlich den Modus aus /etc/selinux/config aus, welcher nach einem Neustart wieder aktiv ist.
Rocky Linux, AlmaLinux, Fedora und RHEL werden mit der SELinux-Richtlinie targeted im Modus Enforcing ausgeliefert. Diese gemeinsame Standardeinstellung ist kein Zufall, da alle vier Distributionen aus derselben Red-Hat-Linie stammen, die vor dem Erscheinen von Rocky Linux und AlmaLinux durch CentOS verlief. Welche der beiden Distributionen Sie verwenden, spielt für die Inhalte auf dieser Seite keine Rolle, da sie dieselben Richtlinien und Werkzeuge bereitstellen. Daher hängt die Wahl zwischen Rocky Linux und AlmaLinux eher von Kompatibilitätsversprechen und der Unterstützung älterer CPUs ab als von Sicherheitsstandards. Ubuntu und Debian verwenden stattdessen AppArmor, das dieselbe Aufgabe mit einem anderen Mechanismus erfüllt (der letzte Abschnitt behandelt dies). Daher kann dieselbe Anwendung auf einem Ihrer Server problemlos installiert werden und auf einem anderen einen 403-Fehler zurückgeben.
Installieren Sie die Werkzeuge, bevor Sie sie benötigen
sudo dnf install -y policycoreutils-python-utils setroubleshoot-serversemanage: command not found auf einem minimalen Image bedeutet, dass policycoreutils-python-utils fehlt: Dieses Paket enthält semanage und audit2allow. setroubleshoot-server fügt sealert hinzu und schreibt eine verständliche Zusammenfassung jedes Zugriffsverweigerungs-Ereignisses in das Journal. Installieren Sie beides auf einem neuen Server, denn der Zeitpunkt, an dem Sie diese Werkzeuge benötigen, ist genau der Moment, in dem bereits ein Fehler vorliegt.
Lesen von SELinux-Zugriffsverweigerungen im Audit-Log
Jede Verweigerung wird vom Audit-Daemon als AVC-Meldung (Access Vector Cache) aufgezeichnet:
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR -ts recenttype=AVC msg=audit(1754896442.881:412): avc: denied { read } for pid=1183 comm="nginx" name="index.html" dev="vda1" ino=17203 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0Vier Felder enthalten die gesamte Information. comm ist das Programm, das blockiert wurde. scontext ist der Quellkontext, also die Domain, in der der Prozess lief. tcontext ist der Zielkontext, die Kennzeichnung des Objekts, auf das zugegriffen werden sollte. tclass ist die Art des Objekts, hier eine Datei. Zusammen gelesen bedeutet dies: Der Prozess in httpd_t versuchte, eine Datei mit der Kennzeichnung default_t zu lesen, und permissive=0 bestätigt, dass die Anfrage tatsächlich blockiert und nicht nur protokolliert wurde.
Wenn ausearch keine Ausgabe liefert, läuft der Audit-Daemon möglicherweise nicht. Verweigerungen landen dann stattdessen im Kernel-Ringpuffer:
sudo journalctl -k | grep -i avcWandeln Sie den Datensatz nun in einen verständlichen Satz um:
sudo ausearch -m AVC -ts recent | audit2why
sudo journalctl -t setroubleshoot --since today
sudo sealert -a /var/log/audit/audit.logaudit2why liest dieselben Datensätze und benennt die erkannte Ursache: ein deaktiviertes Boolean, eine Kennzeichnung, die nicht zur Richtlinie passt, oder das Fehlen einer entsprechenden Regel. sealert durchsucht das gesamte Log und gibt für jede Verweigerung einen Befehlsvorschlag aus. Betrachten Sie diesen Vorschlag als Hinweis. Der Wortlaut ändert sich zwischen den Releases, und sealert schlägt manchmal ein benutzerdefiniertes Richtlinienmodul vor, obwohl eine einzeilige Korrektur der Kennzeichnung die korrekte Lösung wäre.
Ein weiterer wichtiger Punkt: Die Richtlinie enthält dontaudit-Regeln, die als harmlos eingestufte Verweigerungen verbergen. Dadurch kann sich ein Programm fehlerhaft verhalten, während das Log leer bleibt. Deaktivieren Sie diese Filterung für die Dauer eines Tests:
sudo semodule -DB
# reproduce the problem, then read the log again
sudo semodule -BBeheben eines falsch markierten Pfads mit semanage fcontext und restorecon
Zwei Befehle, wobei die Reihenfolge entscheidend ist. semanage fcontext -a speichert, welches Label ein Pfad haben sollte. restorecon wendet diesen gespeicherten Standard auf die Dateien auf dem Datenträger an.
sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
sudo restorecon -Rv /data/www
ls -ldZ /data/www/index.htmlDer Pfad ist ein regulärer Ausdruck. (/.*)? erfasst das Verzeichnis selbst und alles darunter, was für ein Document Root erforderlich ist. Prüfen Sie die Änderungen, bevor Sie diese anwenden: sudo restorecon -Rvn /data/www gibt die geplanten Neumarkierungen aus, da -n bedeutet, dass keine Aktion ausgeführt wird. Nach einem tatsächlichen restorecon lautet das Label httpd_sys_content_t und der 403-Fehler ist ohne Neustart des Dienstes behoben.
Verwenden Sie chcon nur zu Testzwecken. chcon -t httpd_sys_content_t index.html setzt das Label direkt, aber das nächste restorecon, ein Paket-Update oder eine vollständige Neumarkierung setzt es zurück, da die Richtlinie weiterhin vorgibt, dass der Pfad ein anderes Label haben sollte. Auf einem System, auf dem dnf-automatic Sicherheitsupdates zeitgesteuert anwendet, erfolgt dieser Reset nach einem eigenen Zeitplan und nicht während Sie vor dem Rechner sitzen, sodass die Website Stunden nach Ihrer letzten Änderung ausfällt. semanage fcontext ist die Version, die dauerhaft bestehen bleibt. Listen Sie die gespeicherten Einträge mit sudo semanage fcontext -l | grep '^/data' auf.
Inhalte, in die der Dienst schreiben muss, benötigen einen anderen Typ. Verwenden Sie httpd_sys_rw_content_t für ein Upload-Verzeichnis oder einen Cache und beschränken Sie dies auf diese Pfade: Eine schreibgeschützte Website unter einem beschreibbaren Typ gewährt mehr Zugriff, als die Anwendung benötigt.
Warum war das Label überhaupt falsch? Fast immer liegt es daran, wie die Dateien auf das System gelangten. mv behält das bestehende Label einer Datei bei, sodass eine Website, die aus /root verschoben wurde, mit dem Label admin_home_t ankommt und dieses beibehält. Ein einfaches cp weist der neuen Datei das Standard-Label des Zielverzeichnisses zu, was meistens das gewünschte Verhalten ist, während cp -a und rsync -X die Quell-Labels zusammen mit der Datei kopieren. Ein git clone in ein neues Verzeichnis auf oberster Ebene erzeugt default_t. Wenn eine Seite aus /usr/share/nginx/html korrekt geladen wird, aber aus Ihrem eigenen Verzeichnis fehlschlägt, ist dies der Grund.
Behebung einer Fehlerklasse mittels Boolean
Manche Fehler liegen nicht an einer Label-Problematik. Ein Reverse Proxy auf einem frisch installierten Rocky oder AlmaLinux gibt einen 502-Fehler zurück, und das Fehlerprotokoll meldet:
2026/08/11 10:02:55 [crit] 1183#1183: *3 connect() to 127.0.0.1:3000 failed (13: Permission denied) while connecting to upstreamIhr Upstream ist in Ordnung. Die httpd_t-Domain darf standardmäßig keine ausgehenden Netzwerkverbindungen öffnen, daher wird der connect()-Aufruf verweigert, bevor er das Loopback-Interface erreicht. Ein einziger Schalter steuert dieses gesamte Verhalten:
getsebool -a | grep httpd_can_network
sudo setsebool -P httpd_can_network_connect on-P ist das entscheidende Flag: Es schreibt den Wert auf die Festplatte. Ohne -P geht die Änderung beim nächsten Neustart verloren, was zu einem Dienst führt, der nur bis zum nächsten Reboot funktioniert. Überprüfen Sie dies mit semanage boolean -l | grep httpd_can_network_connect, das den aktuellen Laufzeitwert neben dem gespeicherten Wert ausgibt.
Bevorzugen Sie einen Boolean gegenüber einer manuell erstellten Regel, sofern ein solcher existiert. Booleans werden mit der Distributionsrichtlinie ausgeliefert, sind daher gepflegt, dokumentiert und für die nächste Person leicht zu finden. getsebool -a listet alle auf dem System verfügbaren Booleans auf.
Einen Dienst auf einem nicht standardmäßigen Port lauschen lassen
Ports sind ebenfalls mit Labels versehen. Verschieben Sie nginx auf 8081, startet der Dienst nicht:
nginx: [emerg] bind() to 0.0.0.0:8081 failed (13: Permission denied)httpd_t darf nur Ports binden, die mit http_port_t gekennzeichnet sind; 8081 gehört nicht dazu. Fügen Sie den Port hinzu:
sudo semanage port -l | grep -w http_port_t
sudo semanage port -a -t http_port_t -p tcp 8081Prüfen Sie zuerst die Liste. Mehrere hohe Ports sind bereits freigegeben, darunter 8008 und 8443. Ein erneutes Hinzufügen schlägt mit ValueError: Port tcp/8081 already defined fehl. Wenn der Port bereits einem anderen Typ zugeordnet ist, ändern Sie diesen mit semanage port -m -t http_port_t -p tcp 8081, anstatt ihn erneut hinzuzufügen.
Derselbe Befehl sorgt dafür, dass ein geänderter SSH-Port funktioniert. Bind to port 2222 on 0.0.0.0 failed: Permission denied in journalctl -u sshd bedeutet, dass 2222 in ssh_port_t fehlt. Führen Sie daher sudo semanage port -a -t ssh_port_t -p tcp 2222 aus, bevor Sie den Daemon neu starten und Ihre Sitzung beenden. Diesen Schritt lassen Anwender oft aus, wenn sie einer allgemeinen Anleitung zur Härtung von SSH auf einem VPS auf einem Image der Red-Hat-Familie folgen. SELinux ist keine Firewall, daher muss der Port zusätzlich geöffnet werden: sudo firewall-cmd --permanent --add-port=8081/tcp && sudo firewall-cmd --reload hier, oder ufw auf einem Debian- oder Ubuntu-Image. Das Flag --permanent birgt dieselbe Gefahr bei einem Neustart wie -P bei einem Boolean-Wert. Es lohnt sich, die Zonen, die festlegen, für welche Schnittstellen eine Regel gilt, einmal in firewalld-Grundlagen für einen Rocky- oder AlmaLinux-VPS nachzulesen.
Wenn kein Boolean und kein Label zur Änderung vorhanden ist
Dies kommt auf einem normalen Server selten vor und ist der Punkt, an dem Benutzer Schäden verursachen. audit2allow kann aus den Verweigerungen im Log ein Richtlinienmodul erstellen:
sudo ausearch -m AVC -ts recent -c nginx | audit2allow -M nginx_local
cat nginx_local.te
sudo semodule -i nginx_local.ppLesen Sie nginx_local.te, bevor Sie es installieren. Zwei Vorgehensweisen gewährleisten Sicherheit. Filtern Sie die Eingabe mit -c auf das eine Programm, das Sie reparieren möchten, denn das Weiterleiten einer Woche an nicht zusammenhängenden Verweigerungen an audit2allow gewährt alle auf einmal. Installieren Sie niemals ein Modul, das auf einer Verweigerung basiert, die Sie nicht erklären können: Eine Regel, die es httpd_t erlaubt, jede Datei auf dem System zu lesen, ist leicht erstellt und Monate später schwer zu erkennen. Entfernen Sie ein Modul mit sudo semodule -r nginx_local.
Permissive ist ein Diagnosemodus, keine dauerhafte Lösung
sudo setenforce 0
# reproduce the problem once, all the way through
sudo ausearch -m AVC -ts recent
sudo setenforce 1Der Permissive-Modus erlaubt den Zugriff und protokolliert ihn. Sein eigentlicher Nutzen liegt in der Vollständigkeit. Im Enforcing-Modus stoppt der Dienst bei der ersten Verweigerung; Sie beheben diesen Fehler, starten neu und stoßen auf den nächsten. Im Permissive-Modus läuft der Prozess weiter und das Log erfasst alle Verweigerungen in einem Durchgang, sodass Sie diese anschließend gemeinsam beheben können.
setenforce ändert nichts an /etc/selinux/config, daher kehrt das System nach einem Neustart in den Enforcing-Modus zurück. Dies dient als Sicherheitsnetz und ist der Grund, warum eine "Lösung", die nur aus setenforce 0 bestand, im ungünstigsten Moment wieder auftritt. Wenn ein Dienst während der Arbeit mehr Spielraum benötigt, markieren Sie nur diesen Bereich anstatt des gesamten Systems: sudo semanage permissive -a httpd_t belässt alle anderen Bereiche im Enforcing-Modus, und sudo semanage permissive -d httpd_t macht dies rückgängig.
Warum das Deaktivieren von SELinux teurer ist als die Korrektur der Labels
Das Setzen von SELINUX=disabled in /etc/selinux/config tauscht eine einzeilige Korrektur der Labels gegen einen dauerhaft schwächeren Server ein. Der Unterschied zeigt sich an dem Tag, an dem eine Webanwendung kompromittiert wird. Im Modus enforcing läuft der Code des Angreifers in httpd_t, sodass er möglicherweise Webinhalte lesen kann, während das Lesen von /etc/shadow oder das Schreiben einer systemd-Unit durch die Richtlinie verweigert wird, unabhängig davon, was der Unix-Benutzer erlaubt hätte. Ohne geladene Richtlinie erhält derselbe Code alle Rechte des Dienstkontos.
Das Deaktivieren bringt zudem Kosten mit sich, die später anfallen. Während keine Richtlinie geladen ist, werden neue Dateien ohne Label erstellt, sodass das Dateisystem nicht mehr mit der Richtlinie übereinstimmt. Das erneute Einschalten von SELinux erfordert dann ein vollständiges Relabeling, andernfalls fallen eine Vielzahl von Diensten gleichzeitig aus:
sudo fixfiles -F onboot
sudo rebootDies schreibt /.autorelabel und führt beim nächsten Bootvorgang ein Relabeling des gesamten Dateisystems durch. Auf einer großen Festplatte dauert dies lange und die Konsole wirkt, als sei sie eingefroren; starten Sie den Vorgang daher nur, wenn Sie Zeit haben. Da der Rechner ohnehin herunterfährt, lohnt es sich, vorher zu prüfen, was sonst noch für einen Neustart in der Warteschlange steht, was needs-restarting nach einem dnf-Update meldet, wenn alte Kernel und Bibliotheken noch im Arbeitsspeicher liegen. Unter Rocky Linux und AlmaLinux 9 schaltet die Konfigurationsdatei den Kernel-Teil nicht mehr von alleine ab, und der dokumentierte Weg, SELinux vollständig zu deaktivieren, erfolgt über ein Kernel-Argument (sudo grubby --update-kernel ALL --args selinux=0). Diesen Befehl zu kennen, hilft, wenn man den Server eines Vorgängers übernimmt. Er ist jedoch nicht die Lösung für einen 403-Fehler.
Container um ein Label erweitern
Auf einem Host der Red-Hat-Familie laufen Container-Prozesse in container_t und dürfen nur Dateien lesen, die mit container_file_t gekennzeichnet sind. Ein Bind-Mount vom Host schlägt mit Permission denied innerhalb des Containers fehl, während ls -l auf dem Host völlig normal aussieht. Das Suffix :Z weist die Runtime an, das Mount neu zu labeln:
docker run -d -v /data/appdata:/var/lib/app:Z myimage:Z labelt das Verzeichnis ausschließlich für diesen einen Container. :z labelt es für die gemeinsame Nutzung zwischen Containern. Wenn Sie :Z auf ein Verzeichnis richten, das von anderen Diensten verwendet wird, labelt es dieses Verzeichnis rekursiv um, was diese Dienste beschädigt. Verwenden Sie daher für Container eigene Pfade. Falls die Engine noch nicht auf dem System installiert ist: Beachten Sie, dass der Befehl docker auf diesen Distributionen oft nur ein Alias für podman ist. Dies ist eine Besonderheit, die die Installationsschritte für Rocky und AlmaLinux klären, bevor Sie auf diese Problematik stoßen. Alles Weitere zur Einrichtung entspricht jedem anderen Image, wie in Docker auf einem VPS ausführen beschrieben.
Ubuntu und Debian nutzen AppArmor
Gleiche Aufgabe, anderes Design. AppArmor schränkt ein Programm über den Pfad zu seiner ausführbaren Datei ein, indem es ein Profil unter /etc/apparmor.d/ verwendet, anstatt Dateien auf dem Datenträger zu markieren. Es gibt nichts neu zu markieren und kein restorecon. Beginnen Sie hier:
sudo aa-status
sudo journalctl -k | grep -i apparmorEine Verweigerung erscheint als apparmor="DENIED" operation="open" profile="/usr/sbin/nginx" name="/data/www/index.html" requested_mask="r". Der Arbeitsablauf folgt dem gleichen Schema: Lesen Sie die Verweigerung, finden Sie das Profil, ändern Sie die Regel. sudo apt install apparmor-utils bietet Ihnen aa-complain (permissiv für ein Profil) und aa-enforce, um den ursprünglichen Zustand wiederherzustellen. Ubuntu schränkt eine ausgewählte Menge paketierter Dienste ein und lässt den Rest uneingeschränkt. Lesen Sie daher aa-status, um zu sehen, was tatsächlich aktiv ist, anstatt Vermutungen anzustellen.
Eine Gewohnheit lässt sich auf beide Systeme übertragen. Wenn ein Dienst Permission denied bei etwas meldet, das korrekt aussieht, lesen Sie das Sicherheitsprotokoll, bevor Sie die Berechtigungen ändern. Die Bits sind selten zweimal das Problem.
FAQ
Warum gibt Nginx einen 403-Fehler zurück, obwohl die Dateiberechtigungen korrekt sind?
Der Grund ist, dass SELinux den Lesezugriff verweigert, nicht die Berechtigungsbits. Der Webserver läuft in der Domäne httpd_t und darf nur Dateien lesen, die für Webinhalte gekennzeichnet sind. Eine Datei mit der Kennzeichnung default_t oder admin_home_t wird daher abgelehnt, und Nginx hat keine Daten zur Auslieferung. Überprüfen Sie dies mit sudo ausearch -m AVC -ts recent; dies zeigt scontext, das auf httpd_t endet, während tcontext den falschen Typ enthält. Ermitteln Sie anschließend die korrekte Kennzeichnung und wenden Sie diese an: sudo semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?" gefolgt von sudo restorecon -Rv /data/www.
Ist es sicher, setenforce 0 auszuführen, um einen Dienst zum Laufen zu bringen?
setenforce 0 ist ein Diagnoseschritt, keine dauerhafte Lösung. Nutzen Sie diesen Befehl, um das Problem einmalig zu reproduzieren, damit das Protokoll alle Zugriffsverweigerungen in einem Durchgang erfasst. Lesen Sie diese mit sudo ausearch -m AVC -ts recent aus, führen Sie dann sudo setenforce 1 aus und beheben Sie die Ursachen. Ein Server im Modus permissive protokolliert jede Verweigerung, blockiert jedoch nichts; Sie behalten also das Rauschen und verlieren den Schutz. Wenn ein einzelner Dienst während der Arbeit Spielraum benötigt, führen Sie sudo semanage permissive -a httpd_t aus, damit der Rest des Systems im Modus enforcing verbleibt.
Wie betreibe ich einen Dienst auf einem nicht standardmäßigen Port bei aktivem SELinux?
Fügen Sie den Port dem Typ hinzu, an den der Dienst binden darf. Für einen Webserver auf 8081: sudo semanage port -a -t http_port_t -p tcp 8081. Für SSH auf 2222: sudo semanage port -a -t ssh_port_t -p tcp 2222. Prüfen Sie vorab die aktuelle Liste mit sudo semanage port -l | grep -w http_port_t, da ein bereits gelisteter Port zu einem Fehler mit ValueError: Port tcp/8081 already defined führt. Ohne diesen Schritt beendet sich der Daemon beim Start mit bind() ... Permission denied, obwohl kein anderer Prozess den Port belegt.
Nutzt Ubuntu SELinux?
Nein. Ubuntu und Debian verwenden AppArmor. Dieses erzwingt ein Profil, das an den Pfad einer ausführbaren Datei gebunden ist, anstatt an Dateikennzeichnungen. Prüfen Sie dies mit sudo aa-status und suchen Sie nach apparmor="DENIED"-Zeilen in sudo journalctl -k. Ubuntu beschränkt nur eine Auswahl paketierter Dienste, sodass viele Programme standardmäßig unbeschränkt laufen. SELinux im Modus enforcing finden Sie standardmäßig bei Rocky Linux, AlmaLinux, Fedora und RHEL.