このブログは「風見鶏」が、日々気づいたこと、思ったこと、したことを気ままに綴る日記です。2008年9月に旧ブログから引っ越しました。バックアップをご覧ください。

ゲストログインがうまくできないので、コメントを承認制にしました。スパムでないことを確認の上、公開します。判断はあくまで「風見鶏」の主観で行いますので、文句は受け付けません。(笑)承認が遅れることもままあると思いますが、あしからず・・・

システムトラブルのため、2015年以降のブログ画像と2018年5月以降の記事が消失しました。画像は鋭意、新しい物から順次復旧中ですが記事については残念ながら戻せません。残念ですが、あきらめます。

なお、ここに書いていることは、あくまで個人的な思いであり、いかなる組織をも代表、代弁するものではありませんし、無関係ですので念のため。

新年早々のMeltdown

| コメント(0) | トラックバック(0)

年明けからちょっとバタバタしていて、日記を書くのがおっくうになり、サボってしまった。なんとなく気が乗らないというか、まぁ、書くネタも、それほどなかったので。

今日は、朝から実家の番猫を捕獲してケージに押し込め、獣医さんに連れて行って爪切りなどのメンテナンス。結構力があるので暴れると母親の手には負えないから、この作業は最近私の仕事になっている。最初は不満たらたらで鳴きまくっていたのだけれど、やがて観念したようで、とりあえずはおとなしく爪切りを終え、実家に帰ってケージを開けるやいなや、飛び出して奥の間にお隠れになった。かなり爪が伸びて本人(猫)も気になっていたのか、あちこち引っ掻いて実家のなかが結構大変なことになっていたので、ちょっとこれで落ち着きそうである。

それから、またしばらく散歩に出て、2時間弱歩き回ってから実家に戻る。昨日の朝降った雪がまだ残っていて、ちょっと足下が悪かったが、昨日は悪天候のため休養日としたので、今日はその分も頑張って歩いた。

それから、ちょっと一仕事・・・と思ってPCに向かったのだが、このところ話題のCPU脆弱性の話が気になって、論文を読みふけってしまい、結局今日はそれで終わってしまった。読んだMeltdown攻撃の概要は、そのあとFacebookに書いておいたのだが、以下のような感じである。


最近のCPUは、命令の実行を高速化するために、複数の命令を並列実行する機能を持っている。たとえば、ある命令がメモリからのデータ読み込みを必要とするため、待ち時間が生じるような場合、次の命令が前の命令の結果に依存しなければ、それを待ち時間の間に実行するというような処理である。これをアウトオブオーダー実行(順序によらない実行)と言う。最近のプロセッサ命令は、実行過程でよりプリミティブなマイクロコードに分解されるため、こうした前処理は常に先行して行われ、依存関係に直接関わる実行ステージのみが未実行の状態で引き続く命令が待機することになる。これにより、命令列の中の複数の命令が並行して実行されながら、結果を保留した状態で待機していて、先行する命令の完了と同時に結果が反映される。また、こうした命令列の中に分岐(条件分岐)命令が存在した場合は、過去の分岐状況に基づいて予測された分岐結果に基づいて、次にどの命令を先行するか決定して実行する。予測が外れた場合、並行して実行された結果は捨てられ、正しいパスで再度実行される(かえって効率が低下する)ため、こうした方式は投機的実行と呼ばれている。

今回、問題になったのは、並行して実行される命令にOSカーネルのみがアクセス可能なメモリ領域にアクセスするような命令が含まれていた場合、たとえ、プロセス自体に権限がなくても(ユーザプロセスであっても)それが実行されてしまうという点。もちろん、その実行結果が確定された段階では、メモリアクセス例外が発生して処理が中断されるため、直接プログラム側からその値を確認することはできないのだが、実際は、この実行によって、アクセスしたメモリのページがキャッシュに読み込まれるといった副作用が生じる。また、例外発生までに一定のタイムラグが生じるため、先行する命令の結果を受けた後続命令もある程度実行されてしまうため、こうした副作用を、読み込んだデータに依存する形で発生させることができる。この問題は、ソフトウエアへの依存性はなく、こうしたプロセッサのアーキテクチャに存在するため、様々なOSプラットフォームや同種のアーキテクチャを持つCPUで発生する。

あるページがキャッシュされているかどうかは、そのページに対するアクセス速度を調べることで判定ができるが、これを使用してサイドチャネルを作る手法は既にいくつか既知になっている。(たとえば、Flush + Reloadなど)キャッシュを削除しておいて、他のプロセスがどのページを再度キャッシュしたかを調べることができれば、これを悪用してプロセス間でデータ受け渡しが可能になる。(もちろん、そう単純ではないが・・・)

たとえば、先に実行される命令が、カーネルページのアドレスにアクセスして1バイトのデータを取得した後、その値×ページサイズをインデックスにして、後続の命令が実際に実メモリがマッピングされている仮想アドレスにアクセスしたとする。当然、カーネルページへのアクセスでは例外が発生することになるが、この例外発生の前に、カーネルページへのアクセスによるデータが確定して、準備が整ってそれを待っていた後続の命令が実行されてしまう。つまり、ある先頭アドレス+読み出したデータ×ページサイズの位置のページがキャッシュされることになる。もちろん、そのプロセス自身は例外によって読み出したデータを知ることができないが、他のプロセスから、どのページが新たにキャッシュされたかを知ることができれば、読み出したデータの値がわかる。これが、Meltdown攻撃の基本的な原理。サイドチャネル攻撃との組み合わせで効率が悪いように思えるが、それでも平均して500KB/s程度のデータ読み出しが低いエラーレートで可能とのことである。

CPUアーキテクチャの問題であるため、この攻撃を原理的に防ぐ方法は、ハードウエアの改修以外にない。

一方、Linux等のOSでは、ユーザプロセスの仮想メモリ空間に、すべてのカーネルメモリと実メモリがマッピングされている。このことによって、上の攻撃で、最悪の場合、全実メモリの情報やカーネルメモリ内の情報を読み出すことができる。もちろん、それを悪用するためにはカーネルメモリの構造や他のアプリケーションのメモリ構造を知っている必要がある。また、カーネルにおいても、最近ではASLR(KASLR)つまり、アドレス配置のランダム化が行われており、攻撃の難易度は高くなっているが、これも実際のマッピングを推測する手法はいくつか存在する。

Windowsにおいては、Linuxのように全実メモリをプロセス仮想空間にマップするようなことは行っていないが、依然として重要な情報を持つカーネルページがマップされているため、Meltdown攻撃が機能する可能性が高い。

Linuxにおいては、最新の改修で KAISER(KPTI)と呼ばれるパッチが導入された。これにより、当面、全実空間やカーネルページの大部分にアクセスできなくなるが、依然として一部のカーネルページにはアクセス可能である。ただ、KASLRを介してマッピングがランダム化されていることもあって、攻撃難度はかなり上がることになる。当面は、これ(KAISER)が最良の対策となる。ただ、こうしたページに含まれるカーネル空間のポインター値からKASLRのマッピングを推測できる可能性はあり、最終的にはこうしたポインターのすべてをユーザ側からアクセスできなくする必要があるとのこと。

WindowsやMacOS X, iOSにおいても同様のパッチが既に提供されている。


思うに、この攻撃自体の難易度は高いものの、影響範囲が様々なOSプラットフォームやハードウエアを越えて非常に広いことから、有効な攻撃コードが出回る可能性も否定できない。仮想環境やコンテナ環境などにおいても、隔離環境からホストOSや他のインスタンスの情報にアクセスできるなど広く影響を与えることから、とりわけクラウドサービス環境における対応は急務と言えるだろう。

さて、そんな一日・・・。明日は午前中に実家を離れ、帰途につく予定である。

トラックバック(0)

トラックバックURL: https://www.kazamidori.jp/MT/mt-tb.cgi/3411

コメントする

月別 アーカイブ

この記事について

このページは、風見鶏が2018年1月 5日 21:48に書いた記事です。

ひとつ前の記事は「謹賀新年」です。

次の記事は「そろそろ始動、そしてまた歳を食う」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。