Meltdownについて今回CPUに依存する脆弱性が発見されて大きな問題となっている。そこで正月休みを使ってこの問題の解説を試みる。Disclaimer私はセキュリティの専門家ではないので間違えた情報があるかもしれない。一次情報を載せておくので怪しい場合にはそこにアクセスして自分で確認するように。この情報を鵜呑みにしておきたいかなる問題にも責任は負いかねる。今回の脆弱性についてのWEBページ業務で問題の解決を行う場合にはこのページを参照すること。今回は2つの脆弱性が問題になっている。1つ目はMeltdownと名付けられており、CPUのout-of-order実行を利用したもの。2つ目はSpectreというCPUの投機的実行を利用したもの。悪意のあるコードとそうでないコードの見極めが非常に難しいことなどから、解決の難しい問題となっている。MeltdownMeltdownから解説していく。Meltdownと名付けられたこの問題はCPUのout-of-order実行の隙を突いた攻撃方法である。out-of-orderout-of-orderと言うのはモダンなCPUが搭載しているパフォーマンス最適化手段である。現在のCPUはアセンブリ命令をμOpsという更に小さなCPUのオペレーションに分割して実行する。このμOpsに分解された命令はReorder-BufferとSchedulerによってデータの依存関係が計算されて、実行順が変更される。結果としてそれぞれ依存関係から独立した命令は順序に関係なく実行され、依存がある部分は依存先の命令が完了次第即実行される。以下が今回の問題となる疑似コードだが、gist4ad97b3858f184ca74efbbfe54e845ef4行目のmov命令と5行目のshl命令は依存関係があるものの、それ以外はすべて予めμOpsに分解されて実行される。以下はWikipediaからの引用OoOでは、命令及び実行結果を一時溜めておく場所を作り、命令の実行を次のように細分化する。buffer)のエントリを割り当てる。queue)に送る(dispatch)。命令待ち行列内の命令は、入力オペランドが得られるまで実行されない。入力オペランドが得られた段階で、待ち行列内にそれより古い命令があっても先に待ち行列から取り除かれ、実行されることになる。命令が適当な実行ユニットに対して発行(issue)され、実行される。実行結果がリオーダ・バッファに格納される。リオーダ・バッファ内の命令のうち、最も古い命令の実行が完了すると、その実行結果はレジスタファイルに書き戻され、命令はリオーダ・バッファから取り除かれる。retire)ステージと呼ぶ。命令待ち行列とは異なり、より新しい命令が実行完了状態であっても、それより古い命令がリオーダ・バッファ内にリタイアせずに残っている場合は、その(より新しい)命令がリタイアすることはできない。space上の例で示した疑似コードは実行するとカーネルの特権メモリをユーザースペースで読み込んでいるため例外を発生させる。そのため、当然ユーザースペースからカーネルメモリを読み込むことは不可能である。Instructionを経由することでカーネルメモリをCPUキャッシュに載せることが可能になる。本来の実行パスでは実行されるはずのない命令である。以下に擬似コードを示す。このコードは擬似コードであり実際には動作しない。4096]のメモリアクセスが実行される。Memory以上のテクニックを駆使することによって特権がなくても特権が必要なメモリの値をロードすることができる。7でraxつまり、先程カーネルメモリの内容を読み込んだアドレスに対して間接参照をする。することで例外が発生するよりも先に格納されたメモリにアクセスするすることが可能になる。Side-Channel-Attackしかし、上記の方法を利用してもout-of-orderの実行結果は巻き戻されて取得ができない。ここでSide-Channel-Attackを利用する。Side-Channel-Attackとは外からハードやCPUの状態を観測することで値を取得するという方法である。今回のペーパーではFlush+Reloadという方法を利用していた。秘密の値のみに依存したアドレスが取得できるようだ。攻撃手法として例外を握りつぶすためにプロセスのforkを行い、その中でこれらの攻撃を行い、メインプロセスでメモリアドレスを調べる方法が提案されている。SpectreこちらはCPUの投機的実行という機能を利用したものでMeltdownと似ているが、より実行しやすい。条件分岐の結果評価が完了する前にthen節やelse節を実行する。その後条件分岐が確定し、投機的実行した結果の値が必要なくなれば、その結果はそのまま捨てられる。Meltdownみたいに実行されてほしくないコードが実行されることがありうる。嫌な雰囲気になってきたね。Side-Channel-AttackやはりここでもCPUキャッシュの状態を観測することで値を取得する。以下に擬似コードを示す。256];以下はペーパーに記載されていたシナリオである。array1_sizeが確定する前に実行されるとし、xは取得したいアドレスの値とする。するとarray1[x]がキャッシュから取得され、アドレスkが手に入る。array1_sizeが確定することで、すべての結果が破棄される。array2[k]への投機的実行はすでにCPUキャッシュに変化を起こしてしまっているのでそれを観測することで目的のデータを取得することができる。Javascirptペーパーによるとjavascriptでも実行できるためそれなりに危険そうである。V8のデバッグシェルであるd8で実行して成功したようなので結構ダメそう。BlogSharedArrayBufferの無効化、performance.now()のresolutionを20μsに低減Appleわからん!まとめちょっと内容が複雑なため間違いを含んでいる箇所があったら申し訳ない!とにかく基本は1次情報にあたってほしい。詳しい方、コメント等で修正があったらしていただけると助かります。2はてなブログをはじめよう!brn_takeさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。