2018年の年明けから大騒ぎとなっているSpectreとMeltdownの脆弱(ぜいじゃく)性をざっくりと解説する。プロセッサの何が問題となって脆弱性が起きているのだろうか?
2018年正月早々、プロセッサ業界に騒動が起きている。すでにあちらこちらで報道されているのでご存じの方も多いと思うが、Spectre(スペクター)とMeltdown(メルトダウン)と呼ばれるプロセッサの脆弱性の問題である(脆弱性の詳細は、Google Project Zeroの「Reading privileged memory with a side-channel 」参照のこと)。
脆弱性は、以下の3つである。「Variant 1」と「Variant 2」がSpectreと呼ばれるもの、「Variant 3」がMeltdownと呼ばれる脆弱性だ。
いずれも「本来読めてはいけない秘密のデータなどが格納されているメモリを権限の低い別のプロセスから読めてしまう」というセキュリティ上の大問題だ。「ああ、またまた、いつものソフトウェア脆弱性の騒動か」と高をくくる人もいるかもしれないが今回は違う。OSやソフトウェアに関わりなく、「地球上のほとんどのプロセッサ」が原因である。
根本的にはハードウェアを変えるしかないと思うのだけれど、そんなことはすぐにはできない。コンピュータを使わないわけにもいかない。取りあえず、OSやWebブラウザのパッチなど、ソフトウェア的な対策で逃げるしかないのだ。けれども、それによる速度低下がばかにならない、ということでほぼIT業界総力を挙げての「緊急」対応になっている。
こういうドタバタ対応になってしまった理由としては、英国のIT情報サイト「The Register」のリークが原因らしい。この問題は、2017年の夏にGoogleの脆弱性調査専門チーム「Project Zero」が発見したらしいが、問題が問題なだけにひそかにプロセッサやOSなどの主要各社に知らせたらしい。
そこで各社はひそかに対策を練っていたようだが、この予定外のすっぱ抜きがあり、もくろんでいたシナリオとは異なる形での対応を余儀なくされた、ということのようだ。
初期の報道では「Intelのプロセッサのみ対象」という報道がなされたが、これについてはIntelが反論している。Intelだけというのは違う。他社プロセッサでも起こる。ただ、「たまたま」Meltdownという名の問題は、Intel製の方が起こしやすかった、という程度だろう。「クライアントもサーバもみんな問題」という指摘は大筋で正しいが、「地球上の全て」というと、少々言い過ぎだと思う。まずは、どんなプロセッサが対象になっているのか、どういうメカニズムでセキュリティ上のリスクが顕在化するのかを考えてみる。
対象のプロセッサを簡単に要約するならば、「投機的実行(speculative execution:スペキュラティブイクゼーキューション)」「アウトオブオーダ実行」できるプロセッサ、である。確かに、サーバも、PCやスマートフォン(スマホ)などのクライアントも、現在主力で使用されているプロセッサのほとんどがこの範囲に入る。
しかし、明確にこの範囲に入らないものも多数ある。制御用のいわゆるマイコン系では、だいたい投機的実行もアウトオブオーダ実行もしない、スーパースカラですらないことも多い。筆者の愛してやまないマイコンは全然気にしなくてよい。ARMなども、「M」などの型番の付いた下位モデルは、範囲外だろう。また、複数命令を同時に実行できるスーパースカラであっても、初代のPentiumのように投機的実行もアウトオブオーダ実行でもないマシンも対象外だ。
近年のx86、ARMの上位機種、PowerPCなどほぼ全てのメジャーな主力モデルは、ほとんどが対象となる。原理からいうと、SpectreもMeltdownもどこのプロセッサで起きてもおかしくないと思う。
実際、Spectreの方は、Intelであろうが、AMDであろうが、ARM、IBM全てで起きているようだ。一方、Meltdownは、Intel製のx86では起きて、AMDでは起きていないらしい。しかし、ARMの主力機種の1つである「Cortex-A75」などでは、Meltdownを起こすことができたらしい(ARMのホワイトペーパー「Vulnerability of Speculative Processors to Cache Timing Side-Channel Mechanism」)。
どうも「起こしやすい」マイクロアーキテクチャと「起こしにくい」マイクロアーキテクチャがあるのではないかと思う。Meltdownはかなり実行タイミングに依存するようなので、もしかすると運よくAMDのマイクロアーキテクチャにはそういうタイミングがなかったのか。まぁ念のため、アウトオブオーダ実行のプロセッサだったら、「大丈夫か?」とうたがってみるべきだろう。
投機的実行とは、プロセッサの高速化技術の一種であり、条件判断(条件分岐)を含むコードの実行速度を高めることができる。
本来、下の図で条件判断が確定しないとルートAにもルートBにも進むことができない。
しかし、条件判断の確定を待っているとプロセッサのリソースが遊んでしまう(だいたい最近のプロセッサは「完了」する命令の数十命令先の命令まで「着手」している程度の仕組みになっている)。そこで、「実行されそうな」ルートに「賭けて」、先行して着手してしまうのだ。条件判断の結果が当たっていれば、先行して着手したルートの結果をそのまま使えば結果オーライだ。外れた場合は、結果を捨てて別ルートでやり直す。
ともかく条件判断の予想を間違わないようにするのが肝心である。そこで条件判断の過去の履歴を状態条件の予想に使用するのが一般的だ。
アウトオブオーダ実行もプロセッサの高速化技術の一種で、コード実行の順序を工夫することで実行速度を高めることができる。
ソフトウェアから見たら、命令は順番に実行されているようでないと、つじつまが合わなくなる。しかし、ある「命令1」に時間がかかっている場合、それを待っていると以降の命令の開始が全て遅れるので、「命令1」の完了を待たずに、先行して「命令2」以降の実行可能な命令に着手してしまう。ただし、命令の完了は順番にしないとまずいので、「命令2」以降は、「命令1」の完了前に実行されるが「完了」の順番待ちというような状態に置かれる。
万が一、「命令1」で例外が発生などすると、「命令2」以降の実行結果は取り消されることになる(上図の点線内)。
さて、上記のような機構を悪用するSpectreとMeltdownであるが、基本的な考え方は似ている。
SpectreとMeltdownの違いは「勇み足」を引き起こす手法の部分である。
ターゲットは何らかのパスワードを取り扱うようなAPIなどと想定しよう。こうしたAPIに以下のようなコードがあったとする(このコードは脆弱性を発見したProject Zeroの論文「Spectre Attacks: Exploiting Speculative Execution」に例として記載されている)。
if (x < array1_size)
y = array2[array1[x] * 256];
そもそもこの脆弱性は、キャッシュがプロセス間で共有されており、毎回キャッシュラインをフラッシュするようなことをしていなければ、別のプロセスのキャッシュラインに対する接触情報がプロセスの垣根を越えて見えてしまう、というところにある(もちろん、毎回キャッシュラインをフラッシュしていると大幅に性能が低下してしまう)。
Meltdownの場合は、特にターゲットとするAPIなどがなくても攻撃コードのみでよい。
【ポイント】「2」の結果はプログラムの実行上は捨てられて、ソフトウェアからは見えないはずだが、キャッシュの履歴を変えてしまった部分まではキャンセルされない。Spectre同様、間接的に調べていくことで、どのようなデータが読み出されたのかが決定できる。なお、効率的に実行するためには、例外発生でOSにトラップされないような仕組みも入れておく必要がある。
こうして書くとどちらの脆弱性も簡単に攻撃が可能そうだが、何もないところから実際にちゃんと動作するコードを書くのは相当難しそうだ。さらに、緊急のパッチなどの対策でさらに難易度は高くなっていると思われる。
しかし、これはプロセッサのハードウェアに起因するもので、かつ現状のプロセッサのほとんどが頼り切っている技術であるだけに、根本対策は結構難しそうである。
ふと、昔を思い出した。プレスリリースの下書きをしているときに「speculative execution」という用語を訳さなければならなかったことがある。その際、何も考えずに、一般的に日本語訳として使われている「投機的実行」としたら、その原稿を読んだ当時筆者が在籍していたA社のN社長から「投機はよくない!」とお叱りを受けたことがある。そんなことを言われても、訳語としては定番なものだしね……。弱って何か適当な用語に置き換えて書いた後に小さく(投機的実行)としたのだった。やっぱりN社長が言ったように「投機はよくなかった」のだな。
■関連リンク
日本では数少ないx86プロセッサのアーキテクト。某米国半導体メーカーで8bitと16bitの、日本のベンチャー企業でx86互換プロセッサの設計に従事する。その後、出版社の半導体事業部などを経て、現在は某半導体メーカーでヘテロジニアス マルチコアプロセッサを中心とした開発を行っている。
「頭脳放談」
Copyright© Digital Advantage Corp. All Rights Reserved.