ニュース
Googleが発見した「CPUの脆弱性」とは何なのか。ゲーマーに捧ぐ「正しく恐れる」その方法まとめ
「Intel製のCPUだけが持つ脆弱性で,AMD製のCPUなら問題ない」から始まって,「いやいやAMD製のCPUも同様の脆弱性を抱えている」,さらには「メモリページング方式の仮想記憶を使うCPUのすべてが持つ脆弱性である」などと,情報が錯綜しているので,何を信じたらいいのか分からないという人も多いのではなかろうか。そもそも,メモリページング方式の仮想記憶は,今日(こんにち)のすべてのCPUと,その上で動くOSが使っているので,もし最後の情報が本当なら,現代文明を揺るがしかねない大問題だ。
では実際のところ,騒がれている「CPUの脆弱性」とは何であって,ゲーマーの生活にも影響はあるのだろうか? 今回は,脆弱性の概要と影響の範囲をまとめ,「正しく恐れる」方法を紹介してみたい。
Googleが公開した脆弱性は3種類
そもそも今回の脆弱性は,Googleのセキュリティ研究チーム「Project Zero」が北米時間2018年1月3日に発表したものだ。
情報が錯綜した背景には,Project Zeroの発表したペーパーに,「現代的なCPUアーキテクチャに起因している」という共通点を持ちつつ,それぞれ影響を与えるCPUや影響の範囲が異なる,下に示す3つの脆弱性の存在が挙げられる。
- Variant1(CVE-2017-5753):配列の境界チェックバイパス
- Variant2(CVE-2017-5715):分岐ターゲットインジェクション
- Variant3(CVE-2017-5754):不正なデータキャッシュ読み込み
冒頭で名前だけ挙げたSpectreはこのうちVariant1とVariant2,MeltdownはVariant3の識別名で,すでに英語の解説ペーパーがpdfとして公開されている。
- Spectre解説ペーパー
- Meltdown解説ペーパー
※いずれもリンクをクリックするとpdfファイルのダウンロードが始まります。
各脆弱性の影響を受けることが確認されているCPUをここで列挙しておこう。
- Variant1:Intel製の幅広いCPU,Arm製のCPU IPコア,AMD製のCPU
- Variant2:Intel製の幅広いCPU,Arm製のCPU IPコア
- Variant3:Intel製の幅広いCPU,Arm製のCortex-A75
※AMD製CPUは,原理的にはVariant2の影響を受ける可能性があるものの,Googleのセキュリティチームによると,現時点ではVariant2を使った攻撃が成功していないとのことだ。それもあり,AMDは自社製CPUに関して「Variant2のリスクはゼロに近い」とアナウンスしている。また,AMD製CPUはVariant3の影響を受けない。
これら3つの脆弱性のうち,最も脅威度が高いのは,ユーザープロセスからカーネルメモリ空間を読み出すことができてしまうVariant3(=Meltdown)と思われる。Variant3の影響を受けるのは上記のとおり「Intel製の幅広いCPU」とArmのCortex-A75 だけだが,Cortex-A75は2017年に発表されたばかりのCPU IPコアなので,最終製品における実装例はまだない。なので実質的に,最も影響を受けるのはIntel製の「幅広いCPU」のみと言い切ってしまっていいかと思う。
「『幅広いCPU』と言われても分からん」という話はあるが,実際のところ,Intel製CPUのどこからどこまでが影響の範囲かは,はっきりしていない。GoogleのセキュリティチームではIvy BridgeとHaswell,Skylakeの3世代が影響を受けることを確認済みだそうだが,それ以外のIntel製CPUマイクロアーキテクチャが影響を受けるかどうかは,Intelからの公式発表を待つしかないという状況である。
脆弱性を理解する基礎知識
さて,ここで3つの脆弱性を理解するために簡単な予備知識をまとめておこう。
現代のOSは簡単に落ちたりしないように設計してある。たとえばゲームが異常終了してしまったとしても,それが原因でWindowsごと停止してしまうということはまずないということを経験的に知っているだろう※。
※コンポーネントの熱暴走など,ハードウェアの異常に起因するOSの異常終了は依然として存在するが,ハードウェアの異常はここでは問題にしない。あるソフトウェアが原因でWindowsが丸ごと使えなくなったりはしないということだ。
これは,ゲームを含むユーザープログラムから,OSが使っているメモリ領域にアクセスできないよう,「壁」もしくは「バリア」的なものを設けてあるからだ。本稿では以下,便宜的にバリアと呼ぶが,このバリアはCPUの持つ特権機構を利用したものとなっている。ユーザープログラムがOSカーネルのメモリ領域にアクセスしようとすると,「特権違反」(という割り込みの一種)が発生して,アクセスを未然に防ぐのだと考えておけばいい。
この特権機構は,セキュリティを担保するためにも重要な役割を果たす。というのも,OSが管理しているメモリ領域は,他のアプリケーションがやり取りしているデータやパスワード,ユーザーアカウントといった情報を含んでいるからだ。
これらの情報を,他のアプリケーションが覗き見ないようにするということも,特権機構は実現しているのである。
今回明らかになった3つの脆弱性を応用すると,OSが管理しているメモリ領域「カーネルメモリ空間」を,特権機構を超えて覗き見ることができてしまう。これは悪意を持つプログラムがデータやパスワード,ユーザーアカウントを覗き見ることを可能にすることを意味するので,ゲーマーにとっても無視できない問題ということになる。
それを踏まえて,以下,3つの脆弱性を1つずつ見ていきたい。
Variant1:配列の境界チェックバイパス
Variant1は,あるプログラムが「アクセスが許されているメモリ領域」を超えてデータを読み出せる脆弱性だ。CPUが持つ「命令の投機実行」と「データキャッシュの振る舞い」を応用したものとなっている。
Variant1の概要
CPUは基本的に「メモリに並べられている順」に命令を実行するのだが,現代的なCPUでは,命令実行を高速化するため,複数の命令をメモリから取ってきて,問題がなければ順不同でどんどん実行する「投機実行」という手法が採用されている。
投機実行では,条件分岐がある場合でも,条件が成立するか否かはとりあえず横に置いておいて,先に命令を実行してしまう。条件分岐が成立してしまった場合は,先行して実行した結果を捨て,条件が成立したほうの命令を実行し直すのが特徴だ。
あるデータが格納されているメモリ範囲があるとしよう。「もしメモリ範囲を超えていたらメモリ範囲からのデータの読み出しを止める」という条件分岐があったとする。投機実行ではメモリ範囲を超えていたとしても,データの読み出しを実行してしまい,「メモリ範囲を超えた」という条件が成立した時点でデータの読み出しを止めるよう,命令実行の結果を捨ててやり直す動作になる。
さて,ここで「あるメモリ範囲から読み出した値を使って別メモリの範囲を読み出す」という仕掛けを作っておくことを考えてみる。投機実行ではメモリ範囲を超えていたとしても投機的にデータを読み出すため,「別メモリの範囲を読み出す」ことも実行する結果となり,当然,別メモリの範囲がデータキャッシュに読み出される。
なので,「データキャッシュに別のメモリ範囲のデータが存在しているかどうか」は,読み出し速度から測定することが可能だ。つまり「投機実行によって別メモリの範囲を読み出したかどうか」を判定できることになる。こうした振る舞いを巧妙に応用することで,本来なら許されていないメモリ範囲の内容を「推定」できてしまうというのがVariant1の概要だ。
Variant1による影響の範囲
Variant1を使って,たとえばカーネルのメモリ範囲の内容を推定するには,カーネルのメモリ空間で動作するプログラムが必要になる。つまり,Variant1だけを使ってユーザープログラムからカーネルのメモリ範囲内にあるデータを読み出すことはできない。なので,Variant1の脆弱性だけに起因する問題がそうそう簡単に生じることはない。
ただ,残念ながらというかなんというか,WindowsやLinuxといった現在の高機能なOSでは,ユーザー権限で安全にカーネルプログラムを実行する,一種のプラグインのような仕組みがあったりする。そういったプラグインからVariant1を利用することで,本来なら許されていないカーネルのメモリ範囲を読み出すことは可能で,これは大きな問題になると考えられる。
Variant1に向けた各社の対応
Variant1に対しては,WindowsとLinux用の修正プログラムが配信されているので(Windows / ARMv8用Linux),適用しさえすればVariant1に関連した攻撃は防げる。また,修正プログラムを適用することによる性能への影響は軽微とされているので,その点でも安心度は高いと言えるだろう。
また,AppleはiOSとmacOS,tvOS,watchOSに対し,今後のアップデートで対応を行うと発表している。
ただ,Linuxカーネルを採用していても,Androidだけは事情が異なる。よく知られているとおり,Android端末では,修正プログラムの配布をメーカーの裁量――国内においては多くの場合,携帯電話キャリアの裁量――で行っているからだ。なので端末によっては,未来永劫,修正プログラムが配信されないという可能性もある。
Variant2:分岐ターゲットインジェクション
Variant2は,Variant1のように文章で説明するのがかなり困難なので,概要だけ簡単にまとめておきたい。
今日(こんにち)のCPUが分岐予測を使って条件分岐の高速化を図っているというのはすでに紹介したが,ここには,やや複雑なアーキテクチャ上のアルゴリズムと,過去の分岐先を格納しておく分岐ターゲットバッファ(Branch Target Buffer,以下 BTB),両者の活用がある。
CPUの分岐予測アルゴリズムやBTBの詳細な仕組みはCPUメーカーから公開されていないのだが,GoogleのセキュリティチームはHaswellアーキテクチャのCPUを使って,分岐予測とBTBの働きを調べ上げ,「物理CPUのBTBが1つしかない」という制限を利用することで,論理CPU間で一方のスレッド/プロセスの分岐に影響を与え得ることを発見したそうだ。
この振る舞いを使って,他プロセスが割り当てられているメモリを推定することが可能というのがVariant2の概要となる。
Variant2による影響の範囲
カーネルや他のプロセス,あるいは仮想マシンの下で動く仮想環境のメモリをVariant2から推定し,攻撃を行うには,Variant1と同じく,カーネルのプラグインのような仕組みを使う必要がある。そのため,Variant1と同じく,Variant2だけを使った攻撃が簡単にできてしまうということはない。
ただし,Variant1と2を組み合わせて応用することで,JavaScriptなどからカーネルを攻撃する方法が開発されている。ブラウザからの攻撃が可能になる恐れがあるため,脅威度自体は高いと言っていいだろう。
Variant2に向けた各社の対応
Armはすでに同社のアプリケーションプロセッサでVariant2を防ぐLinuxカーネルの修正を公開した。なので,最新の修正プログラムとしてVariant2対策が施されるはずだ。
また,Appleも前出のアナウンスに合わせ,Variant2対策を今後のアップデートで行うと予告している。
一方のIntelはまだ表だった対応の動きを見せていないが,おそらくはWindowsやLinuxといったOSの修正プログラムといった形で対処されることになるだろう。
Androidがメーカーもしくはキャリア次第というのは,ここでも変わらずだ。
Variant3:不正なデータキャッシュ読み込み
Variant3はVariant1の応用のような手法だが,ユーザープログラムからカーネルのメモリ領域を読み出せる可能性を持つ点で脅威度が高い。
たとえば次のような命令コードがあったとしよう。
mov al, [カーネルのメモリ領域]→ この命令は特権違反
shl eax, 0xc
mov ebx, [ユーザーのメモリ領域 + eax]
1行めはカーネルのメモリ領域をレジスタAL(EAXレジスタの下位8bit)に読み出すもので,ユーザープログラムでは「特権違反」となり,例外エラーが発生する。そのためカーネルのメモリ領域は読み出せない,というのが特権機構のキモだ。
だが,前出のとおり現在のCPUでは投機実行が行われている。そこで「特権違反に先行して命令を実行しているのではないか?」と着目した結果がVariant3となる。そしてこの発想は実際に正しいようで,上のコードだと3行めまでが実行できてしまう。そのため,「[ユーザーのメモリ領域 + eax]がキャッシュされたかどうか」を確かめることによって,カーネルメモリ領域の内容を推定できてしまうようだ。
Variant3による影響の範囲
Variant3はユーザープログラムのレベルでアクセスが許可されていないメモリ領域にアクセスできる可能性を秘めているため,Variant1およびVariant2に比べて脅威度がより高い。実際,Googleのセキュリティチームは,「Mozilla Firefox」ブラウザのパスワードマネージャを,Variant3の手法を応用することでリークさせることができたと主張していたりもする。
Variant3に向けた各社の対応
ArmはすでにVariant3に対してLinuxカーネルの修正プログラムによる対応を行った(関連リンク)。
Intel製CPUでもカーネルの修正で対応は可能と考えられる。ただ,「カーネルのメモリ空間をユーザープログラムから」という,Variant3に向けた完璧な対応を行った場合,システムコールのたびにメモリページの切り替えが頻発することになり,いきおい,大幅な性能低下を招くことになるだろう。
もっとも,AppleはすでにiOSとmacOS,tvOSで対策済みとしており(関連リンク),性能低下もわずかだという。すでに利用されているカーネルメモリ空間のランダム化を強化することでVariant 3の攻撃をしづらくしているのではないかと思うが,そうした対策がWindowsでも可能ならば,Intel製CPUを使っている環境における性能低下は小幅なもので済むはずである。
Androidに対策が入るか否かがメーカーもしくはキャリア次第なのは,やはり変わらない。
対策は「最新の修正プログラムを導入しつつ,怪しいプログラムは実行しない」ことに尽きる
仮想記憶やCPUの特権機構は,投機実行や分岐予測といった高速化のための手法が考案されるよりも,かなり以前に成立した仕組みだ。今回の脆弱性は,「投機実行や分岐予測に仮想記憶やCPUの特権機構を実装するにあたり,思わぬ落とし穴があった」という点でとても興味深い。
プログラマー視点で言えば,CPUの特権機構などは当然のように機能しているという前提があるので,それがすり抜けられるという話はまさに寝耳に水といった感じである。
いずれにせよ,プログラマーにとってさえ寝耳に水なのだから,ユーザーレベルでできることというのはさほど多くない。ゲーマーとしては,センセーショナルに騒ぎ立てる人達に耳を貸すことなく,慌てず騒がず最新の修正プログラムを施し,怪しいプログラムは実行しないという鉄則を守ることが肝要だろう。
Graz University of Technologyによるまとめページ(英語)
- この記事のURL: