Sven Erik Matzen

Software Architect | Cloud & Security Expert | AI-enabled Solutions

Der programmierbare Kern: eBPF und die Sandbox im Herzen des Betriebssystems

🎧 Listen to this article

Cloud Computing · 2026-08-31

EU-Kennzeichnung: vollständig KI-generierter Inhalt Vollständig KI-generierter Artikel (ohne Vorabprüfung).

Der Aufhänger: Fremder Code im Allerheiligsten

Stell dir vor, du dürftest ein eigenes, kleines Programm mitten in das Getriebe eines fahrenden Zuges schrauben – während der Zug mit voller Geschwindigkeit fährt, mit Hunderten Passagieren an Bord, und ein einziger Fehler nicht bloß deinen Programmcode, sondern die gesamte Lokomotive zum Stillstand oder zur Entgleisung bringen würde. Genau das ist, in etwas anderem Gewand, seit jeher die verbotene Frucht der Systemprogrammierung: Code direkt im Betriebssystemkern auszuführen, jenem privilegierten Herzstück, das über allem thront, alle Hardware kontrolliert und in dem es keine Sicherheitsnetze gibt. Ein Programm im Userspace kann abstürzen, und das Betriebssystem räumt es auf. Ein Programm im Kern, das abstürzt, reißt die ganze Maschine mit – der berüchtigte Kernel Panic, der Blue Screen der Unix-Welt.

Über Jahrzehnte war das eine harte, unverrückbare Grenze. Wer den Kern erweitern wollte – um Netzwerkpakete anders zu filtern, um Systemaufrufe zu beobachten, um eine neue Sicherheitsregel durchzusetzen –, hatte genau zwei Optionen, beide unbefriedigend. Entweder man schrieb ein Kernelmodul: nativer Maschinencode, der mit vollen Rechten im Kern läuft, blitzschnell, aber lebensgefährlich, denn ein einziger fehlgeleiteter Zeiger legt das ganze System lahm oder öffnet ein Sicherheitsleck im mächtigsten Teil der Software. Oder man verlegte die Arbeit in den Userspace: sicher gekapselt, aber langsam, weil jede Interaktion mit dem Kern ein teurer Kontextwechsel ist und die Daten mühsam hin- und herkopiert werden müssen.

Es schien ein weiteres jener ehernen Zielkonflikte zu sein, wie sie die Informatik durchziehen: Man kann die Geschwindigkeit und die tiefe Sichtbarkeit des Kerns haben – oder die Sicherheit des Userspace, nicht beides. Genau diese vermeintliche Zwangsläufigkeit hat eine Technologie namens eBPF in den letzten zehn Jahren aufgebrochen, und zwar so gründlich, dass sie heute als eine der einflussreichsten Neuerungen in der Geschichte des Linux-Kerns gilt. Die Idee ist so elegant wie subversiv: Man lässt fremden Code doch in den Kern hinein – aber nur solchen Code, den eine mathematische Prüfinstanz vorher bewiesenermaßen für harmlos befunden hat. Nicht Vertrauen, sondern Verifikation.

Für jemanden wie Sven, der mit einem Bein in der Cloud-Architektur und einem in der IT-Sicherheit steht, ist eBPF ein Musterbeispiel dafür, wie eine kluge Neuverhandlung der Vertrauensgrenze einen scheinbar unauflösbaren Kompromiss verschiebt – ganz ähnlich, wie es Die Wette auf fremden Code: Firecracker microVMs und das Ende des Container-VM-Dilemmas für die Virtualisierung getan hat. Dieser Artikel nimmt dich mit auf die ganze Strecke: von der überraschenden Herkunft aus einem Paketfilter der frühen 1990er über die drei Säulen, die eBPF sicher machen, und die Bausteine, aus denen es besteht, bis zu den drei großen Feldern, die es heute umpflügt – Netzwerk, Beobachtbarkeit und Sicherheit –, und schließlich zu den ehrlichen Grenzen einer Technik, die selbst zur neuen, mächtigen Angriffsfläche geworden ist.


Teil 1: Die überraschende Herkunft – von einem Paketfilter zur Universalmaschine

Die Geschichte beginnt nicht mit einer großen Vision, sondern mit einem sehr konkreten, sehr nüchternen Problem: Wie fischt man effizient bestimmte Netzwerkpakete aus dem Datenstrom, ohne sich totzukopieren? 1992 entwarfen Steven McCanne und Van Jacobson am Lawrence Berkeley Laboratory eine Antwort, die sie 1993 auf der Winter-USENIX-Konferenz in San Diego vorstellten: den Berkeley Packet Filter (BPF). Wer je das Werkzeug tcpdump benutzt und einen Ausdruck wie tcp port 443 eingegeben hat, hat unwissentlich BPF verwendet – dieser Ausdruck wird in ein kleines Programm übersetzt, das im Kern läuft.

Der geniale Kunstgriff von McCanne und Jacobson war nicht der Filter selbst, sondern die Architektur dahinter. Statt Regeln in einer starren Tabelle abzuarbeiten, definierten sie eine winzige, abstrakte virtuelle Maschine im Kern: einen simplen Registerrechner mit einem klar umrissenen Befehlssatz, in dem sich Filterlogik als kleines Programm ausdrücken ließ. Der Filter wurde damit von einer Datenstruktur zu Code. Die Pakete mussten nicht mehr in den Userspace kopiert werden, um dort verworfen zu werden; die Entscheidung fiel schon im Kern, direkt an der Quelle. Das war schnell, sparsam und – für die damalige Zeit revolutionär – programmierbar innerhalb einer sicheren, eng begrenzten Abstraktion.

Über zwei Jahrzehnte blieb dieser „klassische BPF" (rückblickend cBPF genannt) ein nützliches, aber begrenztes Nischenwerkzeug für Paketfilter und, später, für die Einschränkung erlaubter Systemaufrufe via seccomp-bpf – jenem Mechanismus, der auch bei der Container-Isolation eine Rolle spielt. Dann, 2014, tat Alexei Starovoitov etwas, das die Sache grundlegend veränderte. Er nahm die Grundidee – eine sichere virtuelle Maschine im Kern – und baute sie von Grund auf neu, viel größer gedacht. Das Ergebnis, „extended BPF" oder eBPF, erschien im Dezember 2014 im Linux-Kernel 3.18.

Der Sprung war qualitativ, nicht bloß quantitativ. Die neue virtuelle Maschine bekam zehn statt zwei Register, eine Breite von 64 Bit passend zu moderner Hardware, die Fähigkeit, persistente Datenstrukturen zu halten, und – der entscheidende Punkt – sie wurde vom Netzwerkstack entkoppelt. eBPF war nicht länger ein Paketfilter, der zufällig programmierbar war, sondern eine allgemeine Ausführungsmaschine im Kern, an die man sich an Dutzenden Stellen andocken konnte. Die Abkürzung BPF blieb aus historischen Gründen, aber sie ist heute irreführend: Mit „Berkeley" und „Packet Filter" hat das moderne eBPF nur noch die Ahnenlinie gemein. Es ist zu etwas geworden, das die Kernelentwickler halb im Scherz, halb im Ernst als „Skript-Sprache für den Kern" oder als „JavaScript des Betriebssystems" bezeichnen: eine Art, den Kern zur Laufzeit sicher zu erweitern, ohne ihn neu zu kompilieren, ohne ein Modul zu laden und ohne die Maschine neu zu starten.


Teil 2: Das Dilemma – Kernelmodul gegen Userspace

Um zu würdigen, was eBPF leistet, muss man das Problem sauber sezieren, das es löst. Der Kern eines Betriebssystems läuft im privilegierten Kernel-Modus der CPU: Er darf alles, sieht alles, kontrolliert alle Hardware. Anwendungsprogramme laufen im User-Modus: eingesperrt in ihren eigenen Speicherbereich, ohne direkten Hardwarezugriff, überwacht vom Kern. Diese Trennung, von der Hardware selbst erzwungen, ist das Fundament aller Systemsicherheit. Sie ist der Grund, warum ein abstürzender Browser nicht den ganzen Rechner mitreißt.

Wer die Fähigkeiten des Kerns erweitern will, steht damit vor einem echten Dilemma. Der Weg über ein Kernelmodul bedeutet, eigenen Code in den Kernel-Modus zu bringen. Er ist maximal mächtig und schnell, denn er läuft mit vollen Rechten direkt dort, wo die Ereignisse passieren. Aber er ist auch maximal gefährlich: Es gibt keine Isolation. Ein Nullzeiger-Zugriff, ein Pufferüberlauf, eine Endlosschleife – und die ganze Maschine steht oder wird verwundbar. Jedes geladene Modul vergrößert die Trusted Computing Base, also die Menge an Code, dem man blind vertrauen muss, und jeder Fehler darin ist ein potenzieller Totalschaden. Erschwerend kommt hinzu, dass Kernelmodule eng an die exakte Kernel-Version gebunden sind und bei jedem Update brechen können.

Der Weg über den Userspace dreht die Abwägung genau um. Hier ist der Code sicher gekapselt; ein Absturz betrifft nur den eigenen Prozess. Aber der Preis ist Geschwindigkeit und Sichtbarkeit. Jede Frage an den Kern – „welche Systemaufrufe macht dieser Prozess gerade?", „was passiert mit diesem Paket?" – erfordert einen Kontextwechsel, das teure Umschalten zwischen User- und Kernel-Modus, und oft das Kopieren großer Datenmengen über diese Grenze hinweg. Für einen Paketfilter, der Millionen Pakete pro Sekunde sichten soll, oder für ein Beobachtungswerkzeug, das jeden Systemaufruf mitschneiden möchte, ist dieser Overhead ruinös. Man sieht die Ereignisse gewissermaßen nur aus der Ferne, durch ein schmales, teures Fenster.

Die verbreitete Meinung lautete also: tiefe Sichtbarkeit und Geschwindigkeit oder Sicherheit. eBPFs Antwort ist eine dritte Position, die das Dilemma auflöst, indem sie eine neue Vertrauensgrenze zieht – nicht zwischen User- und Kernel-Modus, sondern innerhalb des Kerns, um jedes einzelne eingeschleuste Programm herum. Der Code läuft mit der Geschwindigkeit und Sichtbarkeit des Kerns, aber eingesperrt in eine Sandbox, deren Wände nicht aus Hardware bestehen, sondern aus einem mathematischen Beweis.


Teil 3: Die drei Säulen der Sicherheit

Wie kann man fremden, potenziell fehlerhaften Code in den Kern lassen, ohne die Maschine zu gefährden? eBPF ruht dabei auf drei tragenden Säulen, deren Zusammenspiel den ganzen Trick ausmacht.

Die erste und wichtigste Säule ist der Verifier. Bevor ein eBPF-Programm überhaupt laufen darf, unterzieht der Kern es einer statischen Analyse – einer Prüfung des Codes, ohne ihn auszuführen. Der Verifier modelliert das Programm als gerichteten Graphen aller möglichen Ausführungspfade und geht diese systematisch durch. Er verlangt und beweist eine Reihe harter Eigenschaften. Das Programm muss terminieren. Endlosschleifen sind verboten, denn ein Programm, das im Kern nie zurückkehrt, wäre ein perfekter Denial-of-Service-Angriff gegen die eigene Maschine. Frühe Kernel verboten Schleifen ganz; seit Kernel 5.3 erlaubt der Verifier beschränkte Schleifen (bounded loops), indem er die Schleife gedanklich abrollt und nachweist, dass die Laufvariable monoton läuft und einen Grenzwert erreicht. Das Programm darf nur gültigen Speicher berühren. Jeder Zeigerzugriff wird gegen bekannte Grenzen geprüft; ein Zugriff außerhalb, ein Lesen aus uninitialisiertem Speicher, eine Dereferenzierung eines möglicherweise ungültigen Zeigers – all das lässt der Verifier gar nicht erst zu. Das Programm darf keine sensiblen Kerndaten preisgeben und nur eine eng umrissene Menge erlaubter Operationen ausführen. Erst wenn all diese Beweise gelingen, wird das Programm akzeptiert; scheitert auch nur einer, wird es rundweg abgelehnt. Der Verifier ist damit kein Wächter, der zur Laufzeit eingreift, sondern ein Torhüter, der schon vor dem Start entscheidet – und im Zweifel gegen die Zulassung.

Die zweite Säule ist die JIT-Kompilierung (Just-in-Time). Ein einmal verifiziertes eBPF-Programm liegt zunächst als plattformunabhängiger Bytecode für die virtuelle Maschine vor. Statt diesen Bytecode langsam Instruktion für Instruktion zu interpretieren, übersetzt ihn der Kern zur Ladezeit in nativen Maschinencode der jeweiligen CPU-Architektur. Das Ergebnis läuft mit der vollen Geschwindigkeit von handgeschriebenem Kernelcode. Sicherheit und Tempo schließen sich also gerade nicht aus: Die Sicherheit steckt in der Prüfung vor der Ausführung, die Geschwindigkeit in der nativen Ausführung danach. Man bezahlt die Sicherheit einmalig beim Laden, nicht bei jeder einzelnen Instruktion.

Die dritte Säule ist die eingeschränkte Umgebung selbst. Ein eBPF-Programm ist kein freies C-Programm. Es darf nicht beliebige Kernelfunktionen aufrufen, sondern nur eine kuratierte, stabile Menge von Helfer-Funktionen (helpers), die der Kern bereitstellt – etwa um die Uhrzeit zu lesen, auf eine Datenstruktur zuzugreifen oder ein Paket umzuschreiben. Es hat einen begrenzten Stack, es kann nicht beliebig Speicher allozieren, und es kann den Kern nicht blockieren. Diese bewusste Kargheit ist keine Schikane, sondern Teil der Sicherheitsarchitektur: Je kleiner und klarer die Schnittstelle zwischen dem Sandbox-Programm und dem Kern, desto weniger kann schiefgehen und desto vollständiger kann der Verifier seine Beweise führen.

Zusammen ergeben die drei Säulen eine bemerkenswerte Umkehrung der üblichen Logik. Bei einem Kernelmodul lautet die Frage: „Vertraue ich dem Autor genug, um seinen Code mit vollen Rechten laufen zu lassen?" Bei eBPF lautet sie: „Kann eine Maschine beweisen, dass dieser Code, egal wer ihn schrieb, keinen Schaden anrichten kann?" Es ist der Übergang von der sozialen Kategorie des Vertrauens zur mathematischen Kategorie des Beweises.


Teil 4: Die Bausteine – Programme, Hooks, Maps und Helfer

Ein einzelnes, isoliertes Programm im Kern wäre wenig wert. Die Mächtigkeit von eBPF entsteht aus dem Zusammenspiel einiger weniger Grundbausteine, die sich zu erstaunlich komplexen Systemen fügen lassen.

Da sind zunächst die Hooks, die Andockpunkte. Ein eBPF-Programm läuft nicht von sich aus, sondern wird an ein Ereignis im Kern geheftet und immer dann ausgeführt, wenn dieses Ereignis eintritt. Die Bandbreite dieser Andockpunkte ist der eigentliche Grund für die Universalität von eBPF. Am XDP-Hook (eXpress Data Path) hängt sich ein Programm noch im Netzwerktreiber ein, an der frühestmöglichen Stelle, bevor der Kern überhaupt eine Datenstruktur für das Paket angelegt hat – das ist der schnellste Punkt für Paketverarbeitung, mit dem sich Angriffe abwehren oder Pakete umleiten lassen, bevor sie irgendeinen Aufwand verursachen. Am tc-Hook (traffic control) sitzt man etwas später im Netzwerkpfad, mit mehr Kontext. An kprobes und tracepoints klinkt man sich an nahezu beliebige Funktionen und definierte Ereignisse im Kern, um sie zu beobachten. An uprobes beobachtet man sogar Funktionen in Userspace-Programmen. Und am LSM-Hook (Linux Security Module) setzt man sich an die sicherheitsrelevanten Entscheidungspunkte des Kerns und kann Operationen erlauben oder verbieten. Ein und dieselbe Technologie deckt damit Netzwerk, Beobachtung und Sicherheit ab – nur der Andockpunkt unterscheidet sich.

Der zweite Baustein sind die Maps. Ein eBPF-Programm ist zustandslos und kurzlebig; es feuert, wenn sein Ereignis eintritt, und ist dann wieder vorbei. Um Zustand zu halten und Daten weiterzugeben, gibt es Maps: Schlüssel-Wert-Speicher im Kern, die persistent bleben. Mehrere eBPF-Programme können sich dieselbe Map teilen, und – entscheidend – auch der Userspace kann eine Map lesen und beschreiben. Damit entsteht die Brücke zwischen der Sandbox im Kern und der Anwendungswelt darüber: Ein eBPF-Programm im Kern zählt beispielsweise Pakete pro Verbindung in eine Hash-Map, und ein Userspace-Dashboard liest diese Zahlen aus, ohne selbst jemals ein Paket berühren zu müssen. Maps gibt es in vielen Ausprägungen – Hash-Tabellen, Arrays, Ringpuffer für Ereignisströme, spezialisierte Strukturen für Load-Balancing – und sie sind das Rückgrat jeder nichttrivialen eBPF-Anwendung.

Der dritte Baustein sind die schon erwähnten Helfer-Funktionen und, als jüngere Verallgemeinerung, die kfuncs, über die Programme kontrolliert bestimmte Kernelfunktionen nutzen dürfen. Und ein vierter, subtiler Baustein sind die Tail Calls: die Fähigkeit eines eBPF-Programms, an ein anderes zu übergeben, wodurch sich größere Logik in verkettete, je einzeln verifizierbare Häppchen zerlegen lässt – ein eleganter Weg, die absichtlichen Größenbeschränkungen der Sandbox zu umgehen, ohne die Sicherheit aufzugeben.

Bleibt ein hartnäckiges praktisches Problem: Portabilität. Ein eBPF-Programm, das interne Kernel-Datenstrukturen liest, ist an deren exaktes Speicherlayout gebunden – und dieses Layout ändert sich von Kernel-Version zu Kernel-Version. Früher musste man eBPF-Programme deshalb auf der Zielmaschine gegen die dort laufenden Kernel-Header neu übersetzen, was in der Praxis eine Qual war. Die Lösung heißt BTF (BPF Type Format) und CO-RE (Compile Once – Run Everywhere). BTF ist eine kompakte Beschreibung der Typen und Datenstrukturen eines Kerns; CO-RE nutzt sie, damit ein einmal übersetztes eBPF-Programm zur Ladezeit automatisch an das tatsächliche Speicherlayout des laufenden Kerns angepasst wird. Zusammen mit der Userspace-Bibliothek libbpf hat CO-RE eBPF von einer fragilen Bastelei zu einer robusten, auslieferbaren Technologie gemacht – ein oft unterschätzter, aber entscheidender Schritt zur breiten Praxistauglichkeit.


Teil 5: Erstes Feld – Networking, wo alles begann

Es ist kein Zufall, dass die Wiedergeburt von BPF im Netzwerk ihren stärksten Widerhall fand: Hier wurzelt die Technik, und hier war der Leidensdruck am größten. Das klassische Werkzeug zur Paket- und Regelverarbeitung im Linux-Kern war jahrzehntelang iptables (und sein Unterbau netfilter). Es funktioniert, aber sein grundlegendes Problem ist die lineare Abarbeitung: Regeln werden in Ketten der Reihe nach durchprüft. Bei einer Handvoll Regeln ist das egal. In einem modernen Kubernetes-Cluster mit Tausenden von Diensten, die sich ständig ändern, wächst die Regelmenge jedoch enorm, und die Verarbeitungszeit wächst mit ihr – ein O(n)-Verhalten, das bei großer Skalierung zum spürbaren Flaschenhals wird.

Genau hier setzt Cilium an, das prominenteste eBPF-Projekt im Netzwerkbereich, ursprünglich von der Firma Isovalent entwickelt und heute ein Graduated-Projekt der Cloud Native Computing Foundation. Ciliums Kernidee ist, die Netzwerklogik von Kubernetes vollständig in eBPF-Programme zu verlagern, die an XDP- und tc-Hooks hängen und Pakete verarbeiten, bevor sie den vollen Netzwerkstack durchlaufen. Der spektakulärste Effekt ist der Ersatz von kube-proxy, der Standardkomponente, die in Kubernetes die Dienst-IP-Adressen auf konkrete Backend-Container abbildet. kube-proxy tat dies traditionell über iptables mit ebenjener linearen Regelabarbeitung. Cilium ersetzt das durch Hash-Tabellen-Lookups in eBPF-Maps und verwandelt so die Zuordnung von einer O(n)-Suche in eine O(1)-Operation: eine konstante, von der Zahl der Dienste unabhängige Nachschlagzeit. Die Verwandtschaft zu den Ideen aus Der Ring, der die Last verteilt: Consistent Hashing und die Kunst des sanften Umzugs liegt auf der Hand – auch hier geht es darum, Last effizient und stabil auf viele Ziele zu verteilen.

Cilium bringt außerdem ein Beobachtungswerkzeug namens Hubble mit, das die Netzwerkflüsse eines Clusters in Echtzeit sichtbar macht, weil die eBPF-Programme, die den Verkehr ohnehin steuern, ihn zugleich protokollieren können. Netzwerkrichtlinien lassen sich nicht mehr nur auf IP-Ebene, sondern bis hinauf zur Anwendungsschicht (etwa einzelne HTTP-Pfade) durchsetzen, und das direkt im Kern. Was iptables an konzeptioneller Last mit sich schleppte, löst eBPF durch Programmierbarkeit an der richtigen Stelle auf.


Teil 6: Zweites Feld – Observability ohne Instrumentierung

Das vielleicht magischste Anwendungsfeld ist die Beobachtbarkeit (observability). Wer bisher wissen wollte, wie sich eine Anwendung im Detail verhält – welche Funktionen wie lange dauern, welche Systemaufrufe sie macht, wo Latenz entsteht –, musste den Code meist instrumentieren: Messpunkte einbauen, Bibliotheken einbinden, die Anwendung neu übersetzen und ausrollen. Das ist aufwendig, invasiv und oft schlicht unmöglich, etwa bei fremder Software oder in produktiven Systemen, die man nicht anfassen darf.

eBPF dreht dieses Verhältnis um. Weil man Programme an kprobes, uprobes und tracepoints hängen kann, lässt sich ein laufendes System von außen und ohne jede Änderung am Anwendungscode durchleuchten – die Werbeformel dafür lautet „Zero-Instrumentation". Das granulare Urgestein dieser Welt ist bpftrace, eine an das klassische Unix-Werkzeug awk angelehnte Skriptsprache, mit der sich in wenigen Zeilen eine Frage an den laufenden Kern formulieren lässt: „Zeige mir die Verteilung der Antwortzeiten aller Lese-Systemaufrufe" oder „welcher Prozess öffnet gerade wie viele Dateien". Darunter liegt die ältere Bibliothek bcc (BPF Compiler Collection) mit einer Sammlung fertiger Diagnosewerkzeuge. Diese Ergonomie ist wesentlich von Brendan Gregg geprägt worden, dessen Arbeit eBPF-Tracing einer breiten Ingenieursgemeinde zugänglich gemacht hat.

Auf dieser Grundlage sind ganze Plattformen entstanden. Pixie etwa sammelt automatisch Telemetrie über Latenz, Durchsatz und Ressourcennutzung in Kubernetes-Clustern, ohne dass ein Entwickler auch nur eine Zeile Instrumentierung schreiben müsste. Parca nutzt eBPF für kontinuierliches Profiling im laufenden Betrieb, um zu zeigen, wo Rechenzeit wirklich verbraucht wird. Der gemeinsame Nenner ist immer derselbe: Statt jede Anwendung einzeln mit Messtechnik auszurüsten, misst man einmal an der zentralen Stelle, an der ohnehin alle Ereignisse zusammenlaufen – im Kern. Für eine Cloud, in der Hunderte heterogene Dienste zusammenspielen, ist das ein tiefgreifender Wandel: Beobachtbarkeit wird von einer Eigenschaft, die jede Anwendung mühsam selbst mitbringen muss, zu einer Eigenschaft der Plattform.


Teil 7: Drittes Feld – Runtime-Security im Kern

Das dritte große Feld schließt den Kreis zur IT-Sicherheit. Wenn man mit eBPF ohnehin jeden Systemaufruf, jede Prozesserzeugung, jeden Dateizugriff und jede Netzwerkverbindung im Kern beobachten kann, dann kann man dieselbe Fähigkeit nutzen, um bösartiges Verhalten in Echtzeit zu erkennen – und, an den richtigen Hooks, sogar zu unterbinden.

Das reifste Werkzeug dieser Art ist Falco, ursprünglich von der Firma Sysdig gebaut, 2018 der Cloud Native Computing Foundation gestiftet und dort inzwischen ein Graduated-Projekt. Falco beobachtet über eBPF den Strom der Systemaufrufe und schlägt Alarm, wenn ein Prozess Dinge tut, die auf einen Einbruch hindeuten: eine Shell, die aus einem Webserver-Container heraus gestartet wird; ein Zugriff auf sensible Dateien wie /etc/shadow; eine unerwartete ausgehende Netzwerkverbindung. Es ist gewissermaßen ein Einbruchmeldesystem, das direkt an der Quelle sitzt, an der die verdächtigen Handlungen tatsächlich passieren. Tetragon, aus dem Cilium-Umfeld, geht einen Schritt weiter und kann verdächtige Operationen nicht nur melden, sondern auch synchron durchsetzen – also einen Aufruf blockieren oder einen Prozess beenden, bevor der Schaden eintritt –, weil es sich an Hooks setzt, an denen der Kern die Entscheidung noch nicht getroffen hat. Tracee von Aqua Security ist ein weiteres prominentes Werkzeug dieser Kategorie.

Die tiefste Integration bietet BPF-LSM (auch KRSI, Kernel Runtime Security Instrumentation), das eBPF-Programme direkt an die Entscheidungspunkte des Linux-Security-Module-Frameworks hängt – jene Stellen, an denen der Kern ohnehin fragt: „Darf diese Operation ausgeführt werden?". Hier lässt sich programmierbare, feingranulare Sicherheitspolitik unmittelbar im Kern verankern, mit der Autorität, Operationen verbindlich zu erlauben oder zu verweigern. Der sicherheitspolitische Reiz liegt auf der Hand: Man erkennt Angriffe nicht mehr nur nachträglich aus Logdateien, sondern greift im Moment ihres Geschehens ein.

Zugleich mahnt gerade dieses Feld zur Nüchternheit. eBPF ist ein Werkzeug, keine Wunderwaffe. Seitenkanalangriffe wie Spectre und Meltdown (siehe Wenn der Prozessor zu viel rät: Spectre, Meltdown und die Sünde der spekulativen Ausführung), physische Angriffe wie Rowhammer (siehe Bits, die von selbst umkippen: Rowhammer und die physikalische Schwachstelle des Arbeitsspeichers) oder ausgefeilte Supply-Chain-Angriffe (siehe Die Hintertür im Herzen von Linux: Der XZ-Backdoor und die Anatomie eines Supply-Chain-Angriffs) operieren auf Ebenen, die eBPF nicht abdeckt oder sogar selbst betreffen können. Sicherheit bleibt ein Schichtenwerk.


Teil 8: Die neuen Fronten – vom Scheduler bis zu Windows

eBPF hat in den letzten Jahren begonnen, selbst tiefste Bastionen des Kerns zu erobern. Der spektakulärste jüngere Schritt ist sched_ext, in Kernel 6.12 (November 2024) aufgenommen: ein Rahmen, der es erlaubt, den CPU-Scheduler – jenes hochkritische Herzstück, das entscheidet, welcher Prozess wann auf welchem Kern rechnen darf – als eBPF-Programm zu schreiben. Was zuvor unvorstellbar war, weil ein fehlerhafter Scheduler die Maschine sofort zum Erliegen brächte, wird durch die Verifier-Garantien und einen Sicherheitsmechanismus, der einen hängenden eBPF-Scheduler notfalls automatisch durch den eingebauten ersetzt, handhabbar. Plötzlich lassen sich Scheduling-Strategien für konkrete Lasten – Spiele, Server, latenzkritische Dienste – experimentell erproben, ohne den Kern neu zu bauen oder die Maschine neu zu starten. Es ist die vielleicht eindrucksvollste Demonstration der eBPF-These: Selbst das Allerheiligste des Kerns wird sicher programmierbar.

Parallel dazu reift die Infrastruktur weiter. Neuere Kernel brachten BPF Tokens, die eine sicherere Nutzung von eBPF durch weniger privilegierte Instanzen erlauben, sowie BPF Arenas, die großen, gemeinsam genutzten Speicher zwischen Programmen bereitstellen. Institutionell wurde eBPF 2021 unter das Dach der Linux Foundation gestellt: Die eBPF Foundation bündelt seither die Interessen von Firmen wie Meta, Google, Microsoft, Isovalent und Netflix und steuert die Weiterentwicklung als gemeinschaftliches Gut. Und die Idee hat sogar das Betriebssystem gewechselt: Mit eBPF für Windows entwickelt Microsoft eine Portierung, die dieselbe Programmierschnittstelle auf den Windows-Kern bringt – ein Zeichen dafür, dass eBPF sich von einer Linux-Eigenheit zu einem plattformübergreifenden Standard für sichere Kernel-Erweiterung wandelt.


Teil 9: Die ehrlichen Grenzen – wenn die Sandbox selbst zur Angriffsfläche wird

Ein Artikel, der eine Technik nur preist, tut ihr keinen Gefallen. Svens Präferenz für wissenschaftlich gesicherte, überprüfbare Aussagen verlangt, auch die Schattenseiten klar zu benennen – und eBPF hat sie.

Die schärfste liegt im Herzstück selbst: Die gesamte Sicherheit von eBPF ruht auf der Korrektheit des Verifiers. Der Verifier ist ein komplexes Stück Software, und ein Fehler in ihm bedeutet, dass ein Programm für sicher erklärt wird, obwohl es das nicht ist – mit vollen Kernrechten. In der Vergangenheit sind wiederholt Verifier-Schwachstellen gefunden worden, die Privilegienerweiterung ermöglichten. Besonders heikel ist die Klasse der spekulativen Typenverwirrung (speculative type confusion): Angriffe, die – verwandt mit Spectre – die spekulative Ausführung des Prozessors nutzen, um die Garantien des Verifiers zu unterlaufen, weil der Verifier den logischen Kontrollfluss prüft, die CPU aber spekulativ auch Pfade betritt, die logisch nie erreicht würden. Der Kern muss deshalb zusätzliche Härtungsmaßnahmen gegen spekulative Ausführung in eBPF-Programme einweben, und das Wechselspiel bleibt ein aktives Forschungs- und Sicherheitsfeld.

Die zweite Grenze ist eine Frage der Trusted Computing Base. eBPF verkleinert die Vertrauensbasis in einer Hinsicht – man muss dem einzelnen geladenen Programm nicht mehr vertrauen, weil es verifiziert ist. Aber es vergrößert sie in anderer Hinsicht: Der Verifier, die JIT-Kompilierung und die wachsende Menge an Helfern und Hooks sind allesamt Code im Kern, dem man vertrauen muss. Je mächtiger eBPF wird, desto größer wird diese neue, kritische Angriffsfläche. Weil eBPF zudem tiefen Einblick in das ganze System gibt, ist es ein zweischneidiges Schwert: Dieselbe Fähigkeit, mit der Falco Angreifer entdeckt, kann ein Angreifer nutzen, um ein besonders schwer entdeckbares Rootkit zu bauen, das den Datenverkehr belauscht und seine eigenen Spuren im Kern verwischt. Es sind bereits eBPF-basierte Schadprogramme dieser Art beobachtet worden.

Die dritte, praktische Grenze ist Komplexität. eBPF-Programme zu schreiben, die den Verifier bestehen, ist eine eigene Kunst; die Fehlermeldungen des Verifiers sind berüchtigt kryptisch, und die Beschränkungen der Sandbox verlangen ungewohnte Programmiermuster. Und trotz CO-RE bleibt die Bindung an interne, instabile Kernel-Strukturen eine dauernde Quelle von Fragilität, wie neuere Untersuchungen zur Stabilität eBPF-basierter Kernel-Erweiterungen zeigen.

Ich bin der Meinung, dass diese Grenzen die Bilanz nicht umkehren, sondern schärfen: eBPF ist kein Zaubertrick, der Sicherheit umsonst liefert, sondern ein durchdachter Tausch – man verlagert das Vertrauen von vielen unbekannten Modulautoren auf einen einzigen, intensiv geprüften Verifier und zahlt dafür mit der Verantwortung, ausgerechnet diesen Verifier makellos zu halten.


Erkenntnis zum Mitnehmen

Die zentrale Lektion von eBPF reicht weit über den Linux-Kern hinaus. Sie lautet: Ein scheinbar ehernder Zielkonflikt lässt sich manchmal auflösen, indem man die Grundlage des Vertrauens verschiebt – von der Person, die den Code schreibt, zu einem Beweis über den Code selbst. Die alte Frage „Darf ich diesem Autor genug trauen, um seinen Code mit vollen Rechten laufen zu lassen?" ist eine soziale, unzuverlässige, nicht skalierbare Frage. Die eBPF-Frage „Kann eine Maschine beweisen, dass dieser Code, egal von wem, keinen Schaden anrichten kann?" ist eine mathematische, überprüfbare, automatisierbare Frage. Wo immer du in deiner Architektur vor einer harten Wahl zwischen Mächtigkeit und Sicherheit stehst, lohnt die eBPF-Frage: Gibt es eine überprüfbare Eigenschaft, die ich erzwingen kann, statt auf Wohlverhalten zu hoffen?

Für die tägliche Praxis heißt das ganz konkret: Wenn du in einem Kubernetes-Cluster mit Netzwerklatenz, undurchsichtigem Verhalten oder Sicherheitsanforderungen ringst, lohnt sich der Blick auf die eBPF-Werkzeuge, bevor du zu invasiveren Mitteln greifst. Ein bpftrace-Einzeiler kann eine Frage über das laufende System beantworten, für die man früher einen Debugger, einen Neustart oder umgebauten Code gebraucht hätte – ohne die Produktion anzufassen. Und wenn du das nächste Mal hörst, ein Cloud-Anbieter habe „das Netzwerk komplett neu gedacht" oder biete „Observability ohne Agenten", steht die Chance gut, dass im Maschinenraum ein verifiziertes kleines Programm im Herzen des Kerns die Arbeit tut.


Reflexionsfrage zum Schluss

eBPF hat gezeigt, dass man fremden Code sicher ins Allerheiligste eines Systems lassen kann, sofern eine Maschine seine Harmlosigkeit beweist. Wenn diese Idee – Ausführung nur nach maschinell geführtem Sicherheitsbeweis – so tragfähig ist: An welchen anderen Stellen deiner Systeme verlässt du dich heute noch auf das Vertrauen in den Autor eines Stücks Code, wo du morgen einen Beweis über den Code verlangen könntest – und was würde sich an deiner Architektur ändern, wenn Verifikation die Norm würde und Vertrauen die Ausnahme?


Querverweise im Vault


Quellen

← All articles