Landlock LSM: Sandboxing im Kernel ohne root Wir vertrauen Software blind. Ein Update, eine scheinbar harmlose .deb-Datei oder ein schnell heruntergeladener Python-Skript vom Server des Kunden – oft läuft das ganze Chaos mit vollen Benutzerrechten ab. Im Linux-Umfeld gab es lange nur AppArmor oder SELinux, um da etwas Ordnung reinzubringen. Doch beide erfordern Administratorrechte und viel Konfigurationsaufwand. Was ist also, wenn man als normaler User seine eigenen Anwendungen einschränken will? Hier kommt Landlock ins Spiel. Stellen Sie sich vor, Ihre Wohnung (das Dateisystem) hat viele geschützte Räume. Mit Landlock können Sie bestimmte Türen für bestimmte Gäste (Prozesse) einfach zuschließen. Und das Beste: Sie brauchen dafür keine Baugenehmigung des Vermieters (also keine root-Rechte). Das Konzept ist simpel: Der Linux-Kernel bietet seit Version 5.13 eine neue Mandatory Access Control (MAC), die es jedem Prozess erlaubt, seine eigenen Dateizugriffsrechte einzuschränken. Klingt nach einem Nischenthema? Überlegen Sie das nochmal: Jeder, der Home-Labs betreibt oder unsichere Dienste lokal testet, kann damit seine Angriffsfläche drastisch senken. Wie funktioniert Landlock eigentlich? Um zu verstehen, was Landlock leistet, müssen wir kurz einen Schritt zurückgehen. Linux nutzt seit langer Zeit Security Modules, die über den Linux Security Module (LSM)-Framework angesteuert werden. Bekannte Vertreter sind AppArmor, SELinux und YaBBR. All diese Lösungen basieren auf demselben Prinzip: Regeln definieren, wer was darf. Aber sie haben einen großen Nachteil: Die Richtlinien werden zentral verwaltet und benötigen fast immer administrative Berechtigungen. Landlock dreht dieses Modell um. Es folgt dem Prinzip des Least Privilege von innen nach außen. Ein Programm kann aktiv entscheiden, dass es nicht mehr auf alle Dateien zugreifen will, obwohl es technisch die Berechtigung hätte. Wenn dann ein Exploit das Programm kompromittiert, ist der Angreifer sofort in einer Sandbox gefangen, die selbst bei voller Ausführungsumgebung nur sehr begrenzt agieren kann. Konkret gesehen bedeutet das: Wenn mein Webserver nur auf sein own Document Root zugreifen soll, kann ich ihm sagen „du darfst nur diesen Pfad lesen und schreiben, alles andere bleibt für dich gesperrt“ – und zwar vom Anwendungsprozess selbst aus. Beispiel: Grundlegendes Sandboxing mit landlock Die praktischste Methode, Landlock auszuprobieren, ist das Kommandozeilentool landlock, das Teil des bubblewrap-Pakets ist. Stellen wir uns vor, wir möchten den Editor vim so starten, dass er nur auf das Verzeichnis /tmp/meine-dateien Zugriff hat. Wir könnten sonst versehentlich Systemdateien überschreiben. Der Aufruf sieht wie folgt aus: mkdir -p /tmp/meine-dateien touch /tmp/meine-dateien/test.txt # Starte vim mit Landlock-Einschränkung bwrap --ro-bind / / --dev /dev --proc /proc --bind /tmp/meine-dateien /data \ --die-with-parent --share-net -- \ landlock-create /bin/vim /data/test.txt Hier binden wir das gesamte Host-System schreibgeschützt ein (--ro-bind / /) und legen darüberhinweg ein neues Mount-Verzeichnis /data an, das auf unser Testverzeichnis zeigt. Der entscheidende Befehl landlock-create erstellt eine Landlock-Richtlinie, die ausschließlich Lesezugriffe auf /data zulässt. Innerhalb von Vim können wir nun zwar unsere Textdatei öffnen, versuchen wir jedoch, über :shell auf etwas außerhalb zuzugreifen, erhalten wir eine klaren Fehlermeldung: "Operation not permitted". Der Kernel durchsetzt die Grenze konsequent. Persönliche Einschätzung: Ich war anfangs skeptisch, ob ein solches Feature jemals echte Relevanz bekommen würde, da es doch eher im Bereich des Defense-in-Depth liegt. Doch je mehr ich damit spiele, desto mehr sehe ich Potenzial – besonders für CI-Pipelines oder lokale Entwicklungsumgebungen, wo ungetesteter Code häufig ausgeführt wird. Dass kein Daemon im Hintergrund laufen muss und keine globale Policy gepflegt werden muss, ist ein riesiger Pluspunkt für den Daily Use. Landlock programmatisch nutzen Natürlich reicht es nicht aus, Tools wie bwrap zu benutzen; Entwickler wollen Landlock direkt in ihre Applikationen integrieren. Dafür stellt der Kernel spezielle Syscalls bereit (landlock_add_restriction). Glücklicherweise gibt es Bibliotheken, die das Leben erleichtern. Eine der bekanntesten ist liblandlock, eine Header-only-Bibliothek in C, die auch leicht in Go oder Python eingebunden werden kann. Schauen wir uns an, wie wir eine Anwendung schreiben, die sich selbst sandboxed. Angenommen, wir haben einen kleinen Service, der Daten aus einem Logfile liest. Wir wollen sicherstellen, dass dieser Service niemals versucht, irgendetwas zu beschreiben oder außerhalb seiner Logs zu lesen. Beispiel: Eigene C-Anwendung mit Landlock absichern Hier ein minimalistisches C-Code-Snippet, das demonstriert, wie man eine Regel definiert: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/syscall.h> #include <linux/landlock.h> #define _LANDLOCK_CREATE_RESTRICTION_SYSCALL (__NR_landlock_create_restriction) int main() { struct landlock_rule_attr rule_attr = { .parent_handle = NULL, .path_beneath = NULL, .allowed_access fs_read = LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR }; // In der Realität müssten Sie hier File Handles öffnen und validieren // Dies ist ein stark vereinfachtes Pseudocode-Beispiel zur Veranschaulichung printf("Starte abgesicherten Prozess...\n"); // Hier würde landlock_add_restriction(2, &rule_attr, sizeof(rule_attr)) stehen execvp("tail", argv); return 0; } In einer echten Implementierung würden Sie mit open() Handles für die erlaubten Pfade erstellen, diese in die Struktur füllen und dann den Syscall feuern. Sobald dies geschehen ist, kann der aktuelle Thread und alle zukünftigen Child-Prozesse nichts mehr tun, was gegen diese Regeln verstößt. Versucht die Anwendung später, eine Datei in /etc zu öffnen, schlägt der open()-Call mit EPERM fehl. Ein weiteres praktisches Tool ist firejail. Obwohl Firejail primär auf Namespaces basiert, integriert es mittlerweile Landlock, um die Isolation noch enger zu ziehen. Mit einem einzigen Befehl: firejail --net=none --private=/home/user/safe-area firefox startet man Firefox komplett isoliert. Die Kombination aus经典 Container-Techniken und dem Kernel-internen Landlock sorgt dafür, dass selbst bei gravierenden Browser-Exploits der Schadcode kaum Daten exfiltrieren kann. Persönliche Einschätzung: Für reine CLI-Tools ist die direkte Integration vielleicht Overkill. Aber denken Sie an Docker-In-Docker Szenarien oder Build-Jobs: Wenn Sie Jenkins oder GitLab Runner Jobs mit Landlock umschließen, eliminieren Sie sofort eine ganze Klasse von Escape-Angriffen. Die APIs sind noch frisch, aber stabil genug für den Einsatz in Nicht-Mission-Critical Bereichen. Die Hürde, eigene C-Routinen zu schreiben, schreckt ab, daher freuen wir uns auf bessere Bindings für höhere Sprachen wie Rust oder Go. Häufige Fehler und Einschränkungen Wie bei jeder neuen Sicherheitstechnologie stolpert man auch bei Landlock schnell über Fallstricke. Da es relativ neu ist (erste Mainline-Integration 2021), fehlen teilweise noch Feinheiten in der Dokumentation und der Community-Wissenstand ist klein. 1. Verwechslung mit Capabilities Viele Admins versuchen, Landlock als Ersatz für Linux Capabilities (capsh) zu sehen. Das ist falsch. Capabilities regeln Systemaufrufe (wie bind auf einem Port < 1024), während Landlock spezifisch das Dateisystem kontrolliert. Eine Anwendung, die durch Landlock eingeschränkt ist, kann weiterhin Netzwerksockets öffnen oder Threads erzeugen – sie darf nur keine verbotenen Dateien berühren. Nutzen Sie beides zusammen für maximale Sicherheit. 2. Mount-Namespace Probleme Wenn Sie Landlock in Kombination mit komplexen Mount-Strategien (viele Bind-Mounts, OverlayFS) nutzen, kann es passieren, dass Pfade nicht mehr auflösbar sind, weil die Auflösung schon vor der Landlock-Prüfung scheitert. Achten Sie darauf, die Richtlinientiefe richtig zu setzen. Standardmäßig schränkt Landlock rekursiv alles unter einem Pfad ein. Manchmal hilft es, explizite Ausnahmen für /proc/self zu machen, falls die App ihre eigenen Statusdaten auslesen will. 3. Kernel-Versionen beachten Ihr Kernel muss mindestens Version 5.13 unterstützen, besser jedoch 6.x, da in 6.1 viele Verbesserungen bezüglich Socket-Locking eingeflossen sind (noch experimentell). Prüfen Sie mit uname -r und stellen Sie sicher, dass in der Kernel-Konfiguration CONFIG_SECURITY_LANDLOCK=y gesetzt ist. Auf vielen Distributionen wie Ubuntu 22.04 LTS oder Debian Bookworm ist dies standardmäßig aktiviert. Fazit: Ist Landlock Production Ready? Wenn ich heute ein Homelab betreibe oder Continuous Integration Pipelines baue, nutze ich Landlock aktiv. Es ersetzt nicht SELinux in einem hochsicheren Unternehmensnetzwerk, aber es füllt eine Lücke, die sonst offenbliebe: Die Möglichkeit für normale Benutzer, defensive Programmierung direkt durchzusetzen. Besonders beeindruckend finde ich die Minimalität – keine Policy-Datenbanken, keine komplizierten Modi wie 'permissive vs enforcing', nur einfache Zugriffsrechte auf Dateibäume. Wenn Sie Neugierig geworden sind, ist der nächste Schritt einfach: Laden Sie bubblewrap herunter (fast jede Distro bietet es als Paket) und versuchen Sie, Ihren Lieblingsbrowser oder einen lokalen Dev-Server darin auszuführen. Spüren Sie selbst, wie gut der Kernel diese Grenzen hält. In einer Welt, in der Supply-Chain-Angriffe zunehmen, ist jede Schicht der Isolation Gold wert – auch eine, die Sie selbst als User steuern.