Die Neuerungen von Linux 4.16

Seite 3: Schutz vor Meltdown & Spectre

Inhaltsverzeichnis

Zum Schutz vor der ersten Spectre-Variante (Bounds Check Bypass; CVE-2017-5753) haben die Entwickler nach potenziell für die Lücke anfällige Stellen im Kernel-Code gesucht. Solche haben sie dann geändert, um dort eine spekulative Ausführung zu unterbinden und so die Lücke auszuhebeln. Das gelingt vor allem durch den Aufruf des eigens dafür geschaffenen Makros array_index_nospec() (u. a. 1, 2, 3, 4, 5, Dokumentation).

Die Dokumentation erläutert jetzt Gefahren der spekulativen Ausführung und wie man einige solcher mit einem neuem Makro umgehen kann.

(Bild: git.kernel.org – f84a56f73ddd )

Womöglich müssen die Entwickler noch mehr Stellen ähnlich anpassen. Außerdem müssen sie bei der Weiterentwicklung darauf achten, das Makro auch bei neuem Code zu nutzen, wenn dieser potenziell anfällige Abschnitte aufweist. Indizien zufolge ist ein Tool in Arbeit, das solche Stellen aufzeigt. Bislang haben einige Entwickler auf das proprietäre Werkzeug Coverity zurückgegriffen, um solche Code-Bereiche zu finden.

Als Maßnahme gegen die zweite Spectre-Variante (Branch Target Injection / BTI; CVE-2017-5715) setzt der Linux-Kernel 4.16 weiter auf Retpoline, das die dritte Seite des Kernel-Log zu Linux 4.15 bereits näher erläutert hat. Dieser Ansatz reicht in einigen Situationen aber nicht aus, etwa bei der Virtualisierung. Hier haben die Kernel-Entwickler nachgebessert: Zum besseren Schutz nutzt der Kernel in einigen Situationen jetzt Funktionen zur Indirect Branch Control (IBC). Das ist der Oberbegriff für die Prozessor-Flags Indirect Branch Prediction Barrier (IBPB), Indirect Branch Restricted Speculation (IBRS) und Single Thread Indirect Branch Predictor (STIBP), die AMD und Intel mit neuem Microcode nachrüsten.

IBC war für Betriebssystemhersteller gedacht, damit sie darüber einen Komplettschutz vor Spectre v2 implementieren. Windows nutzt diesen Ansatz. Auch Red Hat Enterprise Linux, Suse Enterprise Linux und Ubuntu haben anfangs voll auf diesen Schutzansatz gesetzt, den der offizielle Kernel nach jetzigem Stand wohl nie implementieren wird. Mittlerweile sind auch alle drei Distributoren weitgehend oder vollständig auf Retpoline umgestiegen, nachdem die Entwickler des Linux-Kernels dieser Lösung den Vorzug gegeben haben – unter anderem, weil Retpoline deutlich weniger Performance-Overhead als IBC hat und bereits ohne Microcode-Update gut schützt.

Zum sicheren Virtualisieren mit dem Kernel-eigenen Hypervisor KVM reicht Retpoline aber nicht, da es beim Wechsel von einer Virtual Machine (VM) zum Host oder anderen VMs nicht zum Zug kommt. Linux 4.16 verwendet daher an dieser Stelle jetzt die IBC-Funktion IBPB, um diesen Gefahrenpunkt zu eliminieren (u. a. 1, 2). Außerdem kann der Kernel die Prozessor-Flags jetzt auch an virtuelle Maschinen durchreichen (u. a. 1). Das ist zum sicheren Virtualisieren von Windows und anderen Betriebssystemen nötig, die ausschließlich mit IBC vor Spectre v2 schützen.

Darüber hinaus greift der Kernel jetzt auch auf IBPB zurück, wenn er von oder zu Programmen wechselt (Context Switch), die als "non dumpable" deklariert wurden. Dieses Flag untersagt dem System, beim Programmabsturz ein Abbild des Speicherinhalts (Coredump) zu erzeugen. Es ist daher typischerweise bei Programmen wie GPG gesetzt, die Schlüssel, Passwörter und andere sensitive Informationen verarbeiten – also Programme, die ein lohnendes Angriffsziel sind. Bei solchen nehmen die Kernel-Entwickler daher den Performance-Overhead von IBPB in Kauf, um den Schutz zu verbessern. Linux 4.16 schützt sogar vor Angriffen auf die Firmware, indem es das IBC-Feature IBRS nutzt, bevor er Firmware-Code aufruft. Wenn der Kernel diese beiden Gegenmaßnahmen verwendet, zeigt er in /sys/devices/system/cpu/vulnerabilities/spectre_v2 die Flags "IBPB" und "IBRS_FW" an.

Die Kernel-Entwickler haben den Schutz vor den Anfang Januar bekannt gewordenen Prozessorlücken Spectre und Meltdown verbessert.

Der Retpoline ergänzende Schutz mit sporadischer IBC-Nutzung greift naturgemäß nur bei x86-64-Systemen, die IBC durch neuen Microcode gelernt haben. Einige Systemhersteller liefern BIOSe mit solchem Microcode aus. Linux kann den neuen Microcode auch beim Booten in den flüchtigen Speicher des Prozessors laden. Dazu müssen die Archive mit IBC-tauglichem Microcode installiert sein. Die von AMD sind schon seit einigen Wochen Bestandteil vieler Distributionen. Die Archive mit Intels IBC-Microcode sind seit Mitte März verfügbar, nachdem das Unternehmen solche schon Anfang Januar vorgestellt hatte, aufgrund von Problem aber wenig später zurückzog.

Für IBC ist wichtig, dass der Microcode früh geladen wird.

(Bild: git.kernel.org – 42ca8082e260 )

Wichtig für IBC: Der Kernel muss das Microcode-Update per "Early Microcode Load" hochladen, damit es im Prozessor aktiv ist, bevor der Kernel selbst richtig in Gang kommt. Die meisten modernen Distributionen nutzen diesen Weg. Einige verwenden aber nach wie vor das klassische und manchmal auch "Late Microcode Load" genannte Verfahren, das den Microcode erst in den Prozessor lädt, nachdem der Kernel schon angelaufen ist und die Fähigkeiten des Prozessors abgefragt hat. Er sieht die vom Microcode-Update nachgerüsteten Prozessor-Flags zur IBC daher womöglich nicht, sodass er die Schutzfunktion dann auch nicht nutzt. Auf diese Problematik weist Linux in den per Dmesg abrufbaren Log-Meldungen jetzt hin.

Als wäre das alles nicht schon kompliziert genug, gibt es noch viele andere Details rund um die Gegenmaßnahmen. So ignoriert der Kernel die IBC-Funktionen bei bekanntermaßen problematischen Microcode-Versionen, die auf einer Blacklist stehen; dort waren zeitweise auch Versionen verzeichnet, die Intel letztlich doch wieder als unproblematisch einstufte. Die Liste musste daher bereits mehrfach angepasst werden (u. a. 1, 2); gut möglich, dass weitere Anpassungen erforderlich werden und Distributionen hier hinterherhinken.

Die Entwicklung der Spectre-v2-Gegenmaßnahmen im Linux-Kernel scheint indes nach wie vor nicht abgeschlossen. Schon im Januar gab es größere Diskussionen darüber, dass Retpoline unzureichend für Prozessoren seit der Skylake-Generation ist, was etwa Intels Core-i-6000-CPUs betrifft. Die Entwickler haben daher Schutzcode extra für solche CPUs integriert. Darüber hinaus haben sie lange über einen deutlich tiefergreifenden Ansatz diskutiert, der den Schutz bei Skylake komplett machen sollte. Von diesem Ansatz und der Problematik war in den letzten Wochen aber nichts mehr zu hören. Warum, ist unklar; möglicherweise sind die Entwickler fürs Erste zu der Auffassung gelangt, dass die jetzigen Gegenmaßnahmen in der Praxis auch auf Skylake allemal ausreichen. Zumindest Red Hat scheint davon aber bislang nicht überzeugt zu sein, denn dessen Unternehmens-Linux verwendet bei Skylake-CPUs nicht Retpoline zum Schutz, sondern allein IBC.

Vor Meltdown (Rogue Data Cache Load/CVE-2017-5754) schützt der Kernel schon seit den zum Jahreswechsel freigegebenen Linux-Versionen per PTI (Page Table Isolation). An diesem ebenfalls im Kernel-Log zu Linux 4.15 näher beschriebenem Ansatz haben die Entwickler zwischenzeitlich einige Detailverbesserungen vorgenommen.

Auch am in 4.15 eingeflossenen Retpoline und anderen Maßnahmen gegen die Anfang Januar bekannt gewordenen Prozessorlücken gab es Feinschliff. Einige verbessern den Schutz, beispielsweise am BPF, um diese von zahlreichen anderen Subsystemen genutzte Virtual Machine des Kernels abzudichten. Einige Umbauten reduzieren auch die Performance-Auswirkungen; gerade die KVM-Performance soll durch einige der Optimierungen wieder zugelegt haben. Wichtig bei der KVM-Virtualisierung ist indes, dass man auch das typischerweise mit KVM genutzte Qemu gegen die Prozessorlücken abdichtet.

Details zu diesen und vielen anderen Änderungen rund um den Meltdown- & Spectre-Schutz liefern die Kommentare einiger Git Merges (1, 2, 3, 4, 5, 6, 7).

Die wichtigsten der verbesserten Gegenmaßnahmen sind auch in aktuelle Stable- und Longterm-Kernel wie 4.15 und 4.14 eingeflossen. Viele sind auch in ältere Longterm-Kernel und die Kernel von Linux-Distributionen für PCs übergegangen. Die Optimierungen stecken aber teilweise nur in 4.16; daher ist der mit dem Schutz vor Spectre und Meltdown einhergehende Performance-Verlust dort in manchen Situationen geringer.

Die unter 64-Bit-x86-Systemen verfügbaren Spectre-v1-Maßnahmen wie array_index_nospec() funktionieren auch auf 32-Bit-x86-Systemen; das gleiche gilt für den Spectre-v2-Schutz Retpoline.

Bei der Meltdown-Gegenmaßnahme PTI ist das nicht der Fall, denn an einer PTI-Implementierung für x86-32-Architektur wird noch gearbeitet. Nachdem eine erste und noch rohe Version Mitte Januar erschien, ist seit Anfang März eine vierte Fassung eines PTI für die 32-Bit-x86-Architektur verfügbar. Noch ist unklar, ob diese in Linux 4.17 einfließen wird, denn sie ist bislang nicht im Entwicklerzweig "Linux-Next" angekommen, wo gerade die Änderungen für das im Juni erwartete Linux 4.17 zusammenfließen.

Das für 32-Bit-x86-Systeme vorbereite PTI wird auf PCID-tauglichen Prozessoren zum Einsatz eines 64-Bit-x86-Kernels raten.

(Bild: patchwork.kernel.org – 10289935 )

Wer ein 32-Bit-x86-Linux auf einem modernen 64-Bit-Prozessor betreibt, kann sich bereits jetzt auf einen größeren Performance-Einbruch durch PTI gefasst machen. Im 32-Bit-Modus kann der Kernel nämlich keine "Process-Context Identifier" (PCID) nutzen, mit denen 64-Bit-x86-Linux die Performance-Einbußen durch PTI deutlich senken kann, sofern der Prozessor denn das seit Intels Haswell unterstützte INVPCID beherrscht. Linus Torvalds und andere wichtige Entwickler raten daher dazu, bei solchen Systemen einen 64-Bit-Kernel einzusetzen. Das geht auch ohne Neuinstallation, denn in vielen Fällen funktionieren die Kernel einer 64-Bit-x86-Distribution auch auf deren 32-Bit-x86-Variante.

Allerdings unterstützen die wenigsten Distributionen eine solche Betriebsart von Haus aus, daher muss man oft selbst Hand anlegen. Dadurch kann der Kernel auch andere Prozessor-Features verwenden, die nur im 64-Bit-Betrieb verfügbar ist; zugleich wird der Overhead vermieden, den für 64-Bit kompilierte Programme haben. Dabei kann es aber zu Problemen bei den Schnittstellen kommen, über die sich Kernel und Userspace austauschen. Einige Entwickler sind solche Schwierigkeiten vor ein paar Jahren angegangen; es ist aber unklar, ob sie alles Wichtige abgesichert haben, denn die Kombination von 64-Bit-Kernel mit 32-Bit-Userland ist recht rar und daher kaum getestet.

Der 32-Bit-x86-Code soll noch eine Weile im Kernel bleiben.

(Bild: mail-archive.com – msg1607115 )

Im Rahmen der PTI-Diskussion kam auch die Frage auf, ob der Support für 32-Bit-x86-Systme entfernt werden sollte. Torvalds meldete sich dazu selbst zu Wort: "In fünf oder zehn Jahren vielleicht. In nächster Zeit aber leider nicht."

Die Spectre-v1-Gegenmaßnahme array_index_nospec() funktioniert auch auf der S390-Architektur sowie modernen 32- und 64-Bit-ARM-Kernen.

Der AMR64-Code von Linux bringt jetzt auch einen Spectre-v2-Schutz mit: Um die Lücke auf betroffenen ARM64-Systemen zu umgehen, springt der Kernel an kritischen Stellen jetzt in die Secure Firmware, damit sie von der Sprungvorhersage (den "Branch Predictor") erzeugte Einträge verwirft. Für die von Meltdown betroffenen ARMv8-Kerne bringt der ARM64-Code von Linux jetzt eine ARM64-Implementation von PTI mit. Details hierzu nennen die Kommentare zwei Git Merges (1, 2).

Als Spectre-v2-Gegenmaßnahme hat der Code für IBMs Großrechner der S390-Familie jetzt einen "Expoline" genannten Schutz, der ähnlich wie Retpoline funktioniert.

Der Code für 32-Bit-ARM-Kerne schützt derzeit nicht vor Spectre v2: Eine Patch-Sammlung, die hier helfen soll, hat es bislang nicht in den offiziellen Kernel geschafft. Es gibt auch keinen Meltdown-Schutz, wenn man ein 32-Bit-ARM-Kernel auf einem von Meltdown betroffenen 64-Bit-ARM-Kern betreibt.