David Chisnall zufolge liegt die größte Herausforderung bei der Softwareisolierung nicht darin, zwei Workloads vollständig voneinander zu trennen, sondern Komponenten zu isolieren, die miteinander kommunizieren und Daten gemeinsam nutzen müssen. In einer über InfoQ veröffentlichten Präsentation erläutert Chisnall, wie die CHERI-Architektur Sicherheitskonzepte für Fähigkeiten und erweiterte Zeiger kombiniert, um hardwaregestützten Zeigerschutz sowie Speichersicherheit und eine präzise Isolation innerhalb desselben Adressraums bereitzustellen.
Chisnall ist Mitbegründer und Director of Systems Engineering bei SCI Semiconductor und außerdem Gastforscher an der University of Cambridge. Die Präsentation stützt sich auf die Forschungsarbeiten zu CHERI sowie deren Software- und Hardwareimplementierungen – von CheriBSD und den ARM-Morello-Erweiterungen bis hin zu CHERIoT für Mikrocontroller. Hinzu kommt die RISC-V-Basis namens RVY, deren Standardisierung sich seinen Angaben zufolge in der Endphase befand.
Der Zeiger wird zu einer hardwaregeschützten Entität
CHERI stellt keine eigenständige Befehlssatzarchitektur im herkömmlichen Sinn dar, sondern eine Sammlung von Konzepten, die an unterschiedliche Architekturen angepasst werden können – ähnlich der Umsetzung von SIMD-Konzepten in mehreren Erweiterungen. Nach diesem Modell ist ein Zeiger nicht länger lediglich eine Zahl, die eine Speicheradresse repräsentiert, sondern wird zu einer Fähigkeit, die die Adresse, die Grenzen des Objekts und eine Reihe von Berechtigungen enthält sowie ein Hardware-Tag, das angibt, ob der Wert ein gültiger Zeiger ist.
Diese Fähigkeiten erzwingen Einwegeigenschaften: Grenzen können eingeschränkt und Berechtigungen entzogen, jedoch nicht über denselben Zeiger erweitert oder wiederhergestellt werden. Außerdem überprüft die Hardware, ob der Zeiger gültig und getaggt ist, bevor er für Lade-, Speicher- oder Sprungoperationen verwendet wird. Versucht ein Programm, einen als Daten behandelten oder manipulierten Wert zur Erzeugung einer Adresse zu verwenden, schlägt die Operation fehl, anstatt den Wert automatisch in einen nutzbaren Zeiger umzuwandeln.
Dieses Design bietet der Präsentation zufolge unmittelbaren Schutz vor mehreren üblichen Phasen von Speicher-Exploits, etwa dem Überschreiben eines Zeigers mit einem vom Angreifer kontrollierten Wert. Es ermöglicht außerdem allgemeine Kopiervorgänge wie memcpy, ohne dass die Positionen der Zeiger im Voraus bekannt sein müssen, da das Zeiger-Tag zusammen mit dem Wert übertragen oder gelöscht wird, wenn ein Teil des Fähigkeitsbereichs überschrieben wird.
Einschränkbare Grenzen und Berechtigungen
CHERI-Fähigkeiten umfassen Lese- und Schreibberechtigungen sowie separate Berechtigungen für den Umgang mit in Daten enthaltenen Zeigern. Chisnall erklärt, dass diese Präzision beispielsweise ermöglicht, einem Programm Leseberechtigung für die Daten innerhalb einer komplexen Struktur zu erteilen, ohne ihm die Möglichkeit zu geben, darin neue Zeiger zu speichern. Auf diese Weise kann eine schreibgeschützte Sicht bereitgestellt werden, die sich über einen vollständigen Datenbaum erstreckt, anstatt nur ein einzelnes Objekt oberflächlich zu schützen.
Der Mechanismus des Sealing ermöglicht außerdem die Erstellung sicherer, opaker Zeiger, die Griffen oder Dateideskriptoren ähneln, jedoch nicht zwingend eine vom Kernel verwaltete Übersetzungstabelle benötigen. Die Fähigkeit wird mit einem Typcode versiegelt und kann während der Versiegelung weder verändert noch dereferenziert oder für Sprung-, Lade- und Speicheroperationen verwendet werden. Bei der Rückgabe an die besitzende Instanz gelingt das Entsiegeln nur, wenn der Typcode übereinstimmt.
Räumliche und zeitliche Speichersicherheit
Bei Fehlern durch Überschreitung von Grenzen kann CHERI undefiniertes Verhalten in der Sprache C in einen deterministischen Hardwareabbruch umwandeln. Chisnall zeigt das Beispiel eines Arrays mit 14 Elementen, bei dem auf Element 14 zugegriffen wird. Auf einem herkömmlichen System kann dieser Zugriff die Rücksprungadresse überschreiben, während er auf einem CHERI-System einen Trap auslöst, weil der Zeiger auf die Grenzen des Arrays beschränkt ist.
Der Ansatz beschränkt sich nicht auf räumliche Sicherheit. In CHERIoT werden Zeiger-Tags und ein Schatten-Speicher mit einem Bit pro Allokationseinheit verwendet, sodass Zeiger auf bereits freigegebenen Speicher ungültig gemacht werden können. Beim Laden einer Fähigkeit in ein Register kann ein Load-Filter den Zustand des Blocks überprüfen und das Tag löschen, wenn der Speicher freigegeben wurde. Außerdem prüft ein regelmäßiger Hardwaremechanismus den Speicher und entfernt die Tags von Zeigern, die auf nicht mehr lebende Objekte verweisen. Dadurch kann der Speicher nach Abschluss des Invalidierungszyklus wiederverwendet werden.
Von der Speichersicherheit zur präzisen Isolation
Das ursprüngliche Ziel des CHERI-Projekts bestand Chisnall zufolge darin, eine präzise Isolation zu schaffen, die über die Grenzen der herkömmlichen Prozessisolierung hinausgeht. Die Isolation jeder Komponente in einem eigenen Prozess verursacht Kosten durch Seitentabellen, RPC-Mechanismen sowie die Serialisierung und das Kopieren von Daten. Für Dutzende isolierter Domänen mag dies akzeptabel sein, doch wenn Browser beispielsweise Tausende oder Zehntausende von Sandboxes für Komponenten wie Bild- und Audio-Dekodierung oder die Ausführung von JavaScript-JITs benötigen, ist dieser Ansatz weniger geeignet.
Das CHERI-Modell ermöglicht es, die von den in den Ausführungsregistern vorhandenen Fähigkeiten aus erreichbare Speichermenge als Schutzbereich zu betrachten. Zwei Bereiche innerhalb desselben Adressraums können bestimmte Daten gemeinsam nutzen, während andere Teile isoliert bleiben, da die gemeinsame Nutzung von bestimmten Fähigkeiten ausgeht und sich auf komplexe Datenstrukturen sowie alles von ihnen Erreichbare erstrecken kann.
Auf größeren Systemen erläutert die Präsentation einen schrittweisen Ansatz über den Aufruf coexecve. Dieser erstellt einen neuen Prozess, ohne einen neuen Adressraum anzulegen, und setzt anschließend eine Gruppe von Root-Fähigkeiten fest, die bestimmen, worauf der neue Prozess zugreifen darf. CHERIoT verfolgt dagegen eine strikte Trennung der Berechtigungen innerhalb eines Echtzeitbetriebssystems. Dabei übernimmt eine Umschaltkomponente den Kontextwechsel und die Aufrufe zwischen Compartments und umfasst der Präsentation zufolge etwa 350 Instruktionen.
Chisnalls Schlussfolgerung lautet, dass Speicherschutz und Isolation nicht von einer vollständigen Neuschreibung des Codes oder davon abhängen sollten, jede Komponente in einem eigenen Prozess zu isolieren. Ein weitgehend vertrautes C-Modell, bei dem Zeiger und Zugriffsrechte hardwareseitig verständlich und kontrolliert werden, könnte einen schrittweisen Weg bieten, um Speicherfehler zu reduzieren und eine besser überprüfbare gemeinsame Nutzung zu schaffen. Die Implementierungsdetails unterscheiden sich weiterhin zwischen großen Systemen und Mikrocontrollern. Zudem spiegelt die Präsentation die Sichtweise und unmittelbare Erfahrung ihres Referenten mit CHERI wider und stellt keinen allgemeinen Standard dar, der automatisch die Beseitigung sämtlicher Sicherheitsprobleme garantiert.