Double-sided Rowhammer¶
Bir victim row'u (row N) kuşatan iki aggressor row'u (N-1 ve N+1) hammer'la; disturbance'ı row N üzerinde yoğunlaştırarak bit'lerini single-sided hammering'e göre çok daha hızlı ve güvenilir biçimde flip et.
Mechanism¶
Kurbanı kuşatmak neden işe yarar
Rowhammer bit flip'leri, bir aggressor row'un tekrar tekrar activation'ından doğar; bu da fiziksel olarak komşu row'lardan charge sızdırır. En çok etkilenen row, bir aggressor'a hemen bitişik olandır. Bir hedefin iki tarafına iki aggressor yerleştirebilirseniz — victim row N etrafında N-1 ve N+1 row'ları — o zaman row N aynı anda her iki komşusundan disturbance alır. Bu "double-sided" düzenleme, tek bir komşuyu uzak bir row'a karşı hammer'lamaya (single-sided / amplified hammering) göre daha fazla flip üretir ve bunları çok daha az activation ile üretir.
Püf noktası: aggressor'ları N-1 ve N+1'e yerleştirmek için hangi physical address'lerin aynı bank'in adjacent row'larına denk geldiğini bilmeniz gerekir — farklı row'lar (ki her access row'u yeniden activate etsin) ama aynı bank (ki tek bir row buffer üzerinde çekişsinler). Bu, DRAM bank/row addressing reverse-engineering ile elde edilen DRAM address mapping'ini gerektirir.
Hammering loop'unun kendisi CPU cache'ini yenmek zorundadır: cache'ten servis edilen
read'ler asla DRAM'e ulaşmaz, bu yüzden her access'in ardından gerçek bir row
activation'ı her iterasyonda zorlamak için clflush gelir (ya da bir eviction set /
non-temporal access kullanılır).
Walkthrough¶
1. The core hammer loop (Seaborn/Dullien). Aynı bank'in farklı row'larına işaret eden iki pointer, her biri önce read sonra flush edilerek, sıkı bir loop içinde:
code1a:
mov (X), %eax ; activate row containing X
mov (Y), %ebx ; activate row containing Y
clflush (X) ; evict so next read re-activates
clflush (Y)
jmp code1a
X ve Y aynı bank'te farklı row'lara map olmak zorundadır. Aynı row → row
buffer her iki read'i de re-activation olmadan servis eder; farklı bank'ler → tek
bir row'un sürekli hammering'i olmaz.
2. Make it double-sided. Bir aggressor artı uzak bir row yerine, X ve Y'yi
bir victim row'u çevreleyen row'lar olacak şekilde seçin. Project Zero, memory'yi
üç eşit region olarak düzenledi ve dıştaki ikisini hammer'ladı:
İki dıştaki read ortadaki victim'i kuşatır, dolayısıyla flip'ler victim region'ında yoğunlaşır.
Templating run (kavramsal çıktı)
Sadece virtual adjacency değil, DRAM mapping'ine ihtiyacınız var
Virtual olarak (ve hatta physical olarak) contiguous page'ler aynı bank'te
row-adjacent değildir — memory controller'ın bank/row hash'i onları dağıtır.
X ve Y'yi yalnızca physical-address aritmetiğiyle seçmek sessizce yanlış
row'ları veya farklı bank'leri hammer'lar ve hiç flip üretmez. Önce mapping'i
elde edin ya da same-bank adjacency'yi row-buffer conflict timing
ile doğrulayın.
clflush genellikle bunu mümkün kılan şeydir
Klasik loop, clflush'ın user space'ten erişilebilir olmasına bağlıdır. Bunun
kısıtlandığı yerlerde (ör. JavaScript, bkz. rowhammer.js) flush,
activation başına daha yavaş olan cache eviction set'leriyle değiştirilir.
Mitigation¶
- Target Row Refresh (TRR) ve in-DRAM tracker'lar, aggressor'lar over-activate edildiğinde olası victim'leri refresh eder (sonraki many-sided pattern'lerle bypass edilir; bkz. TRRespass, Blacksmith).
- ECC single-bit flip'leri düzeltir (ama multi-bit flip'ler ve ECC side effect'leri exploit edilebilir kalır).
- Artırılmış refresh rate (ör. 2x) charge leakage için pencereyi kısaltır.
References¶
- Mark Seaborn, Thomas Dullien. Exploiting the DRAM rowhammer bug to gain kernel privileges. Google Project Zero, 2015 — https://projectzero.google/2015/03/exploiting-dram-rowhammer-bug-to-gain.html
- Seaborn, Dullien. Exploiting the DRAM Rowhammer Bug to Gain Kernel Privileges. Black Hat USA 2015 — https://blackhat.com/docs/us-15/materials/us-15-Seaborn-Exploiting-The-DRAM-Rowhammer-Bug-To-Gain-Kernel-Privileges.pdf
- Row hammer the short summary. cyber.wtf, 2016 — https://cyber.wtf/2016/06/27/row-hammer-the-short-summary/