misterunknown
Ehemalige
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
Moin, ich habe ein Verständnisproblem bzgl. des Spectre-Angriffs. Ich muss das hier für die Firma analysieren, und habe mir daher ein paar Infos zusammengesucht. Als erstes bin ich auf diese Seite gestoßen, wo es heißt:
Spectre breaks the isolation between different applications. It allows an attacker to trick error-free programs, which follow best practices, into leaking their secrets.
Anschließend habe ich mir das Paper dazu durchgelesen. Aus beidem ergeben sich für mich zwei Fragen:
Am Ende des Papers gibt es einen PoC in C geschrieben, welcher die Attacke erklärt. Allerdings passiert das dort innerhalb desselben Prozesses. Auch das erwähnte Beispiel, in dem per Javascript Speicheradressen des ausführenden Browser-Prozesses ausgelesen wurden, funktioniert nur innerhalb des einen Prozesses. Die oben zitierte Beschreibung der Lücke spricht jedoch davon, dass die Isolation zwischen verschiedenen Applikationen gebrochen wird. Wie muss ich das verstehen? Das OS nutzt ja (fast) ausschließlich virtual memory. Selbst der Prozessor kennt die virtuellen Adressen und hat dafür den Translation-Lookaside-Buffer, um nicht immer in der Page-Table suchen zu müssen. An welcher Stelle genau wird die virtuelle Adresse in eine physische Adresse aufgelöst? Mein gedankliches Problem ist, dass meines Erachtens bei der "speculative execution" virtuelle Adressen genutzt werden, und diese erst beim eigentlichen Zugriff auf den physischen Speicher aufgelöst werden. Auch das würde aber bedeuten, dass man nur Speicherbereiche des aktuellen Prozesses leaken kann, was dem o.g. Zitat ebenfalls widerspricht.
Ich hoffe mich kann da jemand erhellen. Viele Grüße, Marco
|
redknight
Moderator & Supporter
Anmeldungsdatum: 30. Oktober 2008
Beiträge: 21733
Wohnort: Lorchhausen im schönen Rheingau
|
Angeblich hat die TU Graz da was: https://twitter.com/danimo/status/948886025140568064 (einfach mal Link reingeworfen, ohne die Papers konkret gelesen zu haben)
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
Zu Punkt 2 kann ich was sagen: die Auflösung einer virtuellen Adresse macht die MMU. Beim Zugriff auf den Speicher wird die Übersetzung gemacht und falls die zugegriffene Seite nicht im physikalischen Speicher ist, gibt es einen "Page Fault" und die Seite wird typischerweise von Platte geladen (entweder das Image der Anwendung oder Swap). Hier ist das noch ausführlicher erklärt. Ich denke nicht, dass es hier einen Unterschied zwischen der spekulativen und der tatsächlichen Ausführung gibt. Auch bei einem spekulativen Laden von Daten müssen ja die echten Daten aus dem Hauptspeicher (oder Cache) geholt werden. Ansonsten ist die Ausführung nix wert und man könnte sie gleich lassen.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
Zu Punkt 1: im Blog von Project Zero wird erläutert:
A PoC that demonstrates the basic principles behind variant 1 in userspace on the tested Intel Haswell Xeon CPU, the AMD FX CPU, the AMD PRO CPU and an ARM Cortex A57 [2]. This PoC only tests for the ability to read data inside mis-speculated execution within the same process, without crossing any privilege boundaries.
Das ist also eine Beschränkung des PoC, nicht des Angriffs. Zusätzlich wäre noch zu erwähnen, dass Meltdown Kernel-Speicher liest, der im virtuellen Adressraum jedes Prozesses unter Linux liegt, damit bei einem Syscall weniger Arbeit zu machen ist und der Kernel-Code gleich auf die Kernel-Datenstrukturen zugreifen kann. Für den User-Code ist dieser Speicher unsichtbar - das hebelt Meltdown aus.
|
chilidude
Anmeldungsdatum: 18. Februar 2010
Beiträge: 867
|
@misterunknown 1. Das funktioniert über Timing-Angriffe. Das heisst die Sprungvorhersage wird explizit ausgetrickst um den Prozessor dazu zu zwingen entweder aus dem Cache oder dem Speicher zu laden. Der Zeitunterschied ergibt dann die Aussage über den Speicherinhalt des Fremdprozesses, da sich diese den Cache teilen. (Ist imho zumindest bei Kernen mit HT der Fall) 2. Das betrifft wohl Meltdown. Der Angriff erfolgt immer über die virtuelle Adresse was damit zusammenhängt, dass die Betriebssysteme immmer den kompletten physischen Speicherinhalt in den virtuellen Prozessspeicher einblenden. Das wird vermutlich aus Performancegründen so gemacht
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
chilidude schrieb:
2. Das betrifft wohl Meltdown. Der Angriff erfolgt immer über die virtuelle Adresse was damit zusammenhängt, dass die Betriebssysteme immmer den kompletten physischen Speicherinhalt in den virtuellen Prozessspeicher einblenden. Das wird vermutlich aus Performancegründen so gemacht
Den kompletten? Das glaube ich nicht. Das ergibt doch gar keinen Sinn, denn der physikalische Speicher ist ja verschiedenen Prozessen zugeordnet. Beim Kernel ist das etwas anderes, weil es da halt den Vorteil der schnelleren Syscalls hat.
|
chilidude
Anmeldungsdatum: 18. Februar 2010
Beiträge: 867
|
Ja, der ganze physische Speicher und das steht im Sheet auch so drin. Im Prinzip ist das auch kein Problem, da jeder Eintrag in den Deskriptortabellen nicht nur auf die physische Adresse des Speichers verweist, sondern auch auch eine Zugriffs-ID besitzt, die gegen die Zugriffs-ID des Prozesses abgeglichen wird. Die möglichen ID-Werte liegen zwischen 0 (kernel=höchste) und 3 (user=niedrigste). (Die 1 und die 2 sind eigentlich für Treiber vorgesehen werden aber sowohl bei Linux als auch bei Windows nicht genutzt.) Beim ersten Laden oder Speichern werden die Schattenregister (Caches) geladen und dieses ID-Werte geprüft. (Dies dauert einige hundert Taktzyklen.) Der jeweilige Prozess kann dann nur auf Speicher zugreifen der eine ID aufweist die gleich oder niedriger ist. Der Angriff erfolgt dann über die parallel arbeitende Auswertelogik die den Prozessor unterstützt, d.h. bevor die Schutzverletzung vom Prozessor registriert wird steht bereits in der Auswertelogik ein Ergebnis bereit welches vom Angreifer gelesen werden kann. Dazu bieten Intel-Chips, so wie ich es jetzt aus dem Sheet verstanden habe, wohl die Möglichkeit für den Userprozess die Schutzverletzung zu unterdrücken, so dass er nicht beendet wird. (Normalerweise wird bei einer Schutzverletzung durch den Userprozess dieser durch den Kernel sofort beendet.)
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
chilidude schrieb: Ja, der ganze physische Speicher und das steht im Sheet auch so drin.
In welchem "Sheet"?
Im Prinzip ist das auch kein Problem,
Der Punkt ist, dass das gar nicht sinnvoll ist. Das wäre unnötige Arbeit für den Kernel und die Verwaltungsstrukturen jedes Prozesses wären mit Einträgen für Seiten belastet, die nicht zu ihm oder dem Kernel gehören. Und aktuell ungenutzte Speicherseiten irgendwo einzublenden ist erst recht sinnlos.
da jeder Eintrag in den Deskriptortabellen nicht nur auf die physische Adresse des Speichers verweist,
Nicht alle Seiten müssen in physischem Speicher liegen. Sie können auch auf Festplatte ausgelagert oder noch nicht benutzt worden sein. Du schriebst
Der Angriff erfolgt immer über die virtuelle Adresse was damit zusammenhängt, dass die Betriebssysteme immmer den kompletten physischen Speicherinhalt in den virtuellen Prozessspeicher einblenden.
Es gibt zwei mögliche Interpretationen Deiner Aussage:
Betriebssysteme blenden den kompletten physischen Speicherinhalt in irgendeinen virtuellen Prozessspeicher ein. Betriebssysteme blenden den kompletten physischen Speicherinhalt in alle virtuellen Prozessspeicher ein.
Beides ist nicht sinnvoll, da nicht der komplette physische Speicher in Benutzung sein muss, was die erste Aussage fragwürdig macht. Und Speicher von Prozessen soll ja gerade für andere Prozesse nicht sichtbar und zugreifbar sein, weshalb es unnötig und unsinnig wäre, ihn in andere einzublenden (Aussage 2). Was der Linux-Kernel tut: er blendet den Kernel-Speicher in alle Prozesse ein, damit Syscalls weniger Arbeit haben. Dieser eingeblendete Kernel-Speicher wird durch den Ring 0 normalerweise (also vor Meltdown) vor Zugriffen aus dem Prozesscode in Ring 3 geschützt, wie Du ja beschreibst:
sondern auch auch eine Zugriffs-ID besitzt, die gegen die Zugriffs-ID des Prozesses abgeglichen wird. Die möglichen ID-Werte liegen zwischen 0 (kernel=höchste) und 3 (user=niedrigste). (Die 1 und die 2 sind eigentlich für Treiber vorgesehen werden aber sowohl bei Linux als auch bei Windows nicht genutzt.) Beim ersten Laden oder Speichern werden die Schattenregister (Caches) geladen und dieses ID-Werte geprüft. (Dies dauert einige hundert Taktzyklen.) Der jeweilige Prozess kann dann nur auf Speicher zugreifen der eine ID aufweist die gleich oder niedriger ist.
Du meinst vermutlich "gleich oder höher", denn sonst könnte ein beliebiger Prozess in Ring 3 auf Ring 0-Daten (also Kernel-Daten) zugreifen. Laut den Erklärungen von Team Zero gibt es drei Varianten von Angriffen:
bounds check bypass kann Kernel-Speicher lesen (Meltdown) branch target injection kann Speicher eines beliebigen anderen Prozesses lesen, was wohl auch aus einer VM funktioniert (Spectre) rogue data cache load kann Kernel-Speicher lesen (Meltdown)
Das Einblenden von Kernel-Speicher in jeden Prozess spielt wohl nur bei Variante 1 und 3 eine Rolle. Variante 2 funktioniert ganz anders, denn dabei wird ein Opfer (Prozess) dazu gebracht, spekulativ Anweisungen auszuführen, die er normalerweise nicht ausführen würde und über einen Seitenkanal-Angriff lässt sich dann der Speicher dieses Opfers lesen.
Der Angriff erfolgt dann über die parallel arbeitende Auswertelogik die den Prozessor unterstützt, d.h. bevor die Schutzverletzung vom Prozessor registriert wird steht bereits in der Auswertelogik ein Ergebnis bereit welches vom Angreifer gelesen werden kann. Dazu bieten Intel-Chips, so wie ich es jetzt aus dem Sheet verstanden habe, wohl die Möglichkeit für den Userprozess die Schutzverletzung zu unterdrücken, so dass er nicht beendet wird. (Normalerweise wird bei einer Schutzverletzung durch den Userprozess dieser durch den Kernel sofort beendet.)
Der Witz ist ja gerade, dass gar keine Schutzverletzung erkannt wird. Also muss sie auch nicht unterdrückt werden. Die Zugriffe erfolgen ja auch nicht direkt (also durch eine einfache Operation, die Speicher liest) sondern indirekt.
|
misterunknown
Ehemalige
(Themenstarter)
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
Ich danke allen für eure Antworten! Hat mir sehr geholfen, ich Blicke jetzt durch. Ich kann übrigens nur jedem empfehlen mal die Papers durchzulesen, und zwar beide (Empfehlung: erst Meltdown, dann Spectre).
|
misterunknown
Ehemalige
(Themenstarter)
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
rklm schrieb: Der Angriff erfolgt immer über die virtuelle Adresse was damit zusammenhängt, dass die Betriebssysteme immmer den kompletten physischen Speicherinhalt in den virtuellen Prozessspeicher einblenden.
Es gibt zwei mögliche Interpretationen Deiner Aussage:
Betriebssysteme blenden den kompletten physischen Speicherinhalt in irgendeinen virtuellen Prozessspeicher ein. Betriebssysteme blenden den kompletten physischen Speicherinhalt in alle virtuellen Prozessspeicher ein.
So wie ich das verstanden habe, ist zweitens der Fall. Jeder virtuelle Adressraum eines Userspace-Prozesses beinhaltet die Adressen für den Prozess an sich, und für den Kernel (siehe Seite 4, Figure 2).
Der Angriff erfolgt dann über die parallel arbeitende Auswertelogik die den Prozessor unterstützt, d.h. bevor die Schutzverletzung vom Prozessor registriert wird steht bereits in der Auswertelogik ein Ergebnis bereit welches vom Angreifer gelesen werden kann. Dazu bieten Intel-Chips, so wie ich es jetzt aus dem Sheet verstanden habe, wohl die Möglichkeit für den Userprozess die Schutzverletzung zu unterdrücken, so dass er nicht beendet wird. (Normalerweise wird bei einer Schutzverletzung durch den Userprozess dieser durch den Kernel sofort beendet.)
Der Witz ist ja gerade, dass gar keine Schutzverletzung erkannt wird. Also muss sie auch nicht unterdrückt werden. Die Zugriffe erfolgen ja auch nicht direkt (also durch eine einfache Operation, die Speicher liest) sondern indirekt.
Also bei Meltdown wird schon eine Schutzverletzung erkannt. Die CPU wirft eine Exception, aber eben zu spät, da durch die Out-of-Order-Execution der Wert bereits von einer anderen Instruction benutzt wurde.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
misterunknown schrieb: rklm schrieb: Der Angriff erfolgt immer über die virtuelle Adresse was damit zusammenhängt, dass die Betriebssysteme immmer den kompletten physischen Speicherinhalt in den virtuellen Prozessspeicher einblenden.
Es gibt zwei mögliche Interpretationen Deiner Aussage:
Betriebssysteme blenden den kompletten physischen Speicherinhalt in irgendeinen virtuellen Prozessspeicher ein. Betriebssysteme blenden den kompletten physischen Speicherinhalt in alle virtuellen Prozessspeicher ein.
So wie ich das verstanden habe, ist zweitens der Fall. Jeder virtuelle Adressraum eines Userspace-Prozesses beinhaltet die Adressen für den Prozess an sich, und für den Kernel (siehe Seite 4, Figure 2).
Ja, aber nur den Kernel-Speicher, wie ich ja auch geschrieben habe, aber nicht "den kompletten physischen Speicherinhalt".
Der Witz ist ja gerade, dass gar keine Schutzverletzung erkannt wird. Also muss sie auch nicht unterdrückt werden. Die Zugriffe erfolgen ja auch nicht direkt (also durch eine einfache Operation, die Speicher liest) sondern indirekt.
Also bei Meltdown wird schon eine Schutzverletzung erkannt. Die CPU wirft eine Exception, aber eben zu spät, da durch die Out-of-Order-Execution der Wert bereits von einer anderen Instruction benutzt wurde.
Ah ja, Du hast Recht. Ich habe jetzt mal noch weiter im Paper gelesen und die entsprechenden Erklärungen in Kapitel 4.1 gefunden. Die Schutzverletzung entsteht beim Vorbereiten der Daten (also der Änderung des "microarchitectural state") und nicht mehr beim Auslesen durch den Seitenkanalangriff. Ich hatte mich nur auf das finale Auslesen konzentriert. Japp, jetzt habbich's. Danke!
|
misterunknown
Ehemalige
(Themenstarter)
Anmeldungsdatum: 28. Oktober 2009
Beiträge: 4403
Wohnort: Sachsen
|
rklm schrieb: Ja, aber nur den Kernel-Speicher, wie ich ja auch geschrieben habe, aber nicht "den kompletten physischen Speicherinhalt".
Doch, denn der Kernel mappt immer den gesamten (genutzten) physischen Speicher in seinem Bereich. Siehe auch dazu das Meltdown-Paper: The kernel address space does not only have memory mapped for the kernel’s own usage, but it also needs to perform operations on user pages, e.g., filling them with data. Consequently, the entire physical memory is typically mapped in the kernel. On Linux and OS X, this is done via a direct-physical map, i.e., the entire physical memory is directly mapped to a pre-defined virtual address (cf. Figure 2).
rklm schrieb: Ich habe jetzt mal noch weiter im Paper gelesen und die entsprechenden Erklärungen in Kapitel 4.1 gefunden. Die Schutzverletzung entsteht beim Vorbereiten der Daten (also der Änderung des "microarchitectural state") und nicht mehr beim Auslesen durch den Seitenkanalangriff. Ich hatte mich nur auf das finale Auslesen konzentriert. Japp, jetzt habbich's. Danke!
Ich hab die beiden Papers gestern auch x mal gelesen, bevor ich eine Vorstellung hatte, was genau passiert^^
|
chilidude
Anmeldungsdatum: 18. Februar 2010
Beiträge: 867
|
Technisch geshen besitzt die 8086 Cpu im Protected-Mode Beschreibertabellen, eine globale und bis zu 8191 lokale innerhalb der globalen. (Lokale und globale sind vom Aufbau her identisch.) Jeder Prozess hat daher zumindest eine solche lokale Beschreibertabelle die seinen Prozesspeicher ausweisst und den des gesamten Kernel einschliesslich konkurrierender Prozesse - mit einer anderern Schutz-ID wohlgemerkt. Erfolgte bisher ein Kernelaufruf wird nichts anderes gemacht als den Segmenttselektor (Das sind die Segmentregister cs, ds, es, fs, gs, ss usw.) innerhalb dieser lokalen Beschreibertabelle neu zu laden, was relativ schnell geht. Der Patch behebt nun den Fehler indem er den Kernelspeicher in eine andere Beschreibertabelle auslagert. Bei einem Kernelaufruf muss nun die gesamte Beschreibertabelle, wie bei einem Taskwechsel, neu geladen werden, was den Leistungsverlust von 2-30 Prozent dann ausmacht. Vielleicht ist es so verständlicher.
|