Um gegen Kernel oder prozessübergreifende Speicher Offenlegung (der zu mildern Specter Angriff), Kernel der Linux - 1 wird mit einer neuen Option kompiliert werden , -mindirect-branch=thunk-extern
eingeführt , um gcc
indirekte Gespräche über eine sogenannte auszuführen retpoline .
Dies scheint ein neu erfundener Begriff zu sein, da eine Google-Suche erst in jüngster Zeit verwendet wird (im Allgemeinen alle im Jahr 2018).
Was ist eine Retpoline und wie verhindert sie die jüngsten Angriffe auf die Offenlegung von Kernelinformationen?
1 Es ist jedoch nicht Linux-spezifisch - ein ähnliches oder identisches Konstrukt scheint als Teil der Minderungsstrategien auf anderen Betriebssystemen verwendet zu werden.
security
assembly
x86
cpu-architecture
BeeOnRope
quelle
quelle
gcc
weist! Ich habe lkml.org/lkml/2018/1/3/780 nicht wie auf der Linux Kernel Mailing List-Site erkannt, auch nicht, als ich dort nachgesehen habe (und mir wurde ein Schnappschuss zugestellt, da er offline war).Antworten:
Der von sgbj in den Kommentaren von Paul Turner von Google erwähnte Artikel erklärt Folgendes viel ausführlicher, aber ich werde es versuchen:
Soweit ich dies aus den derzeit begrenzten Informationen zusammensetzen kann, ist eine Retpoline ein Rücklauftrampolin , das eine Endlosschleife verwendet, die niemals ausgeführt wird, um zu verhindern, dass die CPU über das Ziel eines indirekten Sprungs spekuliert.
Der grundlegende Ansatz ist in Andi Kleens Kernel-Zweig zu sehen, der sich mit diesem Problem befasst:
Es führt den neuen
__x86.indirect_thunk
Aufruf ein, der das Aufrufziel lädt, dessen Speicheradresse (die ich aufrufen werdeADDR
) oben auf dem Stapel gespeichert ist, und führt den Sprung mithilfe derRET
Anweisung aus. Der Thunk selbst wird dann mit dem Makro NOSPEC_JMP / CALL aufgerufen, mit dem viele (wenn nicht alle) indirekte Aufrufe und Sprünge ersetzt wurden. Das Makro platziert einfach das Aufrufziel auf dem Stapel und stellt die Rücksprungadresse bei Bedarf korrekt ein (beachten Sie den nichtlinearen Kontrollfluss):Die Platzierung von
call
am Ende ist erforderlich, damit der Kontrollfluss nach Beendigung des indirekten Aufrufs hinter der Verwendung desNOSPEC_CALL
Makros fortgesetzt wird , sodass er anstelle eines regulären Makros verwendet werden kanncall
Der Thunk selbst sieht wie folgt aus:
Der Kontrollfluss kann hier etwas verwirrend sein, lassen Sie mich Folgendes klarstellen:
call
schiebt den aktuellen Anweisungszeiger (Beschriftung 2) auf den Stapel.lea
Fügt dem Stapelzeiger 8 hinzu und verwirft effektiv das zuletzt gepusste Quadword, das die letzte Rücksprungadresse ist (zu Bezeichnung 2). Danach zeigt die Oberseite des Stapels wieder auf die reale Rücksprungadresse ADDR.ret
springt zum*ADDR
Stapelzeiger und setzt ihn auf den Anfang des Aufrufstapels zurück.Am Ende ist dieses ganze Verhalten praktisch gleichbedeutend mit direktem Springen
*ADDR
. Der einzige Vorteil, den wir erhalten, besteht darin, dass der für return-Anweisungen verwendete Verzweigungsprädiktor (Return Stack Buffer, RSB) bei der Ausführung descall
Befehls davon ausgeht, dass die entsprechenderet
Anweisung zum Label 2 springt.Der Teil nach dem Label 2 wird tatsächlich nie ausgeführt, es ist einfach eine Endlosschleife, die theoretisch die Anweisungspipeline mit
JMP
Anweisungen füllen würde . Durch die Verwendung vonLFENCE
,PAUSE
oder allgemeiner eine Anweisung verursacht die Befehlspipeline Strömungsabriß sein stoppt die CPU verschwendet keine Energie und Zeit auf dieser spekulativen Ausführung. Dies liegt daran, dass für den Fall, dass der Aufruf von retpoline_call_target normal zurückkehrenLFENCE
würde, dies die nächste auszuführende Anweisung wäre. Dies ist auch das, was der Verzweigungsprädiktor basierend auf der ursprünglichen Rücksprungadresse (dem Etikett 2) vorhersagt.Um aus Intels Architekturhandbuch zu zitieren:
Beachten Sie jedoch, dass in der Spezifikation niemals erwähnt wird, dass LFENCE und PAUSE die Pipeline zum Stillstand bringen. Daher lese ich hier ein wenig zwischen den Zeilen.
Zurück zu Ihrer ursprünglichen Frage: Die Offenlegung von Kernelspeicherinformationen ist aufgrund der Kombination zweier Ideen möglich:
Obwohl die spekulative Ausführung nebenwirkungsfrei sein sollte, wenn die Spekulation falsch war, wirkt sich die spekulative Ausführung immer noch auf die Cache-Hierarchie aus . Dies bedeutet, dass bei einer spekulativen Ausführung eines Speicherladevorgangs möglicherweise immer noch eine Cache-Zeile entfernt wurde. Diese Änderung in der Cache-Hierarchie kann identifiziert werden, indem die Zugriffszeit auf den Speicher, der demselben Cache-Satz zugeordnet ist, sorgfältig gemessen wird.
Sie können sogar einige Bits beliebigen Speichers verlieren, wenn die Quelladresse des gelesenen Speichers selbst aus dem Kernelspeicher gelesen wurde.
Der indirekte Verzweigungsprädiktor von Intel-CPUs verwendet nur die untersten 12 Bits des Quellbefehls, so dass es einfach ist, alle 2 ^ 12 möglichen Vorhersageverläufe mit benutzergesteuerten Speicheradressen zu vergiften. Diese können dann, wenn der indirekte Sprung innerhalb des Kernels vorhergesagt wird, spekulativ mit Kernel-Berechtigungen ausgeführt werden. Mit dem Cache-Timing-Seitenkanal können Sie somit beliebigen Kernelspeicher verlieren.
UPDATE: Auf der Kernel-Mailingliste gibt es eine laufende Diskussion, die mich zu der Annahme führt, dass Retpolinen die Probleme mit der Verzweigungsvorhersage nicht vollständig mindern, da neuere Intel-Architekturen (Skylake +) zurückfallen, wenn der Return Stack Buffer (RSB) leer ist an den anfälligen Branch Target Buffer (BTB):
quelle
push
/ret
dass es nicht Unwucht der Rückkehr-Adresse Prädiktor - Stack. Es gibt eine falsche Vorhersage (gehen Sie zu,lfence
bevor die tatsächliche Absenderadresse verwendet wird), aber die Verwendung einercall
+ -Modifikationrsp
gleicht dies ausret
.push
/ret
(in meinem letzten Kommentar). re: your edit: RSB-Unterlauf sollte unmöglich sein, da die Retpoline a enthältcall
. Wenn die Kernel-Prävention dort einen Kontextwechsel durchführen würde, würden wir die Ausführung mit dem RSB fortsetzen, der vomcall
in den Scheduler vorbereitet wurde . Aber vielleicht könnte ein Interrupt-Handler mit genugret
s enden, um den RSB zu leeren.Eine Retpoline soll vor dem Exploit der Verzweigungszielinjektion ( CVE-2017-5715 ) schützen . Dies ist ein Angriff, bei dem ein indirekter Verzweigungsbefehl im Kernel verwendet wird, um die spekulative Ausführung eines beliebigen Codeabschnitts zu erzwingen. Der ausgewählte Code ist ein "Gadget", das für Angreifer irgendwie nützlich ist. Zum Beispiel kann Code so gewählt werden, dass Kerneldaten durch die Auswirkungen auf den Cache verloren gehen. Die Retpoline verhindert diesen Exploit, indem sie einfach alle indirekten Verzweigungsbefehle durch einen Rückgabeanweis ersetzt.
Ich denke, der Schlüssel zur Retpoline ist nur der "ret" -Teil, der die indirekte Verzweigung durch eine Rückgabeanweisung ersetzt, sodass die CPU den Rückgabestapel-Prädiktor anstelle des ausnutzbaren Verzweigungsprädiktors verwendet. Wenn stattdessen ein einfacher Push- und ein Return-Befehl verwendet würden, wäre der Code, der spekulativ ausgeführt würde, der Code, zu dem die Funktion schließlich zurückkehren würde, und kein für den Angreifer nützliches Gadget. Der Hauptvorteil des Trampolinteils scheint darin zu bestehen, den Rückgabestapel beizubehalten. Wenn die Funktion tatsächlich zu ihrem Aufrufer zurückkehrt, wird dies korrekt vorhergesagt.
Die Grundidee hinter der Verzweigungszielinjektion ist einfach. Es nutzt die Tatsache aus, dass die CPU nicht die vollständige Adresse der Quelle und des Ziels von Zweigen in ihren Zweigzielpuffern aufzeichnet. So kann der Angreifer den Puffer mit Sprüngen in seinem eigenen Adressraum füllen, die zu Vorhersage-Treffern führen, wenn ein bestimmter indirekter Sprung im Kernel-Adressraum ausgeführt wird.
Beachten Sie, dass retpoline die direkte Offenlegung von Kernelinformationen nicht verhindert, sondern nur verhindert, dass indirekte Verzweigungsbefehle verwendet werden, um ein Gadget spekulativ auszuführen, das Informationen offenlegt. Wenn der Angreifer andere Mittel findet, um das Gadget spekulativ auszuführen, verhindert die Retpoline den Angriff nicht.
Das Papier Spectre Attacks: Ausnutzung der spekulativen Ausführung durch Paul Kocher, Daniel Genkin, Daniel Gruss, Werner Haas, Mike Hamburg, Moritz Lipp, Stefan Mangard, Thomas Prescher, Michael Schwarz und Yuval Yarom geben folgenden Überblick darüber, wie indirekte Zweige genutzt werden können ::
Ein Blogeintrag mit dem Titel Lesen von privilegiertem Speicher mit einem Seitenkanal durch das Project Zero-Team bei Google bietet ein weiteres Beispiel dafür, wie die Injektion von Zweigzielen verwendet werden kann, um einen funktionierenden Exploit zu erstellen.
quelle
Diese Frage wurde vor einiger Zeit gestellt und verdient eine neuere Antwort.
Zusammenfassung :
"Retpoline" -Sequenzen sind ein Softwarekonstrukt, mit dem indirekte Verzweigungen von der spekulativen Ausführung isoliert werden können. Dies kann angewendet werden, um sensible Binärdateien (z. B. Betriebssystem- oder Hypervisor-Implementierungen) vor Angriffen auf die Injektion von Zweigzielen gegen ihre indirekten Zweige zu schützen.
Das Wort " Ret Poline " ist ein Portmanteau der Wörter "Return" und "Trampolin", ähnlich wie die Verbesserung " Rel Poline " aus "Relative Call" und "Trampolin" geprägt wurde. Es handelt sich um ein Trampolin-Konstrukt, das unter Verwendung von Rückgabeoperationen konstruiert wurde und auch im übertragenen Sinne sicherstellt, dass jede damit verbundene spekulative Ausführung endlos "abprallt".
Die Verwendung dieser Compileroption schützt nur in betroffenen Prozessoren vor Spectre V2 , für die das für CVE-2017-5715 erforderliche Mikrocode-Update erforderlich ist. Es funktioniert mit jedem Code (nicht nur mit einem Kernel), aber nur Code mit "Geheimnissen" ist einen Angriff wert.
Der LLVM-Compiler hat
-mretpoline
seit dem 4. Januar 2018 einen Wechsel . An diesem Datum wurde die Sicherheitsanfälligkeit erstmals öffentlich gemeldet . GCC stellte ihre Patches am 7. Januar 2018 zur Verfügung.Das CVE-Datum deutet darauf hin, dass die Sicherheitsanfälligkeit im Jahr 2017 " entdeckt " wurde, betrifft jedoch einige der in den letzten zwei Jahrzehnten hergestellten Prozessoren (daher wurde sie wahrscheinlich vor langer Zeit entdeckt).
Zunächst einige Definitionen:
Trampolin - Manchmal als indirekte Sprungvektoren bezeichnet Trampoline sind Speicherstellen, die Adressen enthalten, die auf Interrupt-Serviceroutinen, E / A-Routinen usw. verweisen. Die Ausführung springt in das Trampolin und springt dann sofort heraus oder springt, daher der Begriff Trampolin. GCC unterstützt traditionell verschachtelte Funktionen, indem zur Laufzeit ein ausführbares Trampolin erstellt wird, wenn die Adresse einer verschachtelten Funktion verwendet wird. Dies ist ein kleiner Code, der sich normalerweise auf dem Stapel im Stapelrahmen der enthaltenen Funktion befindet. Das Trampolin lädt das statische Kettenregister und springt dann zur realen Adresse der verschachtelten Funktion.
Thunk - Ein Thunk ist eine Unterroutine, mit der eine zusätzliche Berechnung in eine andere Unterroutine eingefügt wird. Thunks werden hauptsächlich verwendet, um eine Berechnung zu verzögern, bis das Ergebnis benötigt wird, oder um Operationen am Anfang oder Ende der anderen Unterroutine einzufügen
Memoization - Eine Memoized-Funktion "merkt" sich die Ergebnisse, die bestimmten spezifischen Eingaben entsprechen. Nachfolgende Aufrufe mit gespeicherten Eingaben geben das gespeicherte Ergebnis zurück, anstatt es neu zu berechnen, wodurch die primären Kosten eines Aufrufs mit bestimmten Parametern von allen außer dem ersten Aufruf der Funktion mit diesen Parametern eliminiert werden.
Sehr grob gesagt ist ein Retpolin ein Trampolin mit einer Rückkehr als Thunk , um die Memoisierung im indirekten Zweigprädiktor zu " verderben " .
Quelle : Die Retpoline enthält einen PAUSE-Befehl für Intel, für AMD ist jedoch ein LFENCE-Befehl erforderlich, da der PAUSE-Befehl auf diesem Prozessor kein Serialisierungsbefehl ist, sodass die pause / jmp-Schleife überschüssige Leistung verbraucht, da über das Warten auf die Rückkehr spekuliert wird das richtige Ziel falsch vorhersagen.
Arstechnica hat eine einfache Erklärung des Problems:
Aus Intels Artikel : " Retpoline: A Branch Target Injection Mitigation " ( .PDF ):
quelle