Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Spectre/Meltdownとその派生

406 views

Published on

SCAIS 2019
(Small-workshop on Communications between Academia and Industry for Security)
https://researchmap.jp/sug/SCAIS2019/
の発表資料

Published in: Software
  • Be the first to comment

Spectre/Meltdownとその派生

  1. 1. Spectre/Meltdownとその派生 SCAIS2019 2019/1/21 光成滋生(サイボウズ・ラボ)
  2. 2. • x64の命令実行・メモリアクセスの仕組み • Meltdown/Spectreの概要 • ソフトウェア・CPUでの対策 • 宣伝 SCIS2019 • 2A2-4 準同型暗号の平文空間を制限する コンパクトなゼロ知識証明 スライドの目的 2 / 32
  3. 3. • rax, rbx, rcx, ... ; レジスタ(64bit整数) • al, bl, cl, ... ; 8bit整数レジスタ • mov ; メモリとレジスタ間の値設定命令 • mov al, [addr] ; addrが指すメモリの値をalに読む • mov [addr], al ; alの値をaddrが指すメモリに書く • test x, y / je label • xとyを比較して等しい(jmp if equal)ならならジャンプ x64アセンブリ言語(以下asm) mov al, [mem] ; memから値をalに読み test al, 1 ; 1と比較して je Leq ; 等しいならLeqにjmp jmp .Lexit ; そうでなければLexitにjmp Leq: mov [user], al ; alの値をuserに書く ... Lexit: 3 / 32
  4. 4. • asm命令を複数のμ命令(μ-op)に分解 • 例:add [rcx], rax • load r1 ←[rcx] ; r1←r1 + rax ; store [rcx]←r1 (イメージ) • Out-of-order実行(OOO) • 依存関係を考慮しつつ複数のμ-opを複数のport上でOOO asm命令の処理 Intel Architectures Optimization Reference Manual 2.3 4 / 32
  5. 5. • μ-opの状態を管理するROB(reorder buffer) • ある命令に対する分解された全てのμ-opの処理が完了すると その結果が実際のCPUの状態に反映される • 実行中に例外や割り込みが発生すると結果は破棄される • その途中の命令を一時的命令と呼ぶ(ここだけの用語) 処理の完了 5 / 32
  6. 6. • メモリは遅い • DRAMに1回アクセスすると数十nsec • addは0.1nsecぐらい(0.3nsecに3回ぐらい可能) • キャッシュメモリ • 小容量だが高速(1nsec~)に読める補助メモリ • あるアドレスの値を読むと次回そのアドレスは (キャッシュにあれば)高速に読める • CPUに近い方からL1, L2, L3と階層構造 • できれば速いキャッシュメモリを使い回したい • 効率化のための様々な仕組み • シーケンシャルにメモリを読んでいれば 次読みそうな部分を先読みしておく メモリから値を読むまで 6 / 32
  7. 7. • 分岐やデータの読み書きは遅延する • その結果を予測したパスに沿って実行 • 予測が正解 • 事前計算結果を実際に反映 • 予測が不正解 • 事前計算結果を破棄して元の状態にロールバック • 処理が確定するまでの一時的命令の実行中の結果は CPUの状態に副作用をもたらしてはいけないはず • メモリキャッシュに副作用があった • もちろんCPUのレジスタやメモリの値は書き換わっていない 投機実行 7 / 32
  8. 8. • メモリの読み込み速度差を利用した攻撃 • clflush ; キャッシュの全レベルの内容を無効化 • テーブルのどこか一カ所をアクセスしてキャッシュに入れる • テーブルの各要素のメモリアクセス時間を調べる Flush+Reload x1 x2 x3 x4 x5 x6x0 テーブルx 空 キャッシュ 4番目 を読む x4 テーブルxを順次読みその速度を測定 アクセス 時間 index キャッシュに 入っている 4番目だけ速い clflush 8 / 32
  9. 9. • 一時的命令がメモリを読んだときの キャッシュの副作用を悪用 • secretを読む権限の無いアプリ • (try)一時命令がsecretを読みuserのメモリのraxをアクセス • (err)その後secretが読めないことが判明し例外発生で巻き戻し • (cache)しかしuserを読んだキャッシュはクリアされない • (probe)後でuserの領域で速く読めた場所(x)があれば secretの値はxだったと判明 • 4096倍するのは(probe)で先読み機構の影響をなくすため https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html Meltdownの基本アイデア mov rax, byte [secret]; secretから値を1byte読む shl rax, 12 ; 12bit左シフト(4096倍) mov rax, [user+rax] ; userのrax番目のメモリを読む 9 / 32
  10. 10. • 複数プロセスによる並列処理時の トランザクション処理(TX)をサポートする命令群 • TX開始(txbegin) - 実際の処理 - TX終了(txend)をatomicに行う • 途中で失敗すれば全て巻き戻されてabortしてやり直す • Meltdownではエラーは1回 • (try)のコードをTSXに行う • 例外発生でscretの値が判明してabortするので再度tryできる • secretをずらしながら何度も(try)可能 TSX (transactional synchronization extensions) 10 / 32
  11. 11. • 要件 • 不用意に他のプロセスのメモリ領域にアクセスできない • 仮想メモリ • プロセスごとに独立したメモリ空間を割り当てる • ページング方式 • 仮想メモリを固定長(4KiB)のページに分割 • ページテーブルで管理 • 各ページが実際の物理メモリのどこに位置するかの情報 • アクセス権などの付加情報 • メモリにアクセスするとき • プロセスがアクセスする仮想アドレスに対応する物理メモリ を決定してアクセス メモリの抽象化 11 / 32
  12. 12. • 多段のツリー構造を持ったページテーブルの参照 • メモリ空間(48bit=256TiB)を9+9+9+9+12 bitに分割 x64における参照方法 Intel Architectures Software Developer's Manual 4-20 Vol.3A 12 / 32
  13. 13. • 仮想アドレスから物理アドレスへの変換 • プロセスのCR3レジスタから PML4E(Page Map Level 4 Entry)を参照 • PML4EからPDPTE(Page Directory Pointer Table)を参照 • PDPTEからPDE(Page Directory)を参照 • PDEからPTE(Page Table)を参照 • PTEから物理アドレスを参照 • 補足 • 1ページ4KiBは数十~数百GBのメモリで扱うには小さすぎる • 1ページ2MiB(下位9+12bit), 1GiB(下位9+9+12bit)にする方式 • 段数が3段、2段に減る / テーブルに必要なメモリも減る 4段の参照 13 / 32
  14. 14. • 毎回このテーブル参照は遅すぎる • TLB • 変換結果をキャッシュして高速化するためのバッファ • 初回は通常のテーブル参照しそのアドレスを記録 • 次回からはそこを再利用 • プロセスが切り替わるとそのエントリは無効化される TLB(Translation Lookaside Buffer) 14 / 32
  15. 15. • 最近のCPUは沢山のコアを持っている • 複数のOSを起動しているVMMがいる(OSの仮想化) • VMM(virtual machine monitor) • ゲストOSで仮想アドレスから物理アドレスに変換しても それは本当の物理アドレスではない • 更にもう一度変換する必要がある • Intel VT(virtualization technology) • 仮想化支援技術 • EPT(extended page table) • 通常の4段の参照の後にEPTを参照する 物理アドレスの仮想化 15 / 32
  16. 16. • MPX (memory protection extension) ; Skylake • BND命令 • bnd0, ..., bnd3 ; チェック用レジスタ • 配列などのメモリ境界を設定し範囲をチェックする機構 • 範囲外なら#BR例外 • PK (protection keys) ; Skylake-SP(scalable processor) • ユーザ空間でページ単位の保護を行う • 従来はkernelにお願いして設定する(mprotect)しかない • 読み書きの設定 • PKRU ; 保護用レジスタ • rdpkru, wdpkru • 設定外のアクセスは#PF例外 Intelの特殊なメモリ保護機能 16 / 32
  17. 17. • 重要なコードや情報をenclave(隔離領域)に分離 • CPUのみ信頼 • enclaveはシステムと独立でOSからも読めない • EPC(enclave page cache) • 隔離領域ページキャッシュ • 物理メモリの一部がenclaveとして予約される • EPCM(EPC map)で管理 • 許可されていなければ例外が発生 • 同様の機構:SMM(system management mode) • OS起動前のBIOSでのみ利用可能 • 制限されたメモリアクセス SGX(software guard extensions) 17 / 32
  18. 18. • https://foreshadowattack.eu/ • Intel CPUのL1キャッシュの挙動 • SGXのenclaveなメモリがL1キャッシュにあり、そのマッピン グが破棄されたときに攻撃者がキャッシュ内容を解析できた • SMMやVMMの内容をL1キャッシュ経由で取得できる可能性 L1TF(L1 terminal fault) ; Foreshadow-(NG) Foreshadow-NG.pdf p.2 Figure 1 18 / 32
  19. 19. • 範囲チェックを超えた領域のアクセス • (trained)正常パスでコードを繰り返し実行させて CPUに分岐しないと予測させる • (try)範囲外のxで実行 • (err)一時命令がsecretを超えた別のメモリを参照 • (cache)しかしuserを読んだキャッシュはクリアされない • (probe)後でuserの領域で速く読めた場所(x)を探索 Spectreの基本アイデア if (x < secret.size()) { y = probe[secret[x] * 4096]; } 19 / 32
  20. 20. • 分岐系 • PHT(pattern history table), BHB(branch history buffer) • 分岐命令ごとに「分岐した・しなかった」の履歴を保持 • Intelでは20回程度 • BTB(branch target buffer) • 分岐命令ごとに分岐先アドレスを予測 • RSB(return stack buffer) • call命令のリターンアドレス(関数の呼出元)を予測 • メモリ系 • STLF(store to load forwarding) • memory disambiguation ; Intel SDM 2-34 • storeの後のloadを予測して先読み • x1 = a[0]; b[0] = y; x2 = a[0]; さまざまな予測機構 20 / 32
  21. 21. • A Systematic Evaluation of Transient Execution Attacks and Defenses, C.Canella, et.al., Nov. 2018 • https://arxiv.org/abs/1811.05441 • Spectre • アプリがアクセスできるデータに一時的命令が作用する • 一時的命令はアプリの通常フローで実行可能 • Meltdown • アプリがアクセスできないデータに一時的命令が作用する • 例外命令に続く一時的命令が例外命令のデータにアクセスで きる性質を利用する SpectreとMeltdownの網羅的論文 21 / 32
  22. 22. • same-address-space / cross-address-space • 攻撃者と犠牲者のアドレス空間が同じか否か • in-place / out-of-place • 同じ分岐アドレスか異なる分岐アドレスか • 予測表を小さくするためにハッシュ化して保持 • 異なる分岐先でも同じエントリを参照することがある メモリレイアウトによるSpectreの分類 A Systematic Evaluation... p.4 Figure 3 22 / 32
  23. 23. • ブラウザはJavaScriptを実行するVMを持っている • たくさんのユーザのプログラムを同一プロセスで動かす • Spectreで使える機能 • SharedArrayBuffer • 複数のワーカーでメモリを共有するための機能 • Performance.Now • 高性能タイマー • これらの機能が無効化・タイマーの精度をあえて下げた • Chrome(2018/8) • Site Isolation ; ドメインごとに別のプロセスで実行させる ブラウザへの影響 23 / 32
  24. 24. • 例外 • GP ; general protection • NM ; device-not-available ; FPUが無い • BR ; bound range exceeded exception ; メモリ保護拡張MPX • PF ; page fault • 許可タイプ • U/S ; user/supervisor • P ; present(そのページが存在する / swapされてない) • R/W ; • RSVD ; reserved • XD ; non executable • PK ; protection key 例外種別によるMeltdownの分類 24 / 32
  25. 25. • p.3 Figure 1 A Systematic Evaluation...による分類 25 / 32
  26. 26. • KPTI(kernel page table isolation) + invpcid • カーネル空間(Ks)とユーザ空間(Us)のページテーブルを分離 • 従来:Ksは常にマップされていた • Usから直接アクセス不可なので大丈夫と思っていた • 一般ユーザ権限から任意のメモリを読める可能性 • コンテナ貸しサービスで危険 • PCID(process contexst identifier) • プロセス識別タグ • 特定のプロセスのTLBを無効化 • カーネル実行時以外はKsを切り離す • pros. 見えないので安全 • cons. User⇔Kernel時にPT切り換え. 場合によってTLB無効化 ソフトによる対策 26 / 32
  27. 27. • 配列チェックのテクニック • 範囲を超えたindexは常に0になるのでSpectreが成功しない • 対策が必要な部分を全てこのようにしないといけない array_index_nospec array_index_nospec(size_t index, size_t size) { // maskはsize <= indexなら0そうでなければ-1 mask = int64_t(size - index) >> 63; // 範囲内ならindex そうでなければ0 return index & mask; } 27 / 32
  28. 28. • 間接分岐(call [eax])を使わないコードに変換 • 予測がかからないので遅くなる(悲しいジレンマ) retpoline retpoline(addr): call .L ; *** .T: ; callの次の命令が投機実行されても無限ループさせる pause lfence jmp .T .L: [stack] <- addr ret ; ***には戻らずaddrに戻る(=addrにジャンプする) 28 / 32
  29. 29. • 関数テーブルを使うコード • 通常はjmpテーブルを生成 コンパイラサポート int f(int x, int y) { static int (*const p[])(int) = { f0, f1, f2, f3, f4 // 関数ポインタテーブル }; return p[x](y); } movsxd rax, x mov rdx,<pointer to table> jmp QWORD PTR [rdx+rax*8] ; p[x] ... 29 / 32
  30. 30. • retpolineコードを生成する -mindirect-branch=thunk f: lea rdx,[rip+0x0] movsxd rax,edi mov edi,esi mov rax,QWORD PTR [rdx+rax*8] jmp __x86_indirect_thunk_rax __x86_indirect_thunk_rax: call c <__x86_indirect_thunk_rax+0xc> pause lfence jmp 5 <__x86_indirect_thunk_rax+0x5> mov QWORD PTR [rsp],rax ret 30 / 32
  31. 31. • IBRS(Indirect Branch Restricted Speculation) • 低い権限のモードでの間接分岐予測結果を 高い権限のモードが使わないようにする • Linux 4.19からretpolineの代わりにenhanced IBRSを利用 • STIBP(Single Thread Indirect Branch Predictors) • 一つの物理コアのある論理コアが 別の論理コアでの間接分岐予測を使わないようにする • IBPB(Indirect Branch Predictor Barrier) • バリアに続く間接分岐予測の影響を バリアの前の実行が影響を受けないようにする • プロセスやVMの切り替え時にBTBをフラッシュさせる CPUの改善による対策 31 / 32
  32. 32. • x86/x64最適化勉強会での発表 • 図解でわかるSpectreとMeltdown;@satoru_takeuchi • https://speakerdeck.com/sat/tu-jie-dewakaruspectretomeltdown • SpectreBustersあるいはLinuxにおけるSpectre対策;@mhiramat • https://www.slideshare.net/mhiramat/spectrebusterslinuxspectre • Software guidance for security advisories;Intel • https://software.intel.com/security-software-guidance/ • https://software.intel.com/security-software- guidance/insights/deep-dive-managed-runtime-speculative- execution-side-channel-mitigations • C++ Developer Guidance for Speculative Execution Side Channels;Microsoft • https://docs.microsoft.com/en-us/cpp/security/developer-guidance-speculative-execution 参考文献(スライド内以外) 32 / 32

×