Google'ın Paul Turner tarafından yazılan yorumlarda sgbj tarafından bahsedilen makale , aşağıdakileri çok daha ayrıntılı olarak açıklıyor, ancak bir şans vereceğim:
Bunu şu anda sınırlı bilgilerden bir araya getirebildiğim kadarıyla, bir retpoline, CPU'nun dolaylı bir atlama hedefi üzerinde spekülasyon yapmasını önlemek için asla yürütülmeyen sonsuz bir döngü kullanan bir dönüş trambolindir .
Temel yaklaşım Andi Klein'ın bu konuyu ele alan çekirdek dalında görülebilir :
__x86.indirect_thunk
Hafıza adresi (arayacağım ADDR
) yığının üstünde saklanan çağrı hedefini yükleyen ve bir RET
talimat kullanarak atlamayı yürüten yeni çağrıyı tanıtır . Daha sonra thunk'ın kendisi, birçok (hepsi değilse de) dolaylı çağrı ve atlamaların yerini almak için kullanılan NOSPEC_JMP / CALL makrosu kullanılarak çağrılır . Makro, çağrı hedefini yığına yerleştirir ve gerekirse dönüş adresini doğru şekilde ayarlar (doğrusal olmayan kontrol akışına dikkat edin):
.macro NOSPEC_CALL target
jmp 1221f /* jumps to the end of the macro */
1222:
push \target /* pushes ADDR to the stack */
jmp __x86.indirect_thunk /* executes the indirect jump */
1221:
call 1222b /* pushes the return address to the stack */
.endm
call
Sonuna yerleştirilmesi , dolaylı çağrı bittiğinde, kontrol akışının NOSPEC_CALL
makronun kullanımının arkasında devam etmesi için gereklidir, böylece düzenli bir şekilde kullanılabilircall
Thunk'ın kendisi şöyle görünüyor:
call retpoline_call_target
2:
lfence /* stop speculation */
jmp 2b
retpoline_call_target:
lea 8(%rsp), %rsp
ret
Kontrol akışı burada biraz kafa karıştırıcı olabilir, bu yüzden açıklığa kavuşturalım:
call
geçerli talimat işaretçisini (etiket 2) yığına iter.
lea
yığın işaretçisine 8 ekler , son dönüş adresi (etiket 2'ye) en son itilen dört kelimeyi etkili bir şekilde atar. Bundan sonra, yığının üst kısmı gerçek ADDR adresini tekrar gösterir.
ret
*ADDR
yığın işaretçisini arama yığınının başına atlar ve sıfırlar.
Sonuçta, tüm bu davranış pratik olarak doğrudan zıplamaya eşdeğerdir *ADDR
. Elde ettiğimiz bir fayda, call
talimatı yürütürken iade ifadeleri (Dönüş Yığını Tamponu, RSB) için kullanılan dal tahmin edicisinin karşılık gelen ret
ifadenin etikete 2 atlayacağını varsaymasıdır .
Etiket 2'den sonraki kısım aslında asla yürütülmez, teorik olarak talimat boru hattını talimatlarla dolduracak sonsuz bir döngüdür JMP
. Kullanarak LFENCE
, PAUSE
ya da daha genel bir talimat talimat boru hattı durak olmasını neden bu spekülatif yürütme herhangi bir güç ve zaman israf gelen CPU durur. Bunun nedeni, retpoline_call_target çağrısının normal şekilde dönmesi LFENCE
durumunda, yürütülecek bir sonraki yönerge olmasıdır. Şube öngörücüsünün orijinal dönüş adresine (etiket 2) dayalı olarak tahmin edeceği de budur.
Intel'in mimari kılavuzundan alıntı yapmak için:
Bir LFENCE'ı izleyen talimatlar, LFENCE'tan önce bellekten getirilebilir, ancak LFENCE tamamlanana kadar yürütülmezler.
Ancak belirtim asla LFENCE ve PAUSE boru hattının durmasına neden olduğundan bahsetmez, bu yüzden buradaki satırlar arasında biraz okuyorum.
Şimdi orijinal sorunuza geri dönün: İki fikrin birleşimi nedeniyle çekirdek bellek bilgilerinin açıklanması mümkündür:
Her ne kadar spekülatif yürütme spekülasyon yanlışken yan etkisiz olsa da spekülatif yürütme hala önbellek hiyerarşisini etkiler . Bu, bir bellek yükü spekülatif olarak yürütüldüğünde, yine de bir önbellek hattının çıkmasına neden olmuş olabileceği anlamına gelir. Önbellek hiyerarşisindeki bu değişiklik, aynı önbellek kümesine eşlenen belleğe erişim süresini dikkatlice ölçerek belirlenebilir.
Okunan belleğin kaynak adresinin kendisi çekirdek belleğinden okunduğunda, bazı rastgele bellek parçalarını bile sızdırabilirsiniz.
Intel CPU'ların dolaylı dal tahmincisi, kaynak komutunun yalnızca en alt 12 bitini kullanır, bu nedenle tüm 2 ^ 12 olası tahmin geçmişini kullanıcı tarafından kontrol edilen bellek adresleriyle zehirlemek kolaydır. Bunlar daha sonra, çekirdek içinde dolaylı sıçrama tahmin edildiğinde, spekülatif olarak çekirdek ayrıcalıklarıyla yürütülebilir. Önbellek zamanlaması yan kanalını kullanarak, rasgele çekirdek belleğini sızdırabilirsiniz.
GÜNCELLEME: Çekirdek posta listesinde , Retpolin'lerin Dönüş Yığını Tamponu (RSB) boş olduğunda, daha yeni Intel mimarileri (Skylake +) geri düştüğü gibi, şube tahmin sorunlarını tamamen azaltmadığına inanmamı sağlayan sürekli bir tartışma var. savunmasız Şube Hedef Tamponuna (BTB):
Bir azaltma stratejisi olarak retpoline, bir saldırgan tarafından zehirlenebileceğinden BTB'den gelen tahminleri kullanmaktan kaçınmak için dolaylı şubeleri geri dönüşler için değiştirir. Skylake + ile ilgili sorun, bir RSB alt akışının, saldırganın spekülasyonun kontrolünü ele geçirmesine izin veren bir BTB tahmini kullanmaya geri dönmesidir.