Nutzen Sie unsere Suite von eBPF-Bibliotheken
Startseite » Security Bloggers Network » Nutzen Sie unsere Suite von eBPF-Bibliotheken
Von Artem Dinaburg
Trail of Bits hat eine Reihe von Open-Source-Bibliotheken entwickelt, die die Erstellung und Bereitstellung von eBPF-Anwendungen optimieren sollen. Diese Bibliotheken ermöglichen eine effiziente Prozess- und Netzwerkereignisüberwachung, Funktionsverfolgung, Kernel-Debug-Symbolanalyse und eBPF-Codegenerierung.
Bisher stellte die Bereitstellung portabler, abhängigkeitsfreier eBPF-Anwendungen aufgrund der unterschiedlichen Versionen des Linux-Kernels und der Notwendigkeit externer Tools für die C-zu-eBPF-Bytecode-Übersetzung erhebliche Herausforderungen dar. Wir haben diese Probleme mit unseren innovativen Bibliotheken angegangen, die die neuesten eBPF- und Linux-Kernel-Funktionen nutzen, um externe Abhängigkeiten zu reduzieren. Diese Tools eignen sich ideal für die Erstellung von Agenten auf der Maschine und ermöglichen die Cloud-native Überwachung. Sie werden aktiv gepflegt und sind mit einer Vielzahl von Linux-Distributionen und Kernel-Releases kompatibel. Einige sind sogar integraler Bestandteil der Funktionalität von Osquery, dem renommierten Endpoint-Visibility-Framework.
Die Bibliotheken in dieser Suite sind linuxevents, ebpfpub, btfparse und ebpf-common. Zusammen können sie verwendet werden, um eine optimierte Ereignisüberwachung mit einem hohen Maß an Genauigkeit und Effizienz zu entwickeln. Ihre Anwendungen reichen von Netzwerkereignisüberwachung, Funktionsverfolgung und Kernel-Debug-Symbolanalyse bis hin zur Unterstützung bei der Generierung und Verwendung von eBPF-Code.
Die Linuxevents-Bibliothek zeigt, wie eBPF Ereignisse überwachen kannohne dass genaue Kernel-Header oder andere externe Abhängigkeiten erforderlich sind . Kein Versand von Kernel-Headern, mehreren Kopien des vorkompilierten eBPF-Bytecodes oder Abhängigkeiten von BCC mehr! Die linuxevents-Bibliothek unterstützt die Generierung von Laufzeitcode, um benutzerdefinierte Sonden zur Laufzeit und nicht nur während des Builds zu erstellen. Es ist auch viel schneller als herkömmliches Hooking auf Systemaufrufbasis, eine wesentliche Funktion bei der Überwachung von Ereignissen aus mehreren Containern auf einer einzelnen Maschine. Wie macht Linuxevents das?
Erstens verwendet linuxevents die BTF-Debugging-Daten des Linux-Kernels (über unsere btfparse-Bibliothek), um Funktionsprototypen und Kernel-Datenstrukturen genau zu identifizieren. Dadurch kann sich linuxevents automatisch an Abweichungen im Datenstrukturlayout anpassen und beliebige nicht öffentliche Symbole auf eine Weise einbinden, die die Nachverfolgung erheblich vereinfacht.
Dieser Ansatz ist schneller als herkömmliches Hooking auf Systemaufrufbasis, nicht nur, weil weniger Dinge eingehängt werden müssen (sched_process_exec vs. execve, execveat usw.), sondern auch, weil dadurch teure Korrelationen vermieden werden können. Um beispielsweise nachzuverfolgen, welches Programm auf der Festplatte über execve ausgeführt wird, müsste man normalerweise einen an execve übergebenen Dateideskriptor mit einem offenen Aufruf und mehreren chdir-Aufrufen korrelieren, um den vollständigen Pfad eines Programms zu erhalten. Die Korrelation ist rechenintensiv, insbesondere auf einer Maschine mit mehreren aktiven Containern. Die Linuxevents-Bibliothek verwendet eine genaue Darstellung der Kernel-Datenstruktur, um nur eine Funktion einzubinden und einfach den Pfad aus der VFS-Schicht des Kernels zu extrahieren.
Eine Aufzeichnung der Linuxevents-Bibliothek, die als Teil des execsnoop-Beispiels verwendet wird, das mit der Bibliothek geliefert wird
Die Linuxevents-Bibliothek ist immer noch ein Proof of Concept; Es wird von Osquery als umschaltbares Experiment verwendet. Die Bibliothek verfügt auch über ein kanonisches Beispiel für die Verfolgung ausgeführter Prozesse mit Container-übergreifender Sichtbarkeit.
Die ebpfpub-Bibliothek ermöglicht die Überwachung von Systemaufrufen über mehrere Linux-Kernelversionen hinweg und setzt dabei auf minimale externe Laufzeitabhängigkeiten. In ebpfpub werden eBPF-Probes automatisch aus Funktionsprototypen generiert, die über eine einfache benutzerdefinierte Sprache definiert werden, die aus Tracepoint-Deskriptoren erstellt werden kann. Dieser Ansatz erforderte korrekte Header für den laufenden Kernel und brachte Leistungseinbußen mit sich, beispielsweise die Notwendigkeit, Dateideskriptoren mit Systemaufrufen abzugleichen.
Abhängig vom gewünschten Zielereignis kann ebpfpub entweder Kernel-Tracepoints, Kprobes oder Uprobes als zugrunde liegenden Tracing-Mechanismus verwenden. Die Bibliothek enthält die folgenden Beispiele:
Die ebpfpub-Bibliothek wird derzeit von osquery verwendet, um Prozess- und Socket-Ereignisse durch Nachverfolgung ausgeführter Systemaufrufe zu erfassen. Während ebpfpub immer noch gepflegt wird und unter bestimmten Umständen nützlich ist (z. B. die Notwendigkeit, ältere Kernel zu unterstützen und die Generierung von Laufzeitcode zu verwenden), sollten neue Projekte stattdessen den Linuxevents-Ansatz verwenden.
BTF (Binary Type Format) ist ein kompaktes Binärformat zur Darstellung von Typinformationen im Linux-Kernel. BTF speichert Daten wie Strukturen, Unions, Aufzählungen und Typdefinitionen. Debugger und andere Tools können BTF-Daten verwenden, um umfangreichere Debugging-Funktionen zu ermöglichen, indem sie komplexe C-Typen und -Ausdrücke verstehen. BTF wurde in Linux 4.20 eingeführt und wird aus Quellcode und herkömmlichen Debugging-Informationen wie DWARF generiert. BTF ist kompakter als DWARF und verbessert das Debugging-Erlebnis, indem es mehr semantische Typinformationen übermittelt als zuvor. Das standardisierte BTF-Format ermöglicht auch neuen Debugging-Tools die Nutzung von Typdaten über Compiler hinweg und ermöglicht so eine konsistentere Qualität der Introspektion über Sprachen hinweg.
Mit der btfparse-Bibliothek können Sie BTF-Daten in Ihren C++-Projekten lesen und Header-Dateien direkt im Speicher generieren, ohne dass eine externe Anwendung erforderlich ist. Die Bibliothek enthält außerdem ein Tool namens btf-dump, das sowohl als Beispiel für die Verwendung von btfparse als auch als eigenständiges Tool dient, das in einem Linux-Kernel-Image vorhandene BTF-Daten sichern kann.
Die ebpf-common-Bibliothek besteht aus einer Reihe von Dienstprogrammen, die beim Generieren, Laden und Verwenden von eBPF-Code helfen. Es ist das gemeinsame Substrat, das allen unseren eBPF-bezogenen Werkzeugen zugrunde liegt. Verwenden Sie epbf-common, um Ihre eigenen eBPF-basierten Laufzeittools zu erstellen!
Die Hauptaufgabe der ebpf-common-Bibliothek besteht darin, C-Code in eBPF-Bytecode zu kompilieren und hilfreiche Abstraktionen bereitzustellen, die das Schreiben von eBPF-Hooks erleichtern. Hier sind einige der Funktionen, die ebpf-common bietet:
Die ebpf-common-Bibliothek wird als Kern aller unserer anderen eBPF-Tools verwendet, die als Bibliotheksclients und Beispiele für Anwendungsfälle für ebpf-common für Ihre Anwendungen dienen. Weitere Anleitungen und Beispiele für die Verwendung von ebpf-common finden Sie in unserem Blogbeitrag „Alle Ihre Ablaufverfolgungen gehören zu BPF“.
ebpfault ist ein systemweiter Fehlerinjektor, der keine riskanten Kernel-Treiber erfordert, die das System zum Absturz bringen könnten. Es kann ein bestimmtes Programm starten, auf laufende Prozesse abzielen oder auf alle Prozesse außer denen in einer bestimmten Liste abzielen. Mit einer einfachen Konfigurationsdatei im JSON-Format können Sie Fehler konfigurieren, indem Sie den Systemaufrufnamen, die Wahrscheinlichkeit der Fehlerinjektion und den Fehlercode verwenden, der zurückgegeben werden soll.
Eine Aufzeichnung von ebpfault, das gegen den htop-Prozess ausgeführt wird und über eine bestimmte Konfiguration Fehler verursacht
Der Großteil des online verfügbaren Materials ist auf die Verwendung der Befehlszeilen-Beispieltools zur Demonstration von eBPF ausgerichtet, die meist als eigenständige Demonstrationen und nicht als wiederverwendbare Bibliotheken funktionieren. Wir wollten die Lücken für Entwickler schließen und eine Schritt-für-Schritt-Anleitung zur tatsächlichen Integration von eBPF von Grund auf aus der Sicht eines Entwicklers bereitstellen, der ein Tracing-Tool schreibt. Die Dokumentation konzentriert sich auf die Laufzeitcodegenerierung mithilfe der LLVM-Bibliotheken.
DerAlle Ihre Nachverfolgungen gehören BPFDer Blogbeitrag und unser Begleitcode-Leitfaden zeigen, wie Sie mit epbf-common ein Tool erstellen, das eBPF zum Zählen von Systemaufrufen verwendet, wobei jedes Beispiel an Komplexität zunimmt, angefangen beim einfachen Zählen über die Verwendung von Karten zum Speichern von Daten bis hin zur Verwendung von Perf-Ereignissen für Ausgänge.
Überwachung von Linux-Ereignissen ist ein Vortrag von Alessandro Gario über die Verwendung von eBPF zur Ereignisüberwachung. Alessandro beschreibt, wie Sie dynamisch entscheiden, was überwacht werden soll, und wie Sie Ihren eigenen eBPF-Bytecode direkt aus C++ generieren. Er geht auf einige Feinheiten von eBPF-Karten, Leistungsereignissen und praktische Überlegungen zur Verwendung unserer eBPF-Tools und -Bibliotheken ein.
Die Welt von eBPF wächst weiter und findet Anwendungen in verschiedenen Bereichen. Wir haben eBPF im Hinblick auf interessante Aufgaben untersucht, die über Tracing und Leistungsüberwachung hinausgehen, wie z. B. die Verbesserung von CI/CD für eBPF-Bytecode, das Schreiben eines eBPF-zu-ARM64-JIT-Compilers für die Solana-Plattform und die Verbesserung der Erfahrung beim Erstellen von eBPF-Projekten unter Windows .
ebpf-Verifizierer : Manchmal ist es notwendig, vorgefertigte eBPF-Programme zu bündeln. Der Linux-Kernel „verifiziert“ eBPF-Programme beim Laden und lehnt alle ab, die er für unsicher hält. Das Bündeln von eBPF-Bytecode ist ein CI/CD-Albtraum, da die Überprüfung jedes Kernels ein wenig anders ist. ebpf-verifier zielt darauf ab, diesen Albtraum zu beseitigen, indem es den eBPF-Verifizierer außerhalb des laufenden Kernels ausführt und die Möglichkeit eröffnet, eBPF-Programme über verschiedene Kernel-Versionen hinweg zu testen.
Solana eBPF-zu-ARM64-JIT-Compiler : eBPF taucht an vielen überraschenden Orten auf! Die Solana-Blockchain verwendet eine virtuelle eBPF-Maschine, um ihre Smart Contracts auszuführen, und verwendet einen JIT-Compiler, um den eBPF-Bytecode in native Architekturen zu kompilieren. Trail of Bits hat den Solana eBPF JIT-Compiler auf ARM64 portiert, um Solana-Anwendungen die native Ausführung auf den mittlerweile sehr beliebten ARM64-Plattformen wie Apple Silicon zu ermöglichen.
CMake-Unterstützung zu eBPF für Windows hinzufügen : eBPF funktioniert auch unter Windows! Um die Windows-Entwicklung zu vereinfachen, haben wir das frühere Visual Studio-basierte Build-System auf CMake portiert. Zu den Verbesserungen gehören eine bessere Handhabung transitiver Abhängigkeiten und Eigenschaften, eine bessere Verpackung und verbesserte Build-Einstellungen für eine effizientere Entwicklungserfahrung.
Wir haben eBPF verwendet, um schnelle und qualitativ hochwertige Überwachungsdaten für Systeminstrumentierungsagenten wie Osquery bereitzustellen. Unsere Absicht ist es, dass die von uns erstellten Frameworks und Tools Entwicklern dabei helfen, eBPF nahtloser in ihre Anwendungen zu integrieren. eBPF ist eine nützliche Technologie mit einer großen Zukunft in einer Vielzahl von Bereichen, darunter zunehmend auch in der Cloud-nativen Überwachung und Beobachtung.
Wir planen, in naher Zukunft weitere Erkenntnisse aus der Entwicklung von eBPF-Tools weiterzugeben und hoffen, einige dieser Erkenntnisse auf die Probleme der Cloud-nativen Überwachung und Beobachtbarkeit anwenden zu können.
*** Dies ist ein vom Security Bloggers Network syndizierter Blog von Trail of Bits Blog, verfasst von Trail of Bits. Lesen Sie den Originalbeitrag unter: https://blog.trailofbits.com/2023/08/09/use-our-suite-of-ebpf-libraries/
Von Artem Dinaburgohne dass genaue Kernel-Header oder andere externe Abhängigkeiten erforderlich sindAlle Ihre Nachverfolgungen gehören BPFÜberwachung von Linux-Ereignissenebpf-VerifiziererSolana eBPF-zu-ARM64-JIT-CompilerCMake-Unterstützung zu eBPF für Windows hinzufügen