Nachrichten

Was hinter dem Intel Designfehler steckt, sind zahlreiche Patches?

Was hinter dem Intel Designfehler steckt, sind zahlreiche
 Patches?

Intel Sowohl Windows als auch Linux erhalten wichtige Sicherheitsupdates, die im schlimmsten Fall die Leistung um die Hälfte reduzieren können, um ein Problem zu beheben, das bisher noch nicht vollständig bekannt ist.
In den letzten Wochen haben Patches für den Linux-Kernel Einzug gehalten. Microsoft wurde Testen der Windows-Updates im Insider-Programm seit November , und es wird erwartet, dass die Änderungen am nächsten Patch-Dienstag in Mainstream-Windows-Builds aufgenommen werden. Microsoft Azure hat Wartung nächste Woche geplant, und Amazon AWS ist für Wartung am Freitag geplant – vermutlich verwandt.
Seit den Linux-Patches kam zuerst ans Licht , ein klareres Bild von dem, was falsch scheint, ist aufgetaucht. Während sich Linux und Windows in vielerlei Hinsicht unterscheiden, sind die grundlegenden Elemente, wie diese beiden Betriebssysteme – und tatsächlich jedes andere x86-Betriebssystem wie FreeBSD und Mac OS -Handle-Systemspeicher ist der gleiche, weil diese Teile des Betriebssystems so eng mit den Fähigkeiten des Prozessors gekoppelt sind.
Verfolgen von Adressen
Jedes Byte des Speichers in einem System ist implizit nummeriert, wobei diese Zahlen die Adresse jedes Bytes sind. Die allerersten Betriebssysteme, die mit physikalischen Speicheradressen arbeiten, aber physikalische Speicheradressen sind aus vielen Gründen unbequem. Zum Beispiel gibt es oft Lücken in den Adressen, und (insbesondere bei 32-Bit-Systemen) können physikalische Adressen schwierig zu handhaben sein, was 36-Bit-Nummern oder sogar größere erfordert.
Demnach sind moderne Betriebssysteme auf ein umfassendes Konzept angewiesen, das als virtueller Speicher bezeichnet wird. Virtuelle Speichersysteme ermöglichen es beiden Programmen und den Kernels selbst, in einer einfachen, sauberen und einheitlichen Umgebung zu arbeiten. Anstelle der physikalischen Adressen mit ihren Lücken und anderen Kuriositäten verwendet jedes Programm und der Kernel selbst virtuelle Adressen, um auf den Speicher zuzugreifen. Diese virtuellen Adressen sind zusammenhängend – Sie brauchen sich keine Gedanken über Lücken zu machen – und sind bequem skalierbar, damit sie leicht zu manipulieren sind. 32-Bit-Programme sehen nur 32-Bit-Adressen, selbst wenn die physikalische Adresse eine Nummerierung von 36 oder mehr Bit erfordert.
Während diese virtuelle Adressierung für fast jede Software transparent ist, muss der Prozessor letztendlich wissen, auf welchen physischen Speicher sich eine virtuelle Adresse bezieht. Es gibt eine Zuordnung von virtuellen Adressen zu physischen Adressen, die in einer großen Datenstruktur gespeichert sind, die als Seitentabelle bezeichnet wird. Betriebssysteme erstellen die Seitentabelle unter Verwendung eines Layouts, das durch den Prozessor bestimmt wird, und der Prozessor und das Betriebssystem in Verbindung verwenden die Seitentabelle, wann immer sie zwischen virtuellen und physikalischen Adressen konvertieren müssen.
Dieser gesamte Zuordnungsprozess ist für moderne Betriebssysteme und Prozessoren so wichtig und grundlegend, dass der Prozessor einen speziellen Cache hat – den Translation-Lookaside-Puffer (TLB), der eine bestimmte Anzahl von virtuellen Zuordnungen speichert, so dass die Verwendung der vollständigen vermieden werden kann Seite Tabelle jedes Mal.
Die Verwendung von virtuellem Speicher bietet uns eine Reihe nützlicher Funktionen, die über die Einfachheit der Adressierung hinausgehen. Das wichtigste dabei ist, dass jedes einzelne Programm seinen eigenen Satz virtueller Adressen mit eigenen virtuellen Zuordnungen erhält. Dies ist die grundlegende Technik, die verwendet wird, um “geschütztes Gedächtnis” bereitzustellen; Ein Programm kann den Speicher eines anderen Programms nicht beschädigen oder manipulieren, weil der Speicher des anderen Programms nicht Teil der Zuordnung des ersten Programms ist.
Aber diese Verwendungen eines individuellen Mappings pro Prozess und daher zusätzliche Seitentabellen setzen den TLB-Cache unter Druck. Der TLB ist nicht sehr groß – typischerweise einige hundert Zuordnungen insgesamt – und je mehr Seitentabellen ein System verwendet, desto weniger wahrscheinlich ist es, dass der TLB eine bestimmte virtuell-zu-physikalische Übersetzung enthält.
Halb und halb
Um den TLB bestmöglich zu nutzen, teilt jedes Mainstream-Betriebssystem den Bereich der virtuellen Adressen in zwei Teile auf. Eine Hälfte der Adressen wird für jedes Programm verwendet; die andere Hälfte wird für den Kernel verwendet. Wenn zwischen Prozessen gewechselt wird, ändern sich nur die Hälfte der Seitentabelleneinträge – diejenigen, die zu dem Programm gehören. Die Kernel-Hälfte ist jedem Programm gemeinsam (da es nur einen Kernel gibt) und kann daher die gleiche Seitentabelle für jeden Prozess verwenden. Dies hilft dem TLB enorm; Während es immer noch Mappings verwerfen muss, die zur Hälfte der Speicheradressen des Prozesses gehören, kann es die Mappings für die Kernel-Hälfte beibehalten.
Dieses Design ist nicht vollständig in Stein gemeißelt. Es wurde unter Linux gearbeitet, um es einem 32-Bit-Prozess zu ermöglichen, den gesamten Bereich von Adressen anzugeben, ohne dass zwischen der Seitentabelle des Kernels und der jedes Programms geteilt wird. Während dies den Programmen mehr Adressraum gab, verursachte es einen Performancekosten, weil der TLB die Seitentabelleneinträge des Kernels jedes Mal neu laden musste, wenn der Kernel-Code zum Ausführen benötigt wurde. Dementsprechend wurde dieser Ansatz auf x86-Systemen nie in großem Umfang verwendet.
Ein Nachteil der Entscheidung, den virtuellen Adressraum zwischen dem Kernel und jedem Programm aufzuteilen, ist, dass der Speicherschutz geschwächt ist. Wenn der Kernel einen eigenen Satz von Seitentabellen und virtuellen Adressen hätte, würde er denselben Schutz bieten, den verschiedene Programme voneinander haben; Der Speicher des Kerns wäre einfach unsichtbar. Bei der Split-Adressierung verwenden Benutzerprogramme und der Kernel jedoch denselben Adressbereich, und im Prinzip könnte ein Benutzerprogramm Kernel-Speicher lesen und schreiben.
Um diese offensichtlich unerwünschte Situation zu verhindern, haben der Prozessor und das virtuelle Adressierungssystem ein Konzept von “Ringen” oder “Modi”. x86-Prozessoren haben viele Ringe, aber für dieses Problem sind nur zwei relevant: “Benutzer” (Ring 3) und “Supervisor” (Ring 0). Wenn Sie normale Benutzerprogramme ausführen, wird der Prozessor in den Benutzermodus Ring 3 versetzt. Beim Ausführen von Kernel-Code befindet sich der Prozessor in Ring 0, Supervisor-Modus, der auch als Kernel-Modus bezeichnet wird.
Diese Ringe werden verwendet, um den Kernelspeicher vor Benutzerprogrammen zu schützen. Die Seitentabellen ordnen nicht nur von virtuellen auf physikalische Adressen zu; Sie enthalten auch Metadaten zu diesen Adressen, einschließlich Informationen darüber, welche Ringe auf eine Adresse zugreifen können. Die Seitentabelleneinträge des Kernels sind alle so gekennzeichnet, dass sie nur für Ring 0 zugänglich sind; Die Einträge des Programms sind als von jedem Ring aus zugänglich gekennzeichnet. Wenn versucht wird, in Ring 3 auf Ring-0-Speicher zuzugreifen, blockiert der Prozessor den Zugriff und erzeugt eine Ausnahme. Dies führt dazu, dass Benutzerprogramme, die in Ring 3 laufen, nichts über den Kernel und seinen Ring-0-Speicher lernen können.
Zumindest ist das die Theorie. Die Flut von Patches und Updates zeigen, dass irgendwo diese zusammengebrochen ist. Hier liegt das große Geheimnis.
Zwischen den Ringen wechseln
Folgendes wissen wir. Jeder moderne Prozessor führt eine gewisse spekulative Ausführung aus. Wenn zum Beispiel einige Anweisungen gegeben werden, die zwei Zahlen addieren und dann das Ergebnis im Speicher speichern, könnte ein Prozessor spekulativ die Addition durchführen, bevor festgestellt wird, ob das Ziel im Speicher tatsächlich zugänglich und schreibbar ist. Im allgemeinen Fall, wo der Ort ist beschreibbar schaffte es der Prozessor, Zeit zu sparen, da er die Arithmetik parallel mit dem Herausfinden, was das Ziel im Speicher war, ausführte. Wenn festgestellt wird, dass auf den Speicherort nicht zugegriffen werden kann (z. B. ein Programm, das versucht, auf eine Adresse zu schreiben, die keine Zuordnung und keinen physischen Speicherort hat), wird eine Ausnahme generiert und die spekulative Ausführung wird vergeudet.
Intel Prozessoren, speziell aber nicht AMDs – erlaubt die spekulative Ausführung von Ring-3-Code, der in Ring-0-Speicher schreibt. Die Prozessoren machen richtig blockieren den Schreibvorgang, aber die spekulative Ausführung stört den Prozessorzustand nur minimal, weil bestimmte Daten in den Cache und den TLB geladen werden, um festzustellen, ob der Schreibvorgang erlaubt sein soll. Dies wiederum bedeutet, dass einige Operationen einige Zyklen schneller oder ein paar Zyklen langsamer sind, abhängig davon, ob sich ihre Daten noch im Cache befinden oder nicht. Darüber hinaus verfügen die Prozessoren von Intel über spezielle Funktionen, wie die mit Skylake-Prozessoren eingeführten Software Guard Extensions (SGX), die die Zugriffe auf Speicher leicht ändern. Auch hier schützt der Prozessor Ring-0-Speicher immer noch vor Ring-3-Programmen, aber wiederum werden seine Caches und andere interne Zustände geändert, wodurch messbare Unterschiede entstehen.
Was wir noch nicht wissen, ist, wie viel Kernelspeicher-Informationen an Benutzerprogramme weitergegeben werden können oder wie leicht diese Leckage auftreten kann. Und welche Intel Prozessoren sind betroffen? Wieder ist es nicht ganz klar, aber es gibt Anzeichen dafür, dass jeder Intel-Chip mit spekulativer Ausführung (der alle Mainstream-Prozessoren seit dem Pentium Pro von 1995 eingeführt wurde) Informationen auf diese Weise verlieren kann.
Der erste Wind dieses Problems kam von Forschern von Technische Universität Graz in Österreich . Der Informationsleck, den sie entdeckten, reichte aus, um den Kernel-Modus Address Space Layout Randomization (Kernel ASLR oder KASLR) zu untergraben. ASLR ist so etwas wie ein letzter Versuch, die Ausbeutung von Pufferüberläufe . Mit ASLR werden Programme und ihre Daten an zufällige Speicheradressen platziert, was es für Angreifer etwas schwieriger macht, Sicherheitslücken auszunutzen. KASLR wendet dieselbe Randomisierung auf den Kernel an, so dass die Daten des Kernels (einschließlich der Seitentabellen) und der Code zufällig angeordnet sind.
Die Grazer Forscher entwickelten KAISER , eine Reihe von Linux-Kernel-Patches zur Abwehr des Problems.
Wenn das Problem nur darin bestand, dass es die Derandomisierung von ASLR ermöglichte, wäre dies wahrscheinlich kein großes Desaster. ASLR ist ein netter Schutz, aber es ist bekannt, dass es unvollkommen ist. Es ist eine Hürde für Angreifer, keine unüberwindbare Barriere. Die Branchenreaktion – eine ziemlich große Änderung sowohl von Windows als auch von Linux, die mit etwas Geheimhaltung entwickelt wurde – legt nahe, dass nicht nur ASLR besiegt ist und dass eine allgemeinere Fähigkeit, Informationen aus dem Kernel zu verlieren, entwickelt wurde. In der Tat haben Forscher begann zu twittern dass sie in der Lage sind, beliebige Kerneldaten zu lecken und zu lesen. Eine andere Möglichkeit besteht darin, dass der Fehler verwendet werden kann, um aus einer virtuellen Maschine auszubrechen und einen Hypervisor zu kompromittieren.
Die Lösung, die sowohl die Windows- als auch die Linux-Entwickler gewählt haben, ist im Wesentlichen die gleiche und von dieser KAISER-Arbeit abgeleitet: Die Kernel-Seitentabelleneinträge werden nicht mehr mit jedem Prozess geteilt. In Linux wird dies als Kernel Page Table Isolation (KPTI) bezeichnet.
Bei den Patches ist die Speicheradresse immer noch in zwei Teile aufgeteilt. es ist nur die Kernelhälfte ist fast leer. Es ist nicht ganz leer, da ein paar Kernel-Teile permanent gemappt werden müssen, egal ob der Prozessor in Ring 3 läuft oder Ring 0, aber es ist fast leer. Dies bedeutet, dass selbst wenn ein böswilliges Benutzerprogramm versucht, Kernel-Speicher und Leak-Informationen zu untersuchen, wird es fehlschlagen – es gibt einfach nichts zu verlieren. Die realen Kernel-Seitentabellen werden nur verwendet, wenn der Kernel selbst ausgeführt wird.
Dies untergräbt den Grund für den geteilten Adressraum an erster Stelle. Der TLB muss nun jedes Mal, wenn er zu einem Benutzerprogramm wechselt, alle Einträge löschen, die sich auf die realen Kernelseitentabellen beziehen, wodurch das Leistungssparen beendet wird, das das Teilen aktiviert hat.
Die Auswirkungen davon variieren je nach Arbeitsbelastung. Jedes Mal, wenn ein Programm einen Aufruf an den Kernel macht – um vom Datenträger zu lesen, um Daten an das Netzwerk zu senden, um eine Datei zu öffnen usw. – ist dieser Aufruf ein wenig teurer, da der TLB dadurch gelöscht wird und die echte Kernelseitentabelle, die geladen werden soll. Programme, die den Kernel nicht oft verwenden, könnten einen Treffer von vielleicht 2-3 Prozent sehen – es gibt immer noch einen Overhead, weil der Kernel immer gelegentlich ausgeführt werden muss, um Dinge wie Multitasking zu handhaben.
Aber Workloads, die eine Tonne in den Kernel rufen, werden viel mehr Leistung verlieren. In einem Benchmark, einem Programm, das praktisch nichts tut andere als in die Kernsäge rufen seine Leistung sinkt um etwa 50 Prozent ; mit anderen Worten, jeder Aufruf in den Kernel dauerte mit dem Patch doppelt so lange wie ohne. Benchmarks, die das Loopback-Netzwerk von Linux nutzen, sehen ebenfalls einen großen Hit, wie z 17 Prozent in diesem Postgres-Benchmark. Echte Datenbank-Workloads, die echtes Netzwerk verwenden, sollten geringere Auswirkungen haben, da bei echten Netzwerken der Overhead des Aufrufs in den Kernel tendenziell vom Overhead der Verwendung des tatsächlichen Netzwerks dominiert wird.
Intel-Systeme sind diejenigen, von denen bekannt ist, dass sie den Defekt haben, aber sie sind möglicherweise nicht die einzigen, die betroffen sind. Einige Plattformen, wie SPARC und IBM S390, sind gegen das Problem immun, da ihre Prozessorspeicherverwaltung den geteilten Adressraum und die freigegebenen Kernelseitentabellen nicht benötigt; Betriebssysteme auf diesen Plattformen haben ihre Kernelseitentabellen immer von denen im Benutzermodus isoliert. Andere, wie ARM, sind vielleicht nicht so glücklich. vergleichbare Patches für ARM Linux sind in Entwicklung.

Post Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.