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.

SpectreBustersあるいはLinuxにおけるSpectre対策

4,383 views

Published on

SpectreV1/V2の説明と、Linuxカーネルにおける対策について

Published in: Software

SpectreBustersあるいはLinuxにおけるSpectre対策

  1. 1. あるいは LinuxにおけるSpectre対策 アクセラレーション・ブースト脆弱性災害対策室 (AB災対)勉強会 Feb. 17. 2018 Masami Hiramatsu <mhiramat@kernel.org> SP CTREBUSTERS
  2. 2. 自己紹介 - @mhiramat - Linaro Ltdというところで働いています - Linuxカーネルのトレーサ部分のメンテナなど - 普段はarm系を気に掛けている 2
  3. 3. 落ち着こう 現状、Spectre (Variant 1/2) は動作が解析され、緩和策が進んでいる。 - 根本対策はないが、緩和策はある - いくつかはコンパイラの修正を伴うので、ユーザバイナリを含めて必要なものは総入 れ替えになる覚悟が必要 - 修正は安定版カーネルに順次取り込まれているので4.4, 4.9, 4.14はなんとかなりそ う。(とは言え、大きな修正で今も不具合報告が上がっている) - ディストロカーネルも出来るだけ最新版を採用しよう。 - これはlivepatchでは修正できない。再起動は必須。 - 出来る限り最新版のGCCとLinuxに入れ替えよう。(まだ開発は続いている) - 一部問題についてはライブラリやアプリケーションでの対応が必要 3
  4. 4. はじめに ● 脆弱性の種類と、この資料の説明範囲 ● 基本的に武内さんの説明を理解した上で進める予定 ● 基本的に図解はない(厳しい) 4 コードネーム 別名 しくみ 対策 Spectre Variant 1: Bounds Check Bypass ✔ (おさらい) ✔ Variant 2: Branch Target Injection ✔ ✔ Meltdown Variant 3: Rogue data cache load
  5. 5. Agenda - Spectre (Variant1/2)とは - Variant 1 - Array_index_nospec - Variant 2 - Retpoline 5
  6. 6. Spectre(Variant 1/2)とは 投機的実行を利用して、通常であれば実行されない分岐の先の命令を実行させ、キャッ シュを利用したサイドチャネル攻撃によって情報を得られる脆弱性 簡単に言うと、分岐予測で先読みした足跡をキャッシュの状態から推測する攻撃 - メモリ書き換えはなく、読み取りのみ可能である 2つのVariant(変種・手法)が知られている - Variant 1 : Bounds check bypass - Variant 2 : Branch target injection 6
  7. 7. Branch Check Bypass 7
  8. 8. Variant 1: Bounds Check Bypass (おさらい) データ配列のインデックスの境界条件、チェックしてますか? してますよね? でも投機的実行は境界条件の分岐命令を越えて先に進みます。 8 if (x < array1_size) { idx = array1[x] * 256; y = array2[idx]; }
  9. 9. Bound Check Bypass + Cache Side Channel Attack untrasted_offset_from_callerに変な値が入っても、 ifブロックは投機的に実行されうる 9 struct array { unsigned long length; unsigned char data[]; }; struct array *arr1 = ...; /* small array */ struct array *arr2 = ...; /* array of size 0x400 */ /* >0x400 (OUT OF BOUNDS!) */ unsigned long untrusted_offset_from_caller = ...; if (untrusted_offset_from_caller < arr1->length) { unsigned char value = arr1->data[untrusted_offset_from_caller]; unsigned long index2 = ((value&1)*0x100)+0x200; if (index2 < arr2->length) { unsigned char value2 = arr2->data[index2]; } } (出典: Project Zero blog)
  10. 10. Bound Check Bypass + Cache Side Channel Attack untrasted_offset_from_callerに変な値が入っても、 ifブロックは投機的に実行されうる 10 struct array { unsigned long length; unsigned char data[]; }; struct array *arr1 = ...; /* small array */ struct array *arr2 = ...; /* array of size 0x400 */ /* >0x400 (OUT OF BOUNDS!) */ unsigned long untrusted_offset_from_caller = ...; if (untrusted_offset_from_caller < arr1->length) { unsigned char value = arr1->data[untrusted_offset_from_caller]; unsigned long index2 = ((value&1)*0x100)+0x200; if (index2 < arr2->length) { unsigned char value2 = arr2->data[index2]; } } まずこのif文をパスするように安全な値で 繰り返し 呼び出しを行う (BHBの学習:後述) 攻撃時にはarr1をキャッシュから外す (時間稼ぎ) 攻撃前に読みたいデータがキャッシュ に乗るような操作を行う(別の場所で)
  11. 11. Bound Check Bypass + Cache Side Channel Attack untrasted_offset_from_callerに変な値が入っても、 ifブロックは投機的に実行されうる 11 struct array { unsigned long length; unsigned char data[]; }; struct array *arr1 = ...; /* small array */ struct array *arr2 = ...; /* array of size 0x400 */ /* >0x400 (OUT OF BOUNDS!) */ unsigned long untrusted_offset_from_caller = ...; if (untrusted_offset_from_caller < arr1->length) { unsigned char value = arr1->data[untrusted_offset_from_caller]; unsigned long index2 = ((value&1)*0x100)+0x200; if (index2 < arr2->length) { unsigned char value2 = arr2->data[index2]; } } lengthがキャッシュにない場合 メモリアクセスに時間がかかる →投機的によくあるケースの場合 の処理をしてみよう おっ、このデータはキャッ シュにあるぞ! 先に進もう これもよくOKになるぞ。先に進もう arr2をプリフェッチしよう えっ、最初のifがダメだった?じゃあ実行結果を破棄しよう CPU CPU CPU
  12. 12. Bound Check Bypass + Cache Side Channel Attack untrasted_offset_from_callerに変な値が入っても、 ifブロックは投機的に実行されうる 12 struct array { unsigned long length; unsigned char data[]; }; struct array *arr1 = ...; /* small array */ struct array *arr2 = ...; /* array of size 0x400 */ /* >0x400 (OUT OF BOUNDS!) */ unsigned long untrusted_offset_from_caller = ...; if (untrusted_offset_from_caller < arr1->length) { unsigned char value = arr1->data[untrusted_offset_from_caller]; unsigned long index2 = ((value&1)*0x100)+0x200; if (index2 < arr2->length) { unsigned char value2 = arr2->data[index2]; } } しかしvalueに対応するarr2の「場所」のエ ントリはキャッシュにロード済み Arr2のエントリに片っ端からアクセスし て速度を確かめるぞ!
  13. 13. Variant 1の緩和策:Array_index_nospec Variant1は「配列のインデックスのチェック」を「if文」つまり「テスト命令と分岐命令」で行 うことによって起きる問題点である 緩和策は2通りある - 「配列のアドレスにインデックスから生成したマスクをする」命令を付け加える(分岐 命令ではないのでマスクが常に実行される)→array_index_nospec - 「配列のインデックスチェック時に分岐予測をブロックする」 →ifence (ArmのCSDB命令など) 13
  14. 14. Array_index_nospec インデックスの確認を分岐なしに行えば、分岐予測でBypassする対象がなくなる - array_index_nospec(index, size) インデックスとサイズを渡しインデックスをサニタイズする(index>sizeなら0が帰る) - 演算だけを使っており、分岐命令は一切使わない - アーキ毎にマスク生成ルーチンをアセンブラで記述する(コンパイラが生成する命 令によっては内部で分岐扱いになるため) 分岐命令がないので投機的実行が境界値を取りこぼす可能性がない 14
  15. 15. Array_index_nospecの実装 インデックスとサイズとの差をビットORして反転し、算術シフトで最上位ビットの結果だけ で埋める (sz <= idxで0x0、それ以外は0xffffffffffffffff) (肝の部分だけ) マスクをインデックスに適用して取り出す static inline unsigned long array_index_mask_nospec(unsigned long idx, unsigned long sz) { return ~(long)(idx | (sz - 1UL - idx)) >> (BITS_PER_LONG - 1); } #define array_index_nospec(index, size) ({ typeof(index) _i = (index); typeof(size) _s = (size); unsigned long _mask = array_index_mask_nospec(_i, _s); _i &= _mask; _i; }) 15
  16. 16. Array_index_mask_nospecのx86実装 array_index_mask_nospecはx86では以下の機械語命令で実装 インデックスが配列サイズより溢れているかどうかを、 分岐ではなく0になるマスクで判別する array_index_nospec内部で%maskを適用し、idxが不正な値なら0が返るようにする →index=0なので分岐予測が外れても不正アクセスできない (最初の値にアクセス) cmp %sz, %idx // %idx +(-%sz) の結果、carry bitが発生すればCF=1にする // %idx < %sz であれば、carryが発生する(CF=1) // %idx >= %sz であれば、carryが発生しない (CF=0) // %idx < 0の場合、unsignedになるのでLONGMAXより大きい値として扱われる sbb %mask, %mask  // %mask -= (%mask + CF), CF=1なら-1, CF=0なら0になる 16
  17. 17. Array_index_nospec適用後 untrasted_offset_from_callerに変な値が入っても、 ifブロック内部でサニタイズされる 17 struct array *arr1 = ...; /* small array */ struct array *arr2 = ...; /* array of size 0x400 */ /* >0x400 (OUT OF BOUNDS!) */ unsigned long untrusted_offset_from_caller = ...; if (untrusted_offset_from_caller < arr1->length) { untrusted_offset_from_caller = array_index_nospec(untrusted_offset_from_caller, arr1->length); unsigned char value = arr1->data[untrusted_offset_from_caller]; unsigned long index2 = ((value&1)*0x100)+0x200; if (index2 < arr2->length) { unsigned char value2 = arr2->data[index2]; } } lengthがキャッシュにない場合 メモリアクセスに時間がかかる →投機的によくあるケースの場合 の処理をしてみよう 内部の演算の依存があるから lengthのロードを待とう 上記演算の結果0になるvalue = arr1->data[0] CPU CPU
  18. 18. 重要:Array_index_nospecの限界 Array_index_nospecには限界がある - array_index_nospecを使うコードは安全 - array_index_nospecを使わないコードは危険かも - コンパイラでは判断が難しい 各開発者が使い方を理解した上で、必要な処理をarray_index_nospecを利用するよ うに書き換える必要がある - Documentation/speculation.txt を参照する 18
  19. 19. Variant1の危険性は? 渡されたインデックス1を使って配列1の内容を元にインデックス2を作り配列2にアクセ スするコードが悪用される→そんなのめったに無いよ - Project Zeroの実証コードではLinux内部のBPFインタプリタを使って「ガジェット コード」を生成していた - 古いカーネルではBPFを無効化するのが有効とされている - 新しいカーネルでは、非特権ユーザが作ったBPFコードが配列にアクセスする際 に、常にインデックスにビットマスクを掛けるようにしている 19
  20. 20. 与太話: ifenceはどうなった? Variant1対策にはifence(mfenceもしくはlfenceになる)を利用する実装もあった - 分岐命令は使うが、ポインタのロード時にlfence/mfenceを使うことで待ち合わせを行 う - arm/arm64では新規にCSDB(conditional speculation barrier)命令を CSEL(conditional select)命令と組み合わせて使うことでfence命令相当にする →待ち合わせ命令はコストがかかりすぎるのでボツになった →arm64でも、array_index_mask_nospec()を最適化(cmp + sbc) (ただし実際の適用はしてない?) Arm社のオフィシャルな方式としてはCSDB命令を使った実装なんだけど・・・。 20
  21. 21. Branch Target Injection 21
  22. 22. Variant 2: Branch Target Injection 投機的実行とBTB(分岐先バッファ)と間接分岐命令を利用した攻撃 間接分岐命令とは? - 分岐先がレジスタやメモリの値によって指定される命令 - x86ではcallとjmpの両方に間接分岐命令がある。 間接分岐先は事前の命令が実行された後に決まる(fops->read()など) - 分岐先を決めるために待ち合わせが必要(メモリロードが絡むと遅い) →待機時間が無駄になるので先に進めたい →投機的実行 - 分岐先がわからないのに実行できるの?→BTB 22
  23. 23. BTB: Branch Target Buffer 分岐先を分岐元アドレスで保存するバッファ - 分岐元アドレスを下位31ビットだけのキーで保存し、分岐先についても分岐元の上 位32ビットで補完する。 - 例えば 0xBEEF.1234 が分岐先(ターゲット)とされていて、 0xDEAD.CAFE.1234から分岐する場 合、分岐先は0xDEAD.BEEF.1234となる - 31ビットは長すぎるので、30ビットから14ビットまでの16ビットは、8ビットずつペアに してXORされる - 例えば 0x100.0000 と 0x180.8000 は同じ値として認識される(両方の 8がXORで0になる) - 異なる分岐元なのに同じエントリになるエイリアスが出来る - 例 0xBEEF.CAFE.1234 と 0xDEAD.FACE.3234 は同じキーになる 23
  24. 24. BTB (Project Zeroの観測に基づく) 1エントリ6つの情報で出来ている(64ビット) 24 Source Target a b c d e f 1 1 01010101 10101.01010101 1 01010101.01010101.01010101.01010101 a: (e)が1だった場合に、ソースの上位 32ビットの値をインクリメントして適用するかどうか b: 分岐元アドレスの31ビット目 c: 分岐元アドレスの30ビット目から14ビット目までを8ビットずつXORした値 d: 分岐元アドレスの13ビット目から1ビット目までの値 e: 32ビット境界を超えて分岐するかどうか(上位 32ビットが変わるかどうか ) f: 分岐先アドレスの下位 32ビット ※bitの並びは素直にProject Zeroの説明から起こした。多分 e a b c d f の順で並んでる気がする
  25. 25. BHB: Branch History Buffer 過去の分岐予測結果の当たり外れを記録するバッファ - ややこしいビット演算によって過去29回分の「当たった」分岐パターンを58ビットに エンコード - 現在の分岐パターンを BHBに見つけると、分岐先をBTBに探しに行く - IRET以外の分岐パターンを記録する - 詳しくはProject ZeroのBlogを参照(実験では26回分は記録しているとされた) - 分岐パターンは命令アドレスの下位20ビットを使って更新される 25
  26. 26. Branch Target Injection BTBのエイリアスエントリを悪用する - 1. ユーザ空間でBTBとBHBを「学習」させる - 対象となる間接分岐にたどり着く分岐パターンを再現( BHBの学習のため29回分は再現する) - 何度もパターンを辿って学習させる ( IRET でループ →BHBに同じパターンが残る ) - 2. カーネル空間や別のスレッドで、そのBTBを使って「推論」する  (カーネル空間でBTBのエイリアスエントリを参照) - 3. 狙ったコードが投機的に実行される 実行結果は破棄されるが、キャッシュアクセスは行われる→サイドチャネル攻撃 26
  27. 27. Variant2の緩和策:Retpoline Variant2は投機的な「間接分岐命令」の飛び先をBTBの誤学習によって操作されてしま う問題点である よって緩和策は間接分岐命令を使わないことである 間接分岐命令ではなく、間接的に分岐したい→そうだROPがあるじゃないか 27
  28. 28. ROP:Return Oriented Programming リターンアドレスを改変し、callやjmpなしにコード断片を連続的に実行する攻撃手法 - x86ではスタックの先頭を変更するだけでret命令の戻り先を変更できる 28 push CCC push BBB push AAA <- stackに移動先をプログラム ... ret -> stackから飛び先を読み取ってジャンプ ... AAA: ... ret -> stackから飛び先を読み取ってジャンプ ... BBB: ... ret
  29. 29. Retpolineの実装 Return Oriented Programming(ROP)の手法を利用して関数分岐命令をcall+スタック 操作+ret命令で置き換える。更に間抜け罠を仕掛けておく。 29 .macro RETPOLINE_JMP reg:req call .Ldo_rop_@ .Lspec_trap_@: ここからjmpまで間抜け罠 pause 投機的実行だけが行われるが捨てられる lfence jmp .Lspec_trap_@ .Ldo_rop_@: mov reg, (%_ASM_SP) ret .endm 投機的実行の動き
  30. 30. Return Stack Buffer Ret命令はBTB使わないの? →Ret命令の投機的実行用のキャッシュとしてReturn Stack Buffer (RSB) という仕組 みが導入されている。 - 過去32回分のreturn addressをcall時にpushできるバッファ(キュー) - ret命令時にpopして投機的実行する(iretは対象外) 32回以上callが重なり、そこからのretが重なると空になる 空になると投機的実行は止まる 30
  31. 31. 間抜け罠の役割 RSBにより、call命令の次のアドレスがret命令の分岐予測に使われる - Retpolineのret命令も、call時のアドレスに従って投機的実行される - 投機的実行でcallの次の命令を実行しようとしたプロセッサを足止めし、lfence (load fence)でメモリからのロードを待つように指示しつつ無限ループ 投機的実行を確実にlfenceで止められるかどうかは実装に依るし保証されていないの で、ループして待たせる(し、このコードの実行結果は確実に捨てられる) 31
  32. 32. Retpolineの実装 Retpolineは特定の命令を別の命令シーケンスで置き換えることになる よってコンパイラでの対処が必要となる - GCCとLLVMの両方で共通仕様の処理を追加 - 間接分岐命令(一部のswitch()case文や関数ポインタコール)を __x86_indirect_thunk_*という関数へのジャンプあるいは呼び出しに置き換える - アセンブラで書かれていても勝手に置き換わるらしい? 32
  33. 33. Linuxカーネルの問題 コンパイラで対応しても、Linuxカーネルには2つの問題がある - ハンドアセンブルしているコードでindirect jmp/callを使っている - リンク方法が特殊で__x86_indirect_thunk*がリンクされない また、対応コンパイラが出るまでは不安全な状況におかれてしまう 33
  34. 34. Linuxカーネルの対応(CONFIG_RETPOLINE) CONFIG_RETPOLINEを有効にすると以下の処理が行われる - __x86_indirect_thunk_*をカーネル内で再実装する (arch/x86/lib/retpoline.S) - CALL_NOSPEC/JMP_NOSPECというアセンブラ用マクロを定義 いずれもalternatives(動的コードパッチ機能)で、対応が必要なCPUの場合のみ適用さ れるようになっているので、対応不要なCPUの場合のオーバヘッドは殆ど無い。 34
  35. 35. alternativesによる命令列の変更 起動時にCPU featureをチェックして自己書き換えする 0000000000000000 <__x86_indirect_thunk_rax>: 0: ff e0 jmpq *%rax 2: 90 nop 3: 90 nop 4: 90 nop 5: 90 nop 6: 90 nop 7: 90 nop 8: 90 nop 9: 90 nop a: 90 nop b: 90 nop c: 90 nop d: 90 nop e: 90 nop f: 90 nop 10: 90 nop 0000000000000000 <.altinstr_replacement>: 0: e8 07 00 00 00 callq c <.altinstr_replacement+0xc> 5: f3 90 pause 7: 0f ae e8 lfence a: eb f9 jmp 5 <.altinstr_replacement+0x5> c: 48 89 04 24 mov %rax,(%rsp) 10: c3 retq 35
  36. 36. Skylake用のRSB拡張 Skylake以降の世代では - Retpolineの最後のret命令を使おうとしたとき、RSBが空になっていたら、そのアド レスに対応するBTBエントリを利用して投機的実行を行う - つまりRet命令が間接分岐命令と同じように扱われてしまう そこでRetpolineにはFILL_RETURN_BUFFERという別のコードも追加されている - 簡単に言うと、ダミーのcall命令を2つのアドレスに交互に出すループを使い、RSB を埋めた後、スタックをスキップする。(どうも同じアドレスが続くとまとめられるらし い) 36
  37. 37. FILL_RETURN_BUFFER RSBを無理矢理埋める処理(Callの空打ち) 37 #define __FILL_RETURN_BUFFER(reg, nr, sp) mov $(nr/2), reg; ループ回数の設定 771: call 772f; 関数コール(スタック+1) 773: /* speculation trap */ pause; lfence; jmp 773b; 772: call 774f; 関数コール(スタック+1) 775: /* speculation trap */ pause; lfence; jmp 775b; 774: dec reg; jnz 771b; ループ add $(BITS_PER_LONG/8) * nr, sp; スタックポインタだけを元に戻す RSBは773と775のアドレスで埋まる
  38. 38. FILL_RETURN_BUFFERの使いどころ IntelのDave Hansen氏によってまとめられている(https://goo.gl/pXbvBE) - 基本的にIBRS(後述)なしの場合には色んな箇所で必要 - コンテキストスイッチ、割り込みだけでなく、深い呼び出しなども対象 - IBRSがあってもコンテキストスイッチでは必要になる - VMexit/VMenterする場合に重要 - ホストのring-0のRBSはゲストのring-0のRBSと共通らしい - VMの切り替え処理はスタックが深くなりやすい上、ゲスト OSが脆弱な場合injectが発生する可能 性が・・・。 38
  39. 39. RSB Fill がコンテキストスイッチで必要な理由 プロセス切り替えの場所によってスタックの深さが違う Process1→Process2 ならRSBは枯渇しない (4 > 2) Process2→Process1の場合、Func2の戻りで枯渇(2 < 4)→BTB発動! 39 Func1() Func2() Func3() Func4() context_switch() (#RSB=4) Func1() Func2() context_switch() (#RSB=2) Process1 Process2
  40. 40. Spectreに対するハードウェア緩和策 Intel/AMDから、新しいマイクロコード命令であるIBRS/IBPB/STIBPが提供された - IBRS (Indirect Branch Restricted Speculation) 間接分岐命令の投機的実行を行う際、IBRSが1にセットされる前のBTBの結果を使わないよう にする。(Kernel→User遷移時に0にしておく) - IBPB (Indirect Branch Prediction Barrier) 簡単に言うと、Indirect Branch用BTBのフラッシュ。プロセスやVMの切り替え時に発行し、 Indirect Branch Predicationの状態を初期化する - STIBP(Single Thread Indirect Branch Prediction) 一部のプロセッサではHT間でBTBが共有されているが、これをスレッドごとにする →(1/30日現在) LinusがIntelの出したコードが煩雑で重く確実性が不明で嫌いということでリジェクト されている(5000サイクルほど無駄になるらしい) →IBPBは採用されている(VMの切替時に) 40
  41. 41. Spectre V2緩和策まとめ プロセッサの種類によって方法が少し異なる 乱暴に言うと、Skylake以前はRetpoline、Skylake以降はRetpoline+色々 41 問題 対策 Skylakeより前 IBP injection Retpoline + IBPB Skylake以降 RSB+IBP injection Retpoline + RSB Fill + IBPB 一部のプロセッサ(詳細不明) HT-IBP injection Retpoline + RSB Fill + IBPB + STIBP? AMDのプロセッサ IBP injection* lfence + indirect jump 但し後期Skylakeでは修正されるっぽいので Skylakeというのも正しくない
  42. 42. Arm/Arm64での緩和策 Arm本家からのアナウンスに影響を受けるプロセッサと対策について記述済み https://developer.arm.com/support/security-update - 基本的にはOut-of-order型のCortex-A/Rシリーズの一部が影響を受け - In-order型のプロセッサは影響を受けない(Cortex-A53/55など) 必要なポイント(メモリ空間切り替え等)でBTBの消去や分岐予測の無効化を行う - ファームウェア側で必要な処理を実装 - Linuxカーネルからは適宜ファームウェアを呼び出す(SMCCC)+MMUの無効化 +再有効化(400ns未満で済む) Retpolineは使われない模様→詳しくは参考文献3のBackportリストを参照 42
  43. 43. Retpolineと性能最適化 Retpolineによる性能への影響 - 間接分岐命令のみに影響 - カーネル内のXX_ops的なテクニックが対象 - 投機的実行は間抜け罠にかかる →間接分岐命令は常に投機的実行に失敗する 43 Retpoline 間接分岐命令をROP コードで置き換える。 投機的実行は死ぬ
  44. 44. Retpolineと性能最適化のジレンマ Retpolineを適用した場合、Switch-caseなどを避けて間接分岐で性能を向上させるテク ニックが封じられる ところが、これは「現在の主流プロセッサ」だけが対象 →Intelは今年中に対応したプロセッサの提供を開始予定 →新しいプロセッサではまた間接分岐のほうが速くなる? Retpolineの影響を避けるためだけにコーディングすべきか否か・・・? 44
  45. 45. probe-eventに対するretpolineの影響 ftraceのprobe-eventは、任意の場所でレジスタやメモリを参照するイベントを生成でき る - 構造体や配列などの中身を参照するためかなり柔軟に作っている →但し全て関数ポインタで記述 問題 - 多分retpolineで性能が劣化する 解決策 - 固定シーケンスのバイトコード(switch-case)で書き直し中 45
  46. 46. kprobesに対するretpolineの影響 Retpolineの実装を調査し、1月18日にkprobesの修正パッチを送付→20日には取り込 まれた 問題 - kprobesが使うexceptionの処理の一部に間接分岐が使われている - 元々間接分岐がある関数ではoptprobeを無効化していた 修正 - __x86_indirect_thunkの部分にプローブをしないようにする - __x86_indirect_thunkへのジャンプを見つけたらindirect jumpと同じように扱う(そ の関数内ではoptprobeを無効化) 46
  47. 47. 参考文献 1 Project Zero :Reading privileged memory with a side-channel https://googleprojectzero.blogspot.jp/2018/01/reading-privileged-memory-with-side.html Meltdown and Spectre https://meltdownattack.com/ LinuxコアメンバーによるMeltdownとSpectre 対応状況の説明 https://qiita.com/hogemax/items/008f19fd14eebca474d7 prevent bounds-check bypass via speculative execution https://lwn.net/Articles/744257/ Gcc retpoline branch: http://git.infradead.org/users/dwmw2/gcc-retpoline.git/shortlog/refs/heads/retpoline LLVM retpoline review: https://reviews.llvm.org/D41723 47
  48. 48. 参考文献 2 Spectre Attacks: Exploiting Speculative Execution https://spectreattack.com/spectre.pdf KASLR is Dead: Long Live KASLR https://gruss.cc/files/kaiser.pdf Prefetch Side-Channel Attacks https://gruss.cc/files/prefetch.pdf Intel Analysis of Speculative Execution Side Channels https://newsroom.intel.com/wp-content/uploads/sites/11/2018/01/Intel-Analysis-of-Speculative-Execution-Side-Channels.pdf Vulnerability of Speculative Processors to Cache Timing Side-Channel Mechanism https://developer.arm.com/support/security-update CPU security bugs caused by speculative execution https://github.com/marcan/speculation-bugs/blob/master/README.md 48
  49. 49. 参考文献 3 ARM-TF Security Advisory TFV6 https://github.com/ARM-software/arm-trusted-firmware/wiki/ARM-Trusted-Firmware-Security-Advisory-TF V-6 arm64 kernel for-next https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/core Downloads and help for Meltdown and Spectre https://www.linaro.org/downloads/security/ Linaro Security Blog https://www.linaro.org/blog/meltdown-spectre/ arm/arm64 Spectre/Meltdown backporting https://lkml.org/lkml/2018/2/9/310 49
  50. 50. 50 SPECTREBUSTERS
  51. 51. 51 SP CTREBUSTERS
  52. 52. SPECTREBUSTERS ロゴ SPECTREBUSTERS SPECTREBUSTERS ←本家版 52 SP CTREBUSTERS SPECTREBUSTERS

×