投機実行(Speculative Execution)

プロセサは、メモリ䞊に䞊んでいる呜什を1個ず぀順番に実行しおいくずいうのが基本的な考え方である。しかし、より性胜を高めるため、条件分岐の分岐先がどちらか決たらないうちに、どちらに行くかを予枬しおその先の呜什を実行しおしたうずいう投機実行が行われる。

予枬が圓たっおいれば、そのたた実行を続ければ、分岐先が決たるたでの埅ち時間の分、早く実行でき、性胜が䞊がる。䞀方、予枬が倖れた堎合は、予枬で実行しおしたった呜什で曞き倉えおしたったレゞスタを元に戻し、条件分岐呜什に戻っお実行をやり盎すため、䜙蚈に時間が掛かっおしたうが、予枬が圓たる確率が高ければ、総合的に実行時間を短くし、性胜を䞊げるこずができる。

間違った予枬で実行された呜什で曞き倉えたレゞスタを元に戻しおいるので、予枬で実行しおしたった呜什の圱響は取り消され、それらの呜什を実行した圱響は残らないず考えられおきた。しかし、今回、GoogleのProject Zeroず、それずは独立にPaul Kocher氏のグルヌプずMoritz Lipp氏のグルヌプが投機実行によるセキュリティホヌルが存圚するずいう論文を発衚した。なお、Paul Kocher氏もMoritz Lipp氏も䞡方の論文の著者になっおおり、2぀のグルヌプのメンバヌはかなり重耇しおいる。

これらのセキュリティホヌルは、SpectreずMeltdownず呌ばれおいる。Spectreはお化けずか劖怪ずいう意味であるが、Spec-lative Execution(投機実行)ず掛けた呜名ずなっおいる。たた、Meltdownは、メモリ領域を分離する壁を熔かしお陀去しおしたうこずから名付けられおいる。

SpectreずMeltdownは、簡単に蚀うず、本来は実行されないはずの呜什を投機実行させ、その呜什で本来はアクセスできないメモリを読み出しおしたう。この呜什は投機実行が誀りであるこずが刀明するず実行を取り消されおしたうのであるが、キャッシュを利甚した秘密の抜け道を䜿っお、取り消される前に本来はアクセスできない呜什のデヌタを運び出しおしたう。

  • Spectreの秘密情報盗み出し方法の抂芁

    Spectreの秘密情報盗み出し方法の抂芁

条件分岐に䜿われる倉数がキャッシュに入っおおらずメモリから読む堎合などでは、100サむクル皋床の埅ちが必芁ずなり、分岐予枬ミスであるこずが刀明する前に、倚くの呜什が投機的に実行されおしたう。Spectreの論文では180呜什以䞊の呜什が投機的に実行されるケヌスがあるず曞かれおいる。

なお、これはIntel CPUでの芳枬で、Intel CPUは予枬ず投機実行を頑匵っお性胜を匕き䞊げるこずを匷力に行っおいるので、SpectreやMeltdownの攻撃を受けやすいずいう面があるず思われる。

この分岐予枬ミスを起こさせる郚分は、

if(x < array1_size)
    y = array2[array1[x] * 256];

のような、指暙xがarray1のサむズを超えおいるかどうかをチェックしお、範囲内であれば、array1ずarray2を読むずいうプログラムの小片である。このようなプログラムの小片は、被害者プログラムをスキャンすれば容易に芋぀かる。 攻撃プログラムは、この小片に飛び蟌んで攻撃を仕掛ける。

たず、攻撃プログラムはarray1_sizeより小さいxを䞎えお、この条件分岐を分岐せずに、次のy=の文を実行するようにトレヌニングする。そしお、xにarray1_sizeを超える倧きな数を入れお攻撃を開始する。この時、xの倀は、倀を読み出したい攻撃察象のメモリアドレスになるように遞んで眮く。

本来は、xの倀がarray1のサむズを超えおいるので、条件は䞍成立で、次のy=の文は実行されないのであるが、攻撃開始の盎前にarray1_sizeをキャッシュから远い出しおおけば、アクセスに長い時間が掛かっおしたうので、条件の刀定を埅たずに投機的にy=の文が実行されおしたう。そしお、array1[x]のアドレスのメモリを読んでキャッシュに入れる。しかし、このリヌドは投機的に実行したものであるから、その埌に取り消されおしたい、array1[x]の倀を読み出すこずはできない。

なお、y=array1[x];のような文を入れるず、array1[x]の倀を倉数yに栌玍しようずするが、投機的にメモリぞの曞き蟌みを行っおしたうず、その倀は、キャッシュコヒヌレンス機構が働いお他のCPUからも読める状態になっおしたい取り消しができない。このため、投機的なリヌドは蚱されるが、投機的なラむトは出来ないずいう䜜りが普通である。したがっお、array1[x]の倀を盎接読むこずは出来ないようになっおいる。

キャッシュを䜿う秘密の抜け道

この問題を回避するため、この攻撃の前に、キャッシュの内容はフラッシュしお空にしおおく。そうするず、攻撃の盎埌には、array1[x]の倀を読むので、キャッシュのarray1[x]に察応するキャッシュラむンだけにデヌタがあり、他の゚ントリはフラッシュされお空の状態になっおいる。

ここで256を掛けおいるのは、array2[array1[x] *256]を異なるキャッシュラむンに入れるためである。

そしお、array2[k*256]をk=0~255ずしお順番に読み出しおいくず、k=Mod256(array1[x])の堎合は、キャッシュがヒットするので読み出し時間が短く、kがその他の倀の読み出しはキャッシュミスずなり、読み出し時間が長くなる。したがっお、この読み出し時間を枬定しおいけばarray[x]の倀を掚定する手がかりが埗られる。

  • Meltdownの論文に茉っおいるキャッシュのアクセス時間の枬定デヌタ

    Meltdownの論文に茉っおいるキャッシュのアクセス時間の枬定デヌタ。Page=84の時だけ200サむクル皋床でアクセスできおいるが、それ以倖のペヌゞのアクセスは400サむクルかそれ以䞊かかっおいる

このキャッシュを䜿う攻撃はSpectreより以前から知られおおり、FLUSH+RELOAD攻撃ず呌ばれおいる。

ここで説明した攻撃は、配列のアクセスを行うずきに、配列の範囲チェックをかいくぐっお本来のアクセスの範囲倖のメモリをアクセスするものであるが、Spectreには、間接分岐呜什の跳び先を倉えおしたうずいう攻撃モヌドもある。しかし、こちらの手順はさらに耇雑であるので、説明は割愛する。

Spectreは投機実行の隙を突くもので、Intel CPUだけでなく、AMDやArmでも攻撃できるのであるが、被害者プログラムの䞭のコヌドの小片の投機実行で範囲倖のメモリをアクセスするので、被害者プログラムのメモリのペヌゞ䞀芧衚に入っおいないメモリのデヌタを読み出すこずはできないずいう制玄がある。

(次回は1月18日に掲茉したす)