Vorstellung des Verifizierten Allocators: Eine sichere Lösung zur Speicherverwaltung
Ein neuer Speicher-Allocator bietet verbesserte Sicherheit und Leistung für die Softwareentwicklung.
― 9 min Lesedauer
Inhaltsverzeichnis
- Hintergrund
- Herausforderungen im Speichermanagement
- Vorschlag für einen neuen Speicherzuweiser
- Systemarchitektur
- Speicherregionen
- Grössenklassen und Arenen
- Slabs und Slots
- Sicherheitsmerkmale
- Nullsetzen des Speichers
- Schutzseiten
- Quarantäne für freigegebenen Speicher
- Getrennte Metadaten
- Verifikationsprozess
- Trennungslogik
- Entwicklung von Beweisen
- Leistungsbewertung
- Experimentelle Einrichtung
- Ergebnisse und Vergleich
- Praktische Integration
- Herausforderungen bei der Integration
- Leistungsauswirkungen in Firefox
- Zukunftsarbeit
- Optimierung und Feinabstimmung
- Erweiterung der Sicherheitsmerkmale
- Gemeinschaftsbeitrag
- Fazit
- Originalquelle
- Referenz Links
Speicherzuweisungen sind super wichtige Teile von Softwaresystemen. Sie helfen, den Speicher zu verwalten, damit Programme Speicher anfordern können, wenn sie ihn brauchen, und ihn freigeben, wenn sie fertig sind. Viele moderne Programmiersprachen bieten automatisches Speichermanagement, wie zum Beispiel Garbage Collection. Allerdings verlassen sich viele Systeme immer noch auf Low-Level-Sprachen wie C und C++, die manuelles Speichermanagement ermöglichen. Das bringt Herausforderungen mit sich, besonders in Bezug auf Sicherheit, da diese Sprachen anfällig für Fehler sind wegen ihrer Low-Level-Natur.
Die Herausforderung bei der Verwendung von C und C++ ist, dass sie keine eingebauten Sicherheitsfunktionen wie Speicher-Sicherheit bieten. Das bedeutet, Entwickler können leicht Fehler machen, die zu Speicherbeschädigungen führen, was Sicherheitsanfälligkeiten schaffen kann. Tatsächlich stammen viele Sicherheitsprobleme in Software aus diesen speicherbezogenen Fehlern. Studien zeigen, dass eine grosse Anzahl dieser Anfälligkeiten aus Problemen wie Pufferüberläufen oder Dangling Pointern entsteht.
Als Lösung arbeiten Entwickler daran, Speicherzuweisungen zu verbessern, um sie sicherer und geschützter zu machen. Dieses Papier präsentiert einen neuen Speicherzuweiser, der verifiziert, Gleichzeitig und mit Sicherheit im Hinterkopf gestaltet ist. Dieser neue Zuweiser zielt nicht nur darauf ab, hohe Leistung zu bieten, sondern auch gegen die gängigen Anfälligkeiten zu schützen, die mit dem Speichermanagement in unsicheren Sprachen verbunden sind.
Hintergrund
Die Speicherzuweisung beinhaltet das Anfordern und Freigeben von Speicher während der Programmausführung. Dieser Prozess ist grundlegend in der Programmierung, besonders in Sprachen wie C und C++. Der C-Standard, der 1989 festgelegt wurde, definierte die grundlegenden Speicherzuweisungsfunktionen wie malloc
, calloc
, realloc
und free
. Diese Funktionen werden verwendet, um Speicher dynamisch zuzuweisen, neu zuzuweisen und freizugeben.
Mit dem Wachstum und der Evolution von Systemen ist der Bedarf an sichereren und effizienteren Speicherzuweisungen offensichtlich geworden. Zuweiser müssen jetzt verschiedene Techniken integrieren, um die Sicherheit zu erhöhen, einschliesslich der Randomisierung von Speicherzuweisungsmustern und der Trennung von Metadaten von den tatsächlichen Daten. Diese Methoden helfen, sich gegen Angriffe zu verteidigen, die gängige Speicheranfälligkeiten ausnutzen.
Die Herausforderung beim Erstellen eines robusten Speicherzuweisers besteht darin, verschiedene konkurrierende Anforderungen wie Leistung, Sicherheit und Einfachheit in Einklang zu bringen. Zuweiser müssen effizient im Umgang mit Speicher sein und gleichzeitig starke Schutzmassnahmen gegen Missbrauch bieten.
Herausforderungen im Speichermanagement
Das Speichermanagement in C und C++ bringt verschiedene Herausforderungen mit sich. Entwickler müssen manuell die Speicherzuweisung und -freigabe handhaben, was zu Speicherlecks, doppeltem Freigeben und anderen Fehlern führen kann. Solche Fehler können ernsthafte Anfälligkeiten in Softwaresystemen einführen.
Neben dem Risiko von Fehlern müssen Zuweiser auch mit der Realität umgehen, dass sie oft in Umgebungen verwendet werden, in denen Client-Anwendungen in unsicheren Sprachen geschrieben sein können. Das erhöht das Potenzial für Anfälligkeiten, da der Zuweiser selbst gegen die Arten von Bugs, die aus fehlerhaftem Client-Code entstehen können, widerstandsfähig sein muss.
Selbst weit verbreitete Zuweiser, wie der in der GNU C-Bibliothek (glibc), hatten im Laufe der Jahre mit erheblichen Sicherheitsproblemen zu kämpfen. Daher gibt es ein wachsendes Bedürfnis nach Zuweisern, die nicht nur Funktionalität bieten, sondern auch strengen Sicherheits- und Korrektheitsgarantien entsprechen.
Vorschlag für einen neuen Speicherzuweiser
Um diese Herausforderungen zu bewältigen, schlagen wir einen neuen Speicherzuweiser vor, der verifiziert, gleichzeitig und sicherheitsorientiert ist. Unser Design nutzt moderne Techniken und Frameworks, um einen Speicherzuweiser zu erstellen, der die Anforderungen zeitgemässer Anwendungen erfüllt.
Der neue Zuweiser, genannt Verified Allocator
, basiert auf Prinzipien der Trennungslogik. Dieser Ansatz ermöglicht es uns, das Verhalten des Zuweisers so zu spezifizieren, dass es formell verifiziert werden kann. Wir können sicherstellen, dass er Sicherheitsmerkmale aufrechterhält und korrekt unter gleichzeitigen Zugriffen funktioniert.
Wichtige Merkmale des Verified Allocator
sind:
Sicherheitsmassnahmen: Der Zuweiser implementiert verschiedene Sicherheitsstrategien, um sich gegen Heap-Anfälligkeiten zu verteidigen. Zu diesen Massnahmen gehört das Nullsetzen des Speichers nach der Freigabe und die Verwendung von Schutzseiten, um Zugriffe ausserhalb des gültigen Bereichs zu erkennen.
Unterstützung für Nebenläufigkeit: Für multithreaded Umgebungen konzipiert, erlaubt der Zuweiser sichere gleichzeitige Speicheroperationen. Das hilft, Konflikte zu vermeiden und verbessert die Leistung, wenn mehrere Threads auf den Speicher zugreifen.
Effiziente Speicherbenutzung: Das Design konzentriert sich darauf, den Speicherverbrauch und die Fragmentierung zu minimieren. Durch die Implementierung von Techniken wie Grössenklassen und Arenen kann der Zuweiser Speicher effizient verwalten.
Formale Verifikation: Mithilfe von Trennungslogik können wir die Korrektheit des Zuweisers formell verifizieren. Das bedeutet, dass wir durch rigorose Beweise garantieren können, dass der Zuweiser sich wie erwartet verhält und keine unsicheren Speicheroperationen zulässt.
Systemarchitektur
Die Architektur des Verified Allocator
ist darauf ausgelegt, sowohl Leistung als auch Sicherheit zu maximieren. Sie umfasst mehrere Ebenen, um die Speicherzuweisung effizient zu verwalten.
Speicherregionen
Der Verified Allocator
arbeitet mit unterschiedlichen Speicherregionen. Alle regulären Zuweisungen leben in einer Speicherregion, während alle Metadaten in einer separaten zusammenhängenden Region gespeichert werden. Diese Trennung erleichtert die Verwaltung und erhöht die Sicherheit, da die Metadaten nicht mit den zugewiesenen Daten vermischt werden.
Grössenklassen und Arenen
Um den Speicher effizient zu verwalten, teilt der Zuweiser den Speicher in Grössenklassen. Jede Grössenklasse entspricht einer bestimmten Zuweisungsgrösse, was die Fragmentierung reduziert und die Zuweisungsgeschwindigkeit verbessert. Der Zuweiser verwendet auch Arenen, die eine thread-lokale Speicherverwaltung ermöglichen. Jeder Thread ist mit einer Arena verbunden, um Konflikte zwischen gleichzeitigen Threads zu minimieren.
Slabs und Slots
Der Speicher innerhalb jeder Grössenklasse ist in Slabs organisiert. Ein Slab ist ein Block mit fester Grösse, und jedes Slab ist in kleinere Einheiten, sogenannte Slots, unterteilt. Diese Struktur ermöglicht es dem Zuweiser, Zuweisungen unterschiedlicher Grössen effizient zu verwalten.
Wenn eine Anfrage nach Speicher gestellt wird, sucht der Zuweiser nach einem verfügbaren Slot innerhalb des entsprechenden Slabs. Wenn keine Slots verfügbar sind, kann der Zuweiser ein neues Slab zuweisen.
Sicherheitsmerkmale
Sicherheit ist ein zentrales Anliegen beim Design des Verified Allocator
. Um sich gegen gängige speicherbezogene Anfälligkeiten zu schützen, implementiert der Zuweiser mehrere Sicherheitsmerkmale.
Nullsetzen des Speichers
Immer wenn Speicher freigegeben wird, setzt der Zuweiser den Speicherbereich auf Null. Das stellt sicher, dass sensible Daten später nicht von einem Angreifer abgerufen werden können, der versucht, die übrig gebliebenen Werte in freigegebenen Speicherslots auszunutzen.
Schutzseiten
Schutzseiten sind spezielle Speicherseiten, die als unzugänglich markiert sind. Wenn ein Programm versucht, auf diese Seiten zuzugreifen, wird ein Fehler ausgelöst. Diese Technik hilft, Pufferüberläufe zu erkennen und sicherzustellen, dass kein Überlauf gültige Speicherregionen beschädigt.
Quarantäne für freigegebenen Speicher
Freigegebener Speicher wird in einen Quarantänestatus versetzt, bevor er wiederverwendet wird. Diese Abkühlphase verhindert eine sofortige Wiederverwendung und hilft, Probleme im Zusammenhang mit doppeltem Freigeben oder dem Zugriff auf freigegebenen Speicher zu erkennen. Speicher wird nur nach einer vordefinierten Zeit wieder in Betrieb genommen, wodurch sichergestellt wird, dass eventuelle Probleme vor der Wiederverwendung erkannt werden.
Getrennte Metadaten
Der Zuweiser hält seine Metadaten in einer separaten Region von zugewiesenem Speicher. Dieses Design schützt die internen Strukturen des Zuweisers davor, von Client-Programmen manipuliert zu werden, was die Sicherheit weiter erhöht.
Verifikationsprozess
Die Verifikation des Verified Allocator
ist ein kritischer Schritt in seiner Entwicklung. Mithilfe von Trennungslogik können wir das Verhalten des Zuweisers formell spezifizieren und verifizieren.
Trennungslogik
Trennungslogik ermöglicht es uns, über Speicher auf modulare Weise nachzudenken. Durch die Verwendung logischer Prädikate können wir ausdrücken, auf welche Speicherregionen eine Funktion zugreifen und die sie modifizieren kann. Diese Methode ermöglicht den Nachweis der Korrektheit für einzelne Operationen, ohne das gesamte System auf einmal verifizieren zu müssen.
Entwicklung von Beweisen
Der Verifikationsprozess umfasst die Entwicklung formaler Beweise für jede Funktion im Zuweiser. Dazu gehört der Nachweis, dass die Speicherverwaltungsfunktionen korrekt in Bezug auf die spezifizierten Eigenschaften arbeiten. Der modulare Ansatz ermöglicht es uns, Beweise schrittweise zu erstellen und uns jeweils auf einen Teil des Zuweisers zu konzentrieren.
Leistungsbewertung
Um die Leistung des Verified Allocator
zu bewerten, führen wir Benchmarks durch, bei denen er mit beliebten Speicherzuweisern verglichen wird. Diese Benchmarks messen die Ausführungszeit und den Speicherverbrauch über verschiedene Arbeitslasten hinweg.
Experimentelle Einrichtung
Die Tests werden auf einer Multicore-Maschine durchgeführt, um reale Bedingungen zu simulieren. Die Benchmarks umfassen eine Vielzahl von Anwendungen und Nutzungsmustern, um die Leistung des Zuweisers umfassend zu bewerten.
Ergebnisse und Vergleich
In den Benchmark-Ergebnissen zeigt der Verified Allocator
eine wettbewerbsfähige Leistung im Vergleich zu traditionellen Zuweisern. Obwohl es aufgrund von Sicherheitsmerkmalen einen leichten Overhead geben kann, schneidet der Zuweiser in den meisten getesteten Arbeitslasten ausreichend ab. In bestimmten Szenarien ist seine Leistung auf dem gleichen Niveau oder übertrifft sogar die anderer hochmodernen Speicherzuweiser.
Praktische Integration
Die Integration des Verified Allocator
in bestehende Anwendungen ist ein wichtiger Aspekt seiner Entwicklung. Um seine reale Anwendbarkeit zu testen, haben wir ihn mit einem beliebten Webbrowser, Mozilla Firefox, integriert.
Herausforderungen bei der Integration
Die Integration eines neuen Speicherzuweisers erfordert die Gewährleistung der Kompatibilität mit dem bestehenden Code. Der Verified Allocator
muss alle notwendigen Speicherverwaltungsfunktionen und Erweiterungen unterstützen, die von der Anwendung verwendet werden.
Leistungsauswirkungen in Firefox
Nach der Integration zeigen Leistungstests, dass der Verified Allocator
im Vergleich zum bestehenden Zuweiser einen handhabbaren Overhead einführt. Das deutet darauf hin, dass er in Produktionsumgebungen ohne signifikante Leistungseinbussen verwendet werden kann.
Zukunftsarbeit
Die Entwicklung des Verified Allocator
ist ein fortlaufender Prozess. Zukünftige Arbeiten konzentrieren sich darauf, die Leistung weiter zu optimieren, die Sicherheitsmerkmale auszubauen und eine breite Akzeptanz in realen Anwendungen zu gewährleisten.
Optimierung und Feinabstimmung
Während die Leistungsbenchmarks fortgesetzt werden, werden wir nach Möglichkeiten suchen, bestimmte Aspekte des Zuweisers zu optimieren. Dazu gehört die Feinabstimmung der Zuweisungsstrategien und die Erkundung neuer Techniken zur Reduzierung von Overhead.
Erweiterung der Sicherheitsmerkmale
Es gibt stets die Notwendigkeit, sich an neue Sicherheitsherausforderungen anzupassen. Zukünftige Versionen des Verified Allocator
werden darauf abzielen, zusätzliche Sicherheitsmassnahmen zu integrieren, während neue Anfälligkeiten entdeckt werden.
Gemeinschaftsbeitrag
Um die Zusammenarbeit und Akzeptanz zu fördern, planen wir, den Verified Allocator
als Open-Source-Projekt verfügbar zu machen. Dies wird es anderen Entwicklern ermöglichen, Verbesserungen beizutragen und seine Fähigkeiten zu erweitern.
Fazit
Das Speichermanagement bleibt ein herausfordernder Aspekt der Softwareentwicklung, insbesondere in Low-Level-Programmiersprachen wie C und C++. Der vorgeschlagene Verified Allocator
bietet eine Lösung, die Leistung mit starken Sicherheitsgarantien in Einklang bringt.
Durch formale Verifikation und die Verwendung moderner Techniken adressiert der Verified Allocator
gängige Anfälligkeiten, die mit manuellem Speichermanagement verbunden sind. Sein Design macht ihn für die Verwendung in einer Vielzahl von Anwendungen geeignet, von Systemsoftware bis hin zu Webbrowsern.
Während sich die Softwarelandschaft weiterhin entwickelt, wird der Bedarf an robusten und sicheren Speicherzuweisern nur wachsen. Der Verified Allocator
stellt einen Fortschritt dar, um diesen Anforderungen gerecht zu werden und den Weg für eine sicherere und effizientere Speicherverwaltung in der Zukunft zu ebnen.
Titel: StarMalloc: A Formally Verified, Concurrent, Performant, and Security-Oriented Memory Allocator
Zusammenfassung: In this work, we present StarMalloc, a verified, security-oriented, concurrent memory allocator that can be used as a drop-in replacement in real-world projects. Using the Steel separation logic framework, we show how to specify and verify StarMalloc, relying on dependent types and modular abstractions to enable efficient verification. As part of StarMalloc, we also develop several generic datastructures and proof libraries directly reusable in future systems verification projects. We finally show that StarMalloc can be used with real-world projects, including the Firefox browser, and evaluate it against 10 state-of-the-art memory allocators, demonstrating its competitiveness.
Autoren: Antonin Reitz, Aymeric Fromherz, Jonathan Protzenko
Letzte Aktualisierung: 2024-03-14 00:00:00
Sprache: English
Quell-URL: https://arxiv.org/abs/2403.09435
Quell-PDF: https://arxiv.org/pdf/2403.09435
Lizenz: https://creativecommons.org/licenses/by-nc-sa/4.0/
Änderungen: Diese Zusammenfassung wurde mit Unterstützung von AI erstellt und kann Ungenauigkeiten enthalten. Genaue Informationen entnehmen Sie bitte den hier verlinkten Originaldokumenten.
Vielen Dank an arxiv für die Nutzung seiner Open-Access-Interoperabilität.