Hallo Community.
Anbei findet ihr meine cruden gcc-Patches. (gcc_spectre_v1_rev2.patch)
Natürlich sind diese enorm verbesserungswürdig - zumindest ich will aber
erstmal wieder etwas sichereres haben...
...natürlich stehen auch entsprechende Kernelpatches an...
Ich habe noch einige bedingte Maschinenbefehle an spekulativer
Ausführung blockieren lassen.
Ggf. kommen irgendwann mal optimierte Patchserien gegen Spectre V1
online, oder das hier wird besser optimiert...
Die Patche sind alle auf den aktuellen gcc 7.2 anzuwenden:
https://ftp.gnu.org/gnu/gcc/gcc-7.2.0/gcc-7.2.0.tar.xz
Zum Compilieren vom gcc werden 3 weitere externe Pakete gebraucht:
https://ftp.gnu.org/gnu/gmp/gmp-6.1.2.tar.xzhttp://www.mpfr.org/mpfr-3.1.5/mpfr-3.1.5.tar.xzhttps://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
Ausserdem muss zuvor eine moderne binutils gebaut werden:
https://ftp.gnu.org/gnu/binutils/binutils-2.29.tar.xz
Bitte beachtet, das ihr zuerst einen morderneren gcc benötigt, um mein
installiertes Patch compilieren zu können. (Die meisten Distributionen
liefern ggc 4.9 aus: gcc --version)
Am besten erstmal den 7.2 ohne Patches bauen und in einen Ordner eurer
Wahl installieren lassen.
Dann Pfad umbiegen (gcc --version auf 7.2.0 checken) und dann Patches
installieren und das ganze mit den frischen Compiler nochmal
compilieren.
Ganz am Ende am besten alles ein finales mal Übersetzten...
(Bauanleitung am Ende des Posts)
Mit dem neuen Compiler könnt ihr dann auch (unabhängig von den lfence
Barrieren) "-mindirect-branch=thunk -mfunction-return=thun" zur
Mitigation v. Spectre V2 aktivieren:
https://support.google.com/faqs/answer/7625886
gcc -mindirect-branch=thunk-extern -mfunction-return=thunk -o hello
hello.c
produziert:
# objdump -M intel -d hello
[...]
[...]
Wogegen der alte Compiler /usr/bin/gcc -o hello hello.c
produziert:
# objdump -M intel -d hello
[...]
1
000000000400526 <main>:
2
400526: 55 push rbp
3
400527: 48 89 e5 mov rbp,rsp
4
40052a: 48 83 ec 10 sub rsp,0x10
5
40052e: 89 7d fc mov DWORD PTR [rbp-0x4],edi
6
400531: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi
7
400535: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
8
400539: 7e 0a jle 400545 <main+0x1f>
9
40053b: bf d4 05 40 00 mov edi,0x4005d4
10
400540: e8 bb fe ff ff call 400400 <puts@plt>
11
400545: b8 00 00 00 00 mov eax,0x0
12
40054a: c9 leave
13
40054b: c3 ret
14
40054c: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
[...]
Bauanleitung nach /tmp/install
1) mkdir -p /tmp/sources
2) cd /tmp/sources
3) xzcat binutils-2.29.tar.xz | tar -x
4) cd binutils-2.29
5) mkdir build
6) cd build
7) ../configure --prefix=/tmp/install/ --disable-nls --disable-werror
8) make -j<AnzahlDerCPUKerne>
9) make install
10) cd /tmp/sources
11) xzcat gcc-7.2.0.tar.xz | tar -x
12) cd gcc-7.2.0
13) xzcat gmp-6.1.2.tar.xz | tar -x
14) mv gmp-6.1.2/ gmp
15) xzcat mpfr-3.1.5.tar.xz | tar -x
16) mv mpfr-3.1.5/ mpfr
17) zcat mpc-1.0.3.tar.gz | tar -x
18) mv mpc-1.0.3/ mpc
19) mkdir build
20) cd build
21) ./configure --prefix=/tmp/delme.gast/install/ --disable-werror
--enable-languages=c,c++ --disable-multilib
(wenn der gcc auch 32Bit können soll - dann "--disable-multilib"
weglassen)
22) make -j<AnzahlDerCPUKerne> <-- das dauert ne Weile ?
23) make install
24) export PATH="/tmp/install/bin/:${PATH}:/tmp/install/bin/"
25) gcc --version
gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
Dies ist freie Software; die Kopierbedingungen stehen in den Quellen. Es
gibt KEINE Garantie; auch nicht für MARKTGÄNGIGKEIT oder FÜR SPEZIELLE
ZWECKE.
26) cd ..
27) xzcat gcc-7_2_0-retpoline-20180107.tar.xz | tar -x
28) cat ./gcc-7_2_0-retpoline-20180107/*.patch | patch -Np1
29) cat gcc_spectre_v1_rev2.patch | patch -Np1
30) cd build
31) make -j<AnzahlDerCPUKerne>
32) make install
-fertig ist der neue Compiler, jetzt nocheinmal komplett übersetzten um
alle c-libs anzupassen...
Stephan B. schrieb:> zumindest ich will aber erstmal wieder etwas sichereres haben...
Ist ein Patch auf der Ebene denn überhaupt sinnvoll?
Es handelt sich ja nicht um einen Silicon-Bug (in dem Sinne, dass
falscher Code generiert wird wie z.B. beim FDIV). Sondern er
ermöglicht, abhängig vom OS, Speicherbereiche zu "lesen", die man
eigentlich nicht lesen dürfen sollte.
> With this patch performance might drop by more than 75% !!
:-)
So ein Patch nimmt einem also nur die Möglichkeit, selbst einen solchen
Angriff zu starten — den mal als "good boy" natürlich niemals machen
würde. Und als "bad boy" kann man (Inline) Assembler o.ä. verwenden.
> ...natürlich stehen auch entsprechende Kernelpatches an...
Auf den GCC Mailing-Listen werden auch Patches diskutiert, aber vor
allem auch Built-ins, die zur Unterstützung in OS-Code, VMs etc. gezielt
eingesetzt werden können.
https://gcc.gnu.org/ml/gcc/2018-01/msg00029.html> Ich habe noch einige bedingte Maschinenbefehle an spekulativer> Ausführung blockieren lassen.
Müssen da nicht auch die Instruktionslängen angepasst werden?
> Die Patche sind alle auf den aktuellen gcc 7.2 anzuwenden:> https://ftp.gnu.org/gnu/gcc/gcc-7.2.0/gcc-7.2.0.tar.xz>> Zum Compilieren vom gcc werden 3 weitere externe Pakete gebraucht:> https://ftp.gnu.org/gnu/gmp/gmp-6.1.2.tar.xz> http://www.mpfr.org/mpfr-3.1.5/mpfr-3.1.5.tar.xz> https://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
Meist will man auch ISL. Am einfachsten bekommt man diese Libs in der
richtigen Version, unabhängig von evtl. vorhandenen Host-Versionen per
in-tree Build mit
1
./contrib/download_prerequisites
> Ausserdem muss zuvor eine moderne binutils gebaut werden:> https://ftp.gnu.org/gnu/binutils/binutils-2.29.tar.xz>> Bitte beachtet, das ihr zuerst einen morderneren gcc benötigt, um mein> installiertes Patch compilieren zu können. (Die meisten Distributionen> liefern ggc 4.9 aus: gcc --version)> Am besten erstmal den 7.2 ohne Patches bauen und in einen Ordner eurer> Wahl installieren lassen.
Huh? Das macht ein Bootstrap doch automatisch?
> Bauanleitung nach /tmp/install> [...]> 11) xzcat gcc-7.2.0.tar.xz | tar -x> 12) cd gcc-7.2.0> 13) xzcat gmp-6.1.2.tar.xz | tar -x> 14) mv gmp-6.1.2/ gmp> 15) xzcat mpfr-3.1.5.tar.xz | tar -x> 16) mv mpfr-3.1.5/ mpfr> 17) zcat mpc-1.0.3.tar.gz | tar -x> 18) mv mpc-1.0.3/ mpc
./contrib/download_prerequisites ist hier der empfohlene Weg
> 19) mkdir build> 20) cd build> 21) ./configure --prefix=/tmp/delme.gast/install/ --disable-werror> --enable-languages=c,c++ --disable-multilib
configure innerhalb des Source-Tree wird von GCC nicht unterstützt.
Evtl. beruhen deine Probleme beim Generieren darauf? Jedenfalls würde
ich von nicht-unterstützten Konfigurationen absehen: wozu möglichen
Ärger wenn man ihne einfach ausschließen kann...
> 24) export PATH="/tmp/install/bin/:${PATH}:/tmp/install/bin/"
Wozu 2× /tmp/install/bin/?
Hallo Johann L., schön das jemand antwortet.
Johann L. schrieb:> Stephan B. schrieb:>> zumindest ich will aber erstmal wieder etwas sichereres haben...>> Ist ein Patch auf der Ebene denn überhaupt sinnvoll?> [...]
Ich habe das original "Spectre"-paper so verstanden, das für eine
halbwegs abdeckende Mitigation des Szenarios "conditional branch
misprediction" (Spectre V1) auch alle Software im Userspace neu
übersetzt werden muss.
Seite 11, Kapitel 7 Abs.2 "The problem of inserting speculative
execution blocking [...]" ist sogar recht spezifisch darüber
("[...]Insertion in security-critical routines alone is not sufficient,
[...]").
Da es dafür IMHO an compiler patches mangelt, habe ich mal den "Hammer"
angesetzt.
> So ein Patch nimmt einem also nur die Möglichkeit, selbst einen solchen> Angriff zu starten — den mal als "good boy" natürlich niemals machen> würde. Und als "bad boy" kann man (Inline) Assembler o.ä. verwenden.
Nein, ich denke das ist anders zu verstehen.
Spectre V1 benötigt sog. "gadjets" im -->Fremdcode<-- im Fremdcontext
zum exploiten.
Wenn ein Angreifer also sich selbst in ASM implementiert (oder anders
übersetzt) nützt ihm das wohl nichts.
> Auf den GCC Mailing-Listen werden auch Patches diskutiert, aber vor> allem auch Built-ins, die zur Unterstützung in OS-Code, VMs etc. gezielt> eingesetzt werden können.
eben.
Gibt es schon irgendwo ein Wort darüber was mit dem restl. Userspace
ist? Vielleicht hat das paper ja unrecht oder übertreibt? (Oder ich was
falsch verstanden?)
Aber auch Intel spricht in seinem Whitepaper von "For the bounds check
bypass method, Intel’s mitigation strategy is focused on software
modifications. [...]"
> Müssen da nicht auch die Instruktionslängen angepasst werden?
Das ist eine hervorragende Frage: Ich bin nicht sicher. Hast du eine
Empfehlung?
Der gcc soll das lfence eigentlich nicht mit dem Sprung assoziieren.
Ich nutze nur die Ausgabe um es per huckepack mit in den ASM Code
einzufügen.
Bisher scheint alles übersetzte auch gleichermassen zu funktionieren.
(Auch Kernel...)
> [...]>
1
./contrib/download_prerequisites
> [...]> Huh? Das macht ein Bootstrap doch automatisch?
OK - ich hatte mich an LFS orientiert.
funktioniert aber auch so.
>> 19) mkdir build>> 20) cd build>> 21) ./configure --prefix=/tmp/delme.gast/install/ --disable-werror>> --enable-languages=c,c++ --disable-multilib>> configure innerhalb des Source-Tree wird von GCC nicht unterstützt.> Evtl. beruhen deine Probleme beim Generieren darauf? Jedenfalls würde> ich von nicht-unterstützten Konfigurationen absehen: wozu möglichen> Ärger wenn man ihne einfach ausschließen kann...
Vor dem configure fehlt ein Punkt: "../configure [...]"
Sorry Tippfehler.
Danke für deine Anmerkungen und sorry für meine gcc-Unsicherheit.
Normalerweise mach ich weniger am gcc rum - und nur jetzt gerade aus der
Not heraus.
MfG Stephan
Stephan B. schrieb:> Hallo Johann L., schön das jemand antwortet.>> Johann L. schrieb:>> Stephan B. schrieb:>>> zumindest ich will aber erstmal wieder etwas sichereres haben...>>>> Ist ein Patch auf der Ebene denn überhaupt sinnvoll?>> [...]>> Ich habe das original "Spectre"-paper so verstanden, das für eine> halbwegs abdeckende Mitigation des Szenarios "conditional branch> misprediction" (Spectre V1) auch alle Software im Userspace neu> übersetzt werden muss.> Seite 11, Kapitel 7 Abs.2 "The problem of inserting speculative> execution blocking [...]" ist sogar recht spezifisch darüber> ("[...]Insertion in security-critical routines alone is not sufficient,> [...]").>> Da es dafür IMHO an compiler patches mangelt, habe ich mal den "Hammer"> angesetzt.
Scheint dann doch etwas aufwändiger zu sein:
https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00422.html
An Patches mangelt es also nicht.
> Aber auch Intel spricht in seinem Whitepaper von "For the bounds> check bypass method, Intel’s mitigation strategy is focused on> software modifications. [...]"
Ja klar, einen Silicon-Bug behebt man durch Software oder durch anderes
Silizium. Letzteres scheidet zumindest kurzfristig aus, und selbst
langfristig wird noch ältere Hardware im Einsatz bleiben — auch weil
das Problem softwareseitig behebbar ist (sieht zumindest momentan danach
aus, auch wenn die Mühlen dann langsamer mahlen).
>> Müssen da nicht auch die Instruktionslängen angepasst werden?>> Das ist eine hervorragende Frage: Ich bin nicht sicher. Hast du eine> Empfehlung?
Mit x86 kenn ich mich nicht soweit aus. Bei den meisten Targets gibt es
falschen Code wenn Instruktionslängen zu klein sind, weil relative
Sprünge nicht mehr passen. Momentan kenn ich auch kein offizielles
Target, das zu kurze Sprünge Relaxen kann, z.B. durch jumpity-jump, was
aber erfordert, dass Assembler oder Linker im Code reinfutscheln.
> Der gcc soll das lfence eigentlich nicht mit dem Sprung assoziieren.
Genau das hast du aber getan :-)
> Ich nutze nur die Ausgabe um es per huckepack mit in den ASM Code> einzufügen.
Der gcc weiß von dem lfence ja nix; es gehört zum asm-String der in
final ausgegeben wird. Und die ausgegebene Instruktion hat eine
bestimmte (maximal-)Länge, die nun nicht mehr stimmt.
> Bisher scheint alles übersetzte auch gleichermassen zu funktionieren.
Ja größer die von der ISA unterstützten Offsets sind, desto seltener
wird man das Probhlem sehen. Es tritt ja nur an der Grenze der
Gültigkeit auf, und die Wahrscheinlichkeit für eine bestimmte Sprungläge
fällt grob exponentiell mit der Weite.
Hier ein Beispiel für so einen Bug in Aktion (nicht für x86):
https://gcc.gnu.org/PR72767
Es kracht nur bei bestimmten Sprungweiten, siehe Testfall am PR.
>> configure innerhalb des Source-Tree wird von GCC nicht unterstützt.>> Evtl. beruhen deine Probleme beim Generieren darauf? Jedenfalls würde>> ich von nicht-unterstützten Konfigurationen absehen: wozu möglichen>> Ärger wenn man ihne einfach ausschließen kann...>> Vor dem configure fehlt ein Punkt: "../configure [...]"
"First, we highly recommend that GCC be built into a separate
directory from the sources which does not reside within the
source tree. [...] building where objdir is a subdirectory
of srcdir is unsupported."
https://gcc.gnu.org/install/configure.html
Johann L. schrieb:> Scheint dann doch etwas aufwändiger zu sein:>> https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00422.html>> An Patches mangelt es also nicht.
Das sind nur die retpoline patches (siehe allererste Datei im ersten
Post) gegen Spectre Variante 2.
Steht auch in der longmsg drin:
>This set of patches for GCC 8 mitigates variant #2 of the speculative execution
vulnerabilities on x86 processors identified by CVE-2017-5715, aka Spectre.
>They convert indirect branches to call and return thunks to avoid speculative
execution via indirect call and jmp.
Mir ist nichts bekannt das derzeit etwas gegen Variante 1 unternommen
wird?
Johann L. schrieb:> Mit x86 kenn ich mich nicht soweit aus. Bei den meisten Targets gibt es> falschen Code wenn Instruktionslängen zu klein sind, weil relative> Sprünge nicht mehr passen. Momentan kenn ich auch kein offizielles> Target, das zu kurze Sprünge Relaxen kann, z.B. durch jumpity-jump, was> aber erfordert, dass Assembler oder Linker im Code reinfutscheln.>>> Der gcc soll das lfence eigentlich nicht mit dem Sprung assoziieren.>> Genau das hast du aber getan :-)
Sollte der lfence Inject tatsächlich für paranoide Menschen notwendig
sein,
muss man vermutlich alle bedingten Opcodes per "define_insn_and_split"
definieren. Dann kann man sich den Hack dann sparen.
Johann L. schrieb:> https://gcc.gnu.org/install/configure.html
OK, zur Kenntniss genommen. Danke für den Link.
Scheinbar handhabt es LFS dann "unsupported":
http://www.linuxfromscratch.org/lfs/view/stable/chapter05/gcc-pass1.html
MfG Stephan
Ich finde es schon merkwürdig, dass du diesen Patch hier auf
Mikrocontroller.net und nicht auf einer gcc-Liste präsentierst.
Warum sollte ich meinen GCC und mein System mit einem windigen Patch aus
irgendeinem Forum compilieren?
Ma W. schrieb:> Warum sollte ich meinen GCC und mein System mit einem windigen Patch aus> irgendeinem Forum compilieren?
Brauchst du nicht und sollst du nicht.
Ich bin nicht sicher ob das einem Post in den gcc-Mailinglisten bereits
wert ist - zumal die Leute dort erstmal allerhand anderes zu tun haben.
Hatte mir wohl mehr Feedback und Diskussion erhofft - nicht das nur alle
darauf warten mit Patches bedient zu werden?
Schönen Abend noch.
Stephan B. schrieb:> Ich bin nicht sicher ob das einem Post in den gcc-Mailinglisten bereits> wert ist - zumal die Leute dort erstmal allerhand anderes zu tun haben.>> Hatte mir wohl mehr Feedback und Diskussion erhofft
Genau dieses Feedback und Diskussion wirst du aber — wenn überhaupt —
genau dort finden; dort sind die Leute, die sich mit GCC auskennen, und
in diesem Fall mit dem i386-Backend und der entsprechenden Harware bis
in die kleinsten Details vertraut sind.
Sich in gcc-patches anzumelden (wo momentan über Änderungen diskutiert
wird) ist also nicht die schlechteste Idee, und es kostet nur einen
Click.
https://gcc.gnu.org/lists.html#subscribe
Momentan ist das Thema ja on-topic und wird heiß diskutiert. Wenn du
eine Frage zum aktuellen Patch o.ä. hast dann wird man bestimmt
bereitwillig Auskunft geben; was aber bedingt dass man auch nachfragt
:-)
Johann L. schrieb:> Stephan B. schrieb:>> With this patch performance might drop by more than 75% !!>> :-)
Klingt nach nem ziemlichen Killer, sofern man nicht den Spezialfall von
einem Rechner hat, der ausschließlich für Anwendungen mit sehr niedrigen
Anforderungen an die Performance, aber hohen an die Sicherheit dient.
Ist ja auch kein Wunder, denn viele memory barriers einzufüen killt ja
jede Performance.