マイクロアーキ・サイドチャネルの原理 ─ Spectre/Meltdown系
投機実行はなぜ秘密を漏らすのか。SpectreとMeltdownとMDSが残す痕跡と読み出し手口、KPTIやretpolineといった緩和の構造を原理から押さえ、性能対策とのトレードオフを見極められます。
- 1.投機実行は誤った経路でも一瞬メモリへ触れ、キャッシュ状態という観測可能な痕跡を残す。アーキ状態は巻き戻されてもマイクロアーキ状態は戻らないのが根本原因。
- 2.Spectreは分岐予測器を誤訓練して被害者に越境ロードさせ、Meltdownは例外確定前の不正ロードを、MDSは内部バッファの残留データを盗む。痕跡はFlush+ReloadやPrime+Probeで読み出す。
- 3.緩和はKPTIでアドレス空間を分離し、retpolineや分岐予測の隔離・フラッシュで誤訓練経路を断ち、境界チェック後の投機を止める。いずれも性能と引き換えになる。
投機実行が「痕跡」を残すという根本問題
現代CPUはアウトオブオーダ実行と分岐予測を使い、分岐の結末を待たずに先へ進みます。予測を外せば誤った経路で実行した命令を破棄し、レジスタやメモリといったアーキテクチャ状態を巻き戻します。プログラムから見れば、投機は「なかったこと」になる――はずでした。
問題は、巻き戻されるのはアーキ状態だけで、マイクロアーキ状態は戻らない点にあります。投機中にあるアドレスへロードすれば、そのデータはキャッシュに載ったままです。命令自体は破棄されても、「どこに触れたか」というキャッシュの占有状態は痕跡として残ります。攻撃者はこの残留を計測し、本来読めないはずの値を間接的に復元します。これがマイクロアーキ・サイドチャネルの核心です。
アーキ状態はISAが定義する観測可能な状態(レジスタ、メモリ、フラグ)で、投機失敗時に正しく巻き戻されます。マイクロアーキ状態はキャッシュ・TLB・各種内部バッファなど実装上の状態で、ISAの可視範囲外ゆえに巻き戻し対象外です。「機能的には正しいが情報を漏らす」隙はこのギャップに生まれます。
痕跡を読む ── Flush+Reload と Prime+Probe
漏れた秘密は、まず秘密値に応じて異なるキャッシュラインへアクセスさせる「符号化」を経て、キャッシュの状態差として残ります。これを復元する代表手法が次の2つです。
| 手法 | 前提 | 計測の仕組み |
|---|---|---|
| Flush+Reload | 被害者と共有するメモリ(共有ライブラリ等)がある | 対象ラインをclflushで追い出し、被害者実行後に再ロードして速ければヒット=被害者が触れたと判定 |
| Prime+Probe | 共有メモリ不要、同一キャッシュセットを使えればよい | 自分のデータでセットを埋め、被害者実行後に再アクセス。遅くなったライン=被害者に追い出されたセットと判定 |
| Evict+Time | 対象処理の実行時間を測れる | 特定セットを追い出してから処理時間を測り、遅延の有無でアクセス有無を推定 |
いずれも「キャッシュヒットは速く、ミスは遅い」という計測可能な時間差を、秘密の1ビット1ビットに翻訳する装置です。Flush+Reload は共有メモリが要る代わりに精度が高く、Prime+Probe は共有を前提とせず適用範囲が広いという住み分けがあります。
Spectre ── 分岐予測器を誤訓練する
Spectreは被害者プロセス自身に越境ロードを実行させる攻撃です。代表的なVariant 1(境界チェックバイパス)は、次のような配列アクセスを標的にします。
if (x < array1_size) // 境界チェック
y = array2[array1[x] * 64]; // x が範囲内のときだけ実行されるはず
攻撃者はまず正当な x を何度も与え、この分岐を「Taken(範囲内)」だと予測器に誤訓練します。その後で巨大な x を渡すと、array1_size のロードが遅延している隙にCPUは分岐を投機的にTakenと予測し、array1[x](範囲外=秘密)を読み、その値で array2 にインデックスアクセスします。境界チェックが確定すると投機は破棄されますが、array2 のどのラインがキャッシュされたかという痕跡が残り、Flush+Reload で秘密値が割れます。
Variant 2(分岐ターゲット注入)はさらに強力で、間接分岐の飛び先を予測するBTBを攻撃者が誤訓練し、被害者の投機実行を任意のコード片(ガジェット)へ誘導します。Spectreは権限境界を越えず被害者のアドレス空間内で完結するため、ソフトウェアのバグではなく投機実行そのものの性質を突きます。
Meltdown ── 例外確定前の不正ロード
Meltdownは権限チェックの順序の隙を突きます。ユーザー空間からカーネルアドレスをロードすると最終的に例外(保護違反)になりますが、一部のCPUでは例外が確定してリタイアする前に、ロードしたデータが後続命令へ投機的に流れてしまいます。
; rcx = カーネルアドレス(本来は読めない)
mov al, [rcx] ; 投機的にロード(後で例外になる)
shl rax, 6 ; 値 × 64 でインデックス化
mov rbx, [array + rax] ; 秘密値に応じたラインをキャッシュへ
例外で al の値はアーキ状態としては無効化されますが、array のどのラインが載ったかは残り、Flush+Reloadで復元できます。Spectreとの本質的な違いは、Meltdownが自分のプロセスの権限を越えてカーネルメモリを直読みする点です。許可確認とデータ転送が論理的に同時でなく、転送が先行しうる実装に依存します。
両者を混同しがちですが構造が異なります。Meltdownは権限境界を越える不正ロードで、後述のKPTIなどアドレス空間分離で塞げます。Spectreは権限を越えず被害者自身に投機させるため境界分離では防げず、誤訓練経路を断つ別の対策が要ります。「Meltdownは是正可能な実装バグ寄り、Spectreは投機実行に内在する設計問題」と位置づけると整理できます。
MDS ── 内部バッファの残留を盗む
MDS(Microarchitectural Data Sampling)は、キャッシュよりさらに内部のバッファに着目します。ロード/ストアの途中データを保持するストアバッファやラインフィルバッファ、ロードポートには、直前の処理のデータが残ることがあります。フォルトや特定条件でロードが失敗したとき、CPUがこれらのバッファの古い残留値を投機的に転送してしまう実装がありました(RIDL/Fallout/ZombieLoad などの呼称で知られます)。
攻撃者は失敗ロードを大量に発生させ、漏れてきた残留値を統計的に集めて秘密を再構成します。MDSはアドレスを指定して狙い撃つのではなく、たまたまバッファに居合わせたデータをサンプリングする性質を持ち、SMT(同時マルチスレッディング)で物理コアを共有する別スレッドからの漏洩が深刻になります。
緩和の構造 ── どこで投機を断つか
緩和は「漏れる経路のどこを断つか」で分類できます。
- KPTI(カーネルページテーブル分離):Meltdown対策。ユーザーモード時にカーネルページをTLB/ページテーブルから外し、不正ロードの対象を物理的に存在させません。代償としてシステムコールごとにアドレス空間を切り替えるためTLBフラッシュが増え、syscall負荷が上がります。
- retpoline:Spectre Variant 2対策。間接分岐をBTB予測に頼らない
call/retの構造に置き換え、投機の飛び先を無害なループ(待機)に固定して攻撃者のターゲット注入を無力化します。 - 分岐予測器の隔離・フラッシュ:IBPB(分岐予測バリア)やSTIBPでスレッド間・コンテキスト間の予測器共有を断ち、誤訓練の持ち越しを防ぎます。eIBRSのようにハードウェアで特権レベル間の予測流用を抑える方式もあります。
- 境界後の投機停止:Variant 1には
lfenceなどの投機バリアを境界チェック直後に挿入し、チェック確定まで後続ロードを投機させません。配列インデックスを範囲内へ強制マスクする手法も併用されます。 - バッファのオーバーライト:MDS対策の
VERW命令で、特権境界を越える前にマイクロアーキバッファを上書きし、残留値を消します。
これらはいずれも投機の効きを意図的に削るか、追加のフラッシュ・バリアを挟むため性能を犠牲にします。KPTIはsyscall多発ワークロードを、retpolineや分岐バリアは間接分岐の多いコードを重くします。新しい世代のCPUはMeltdown/MDS系を設計段階でハードウェア的に塞ぎ、ソフトウェア緩和を不要化する方向に進んでいますが、Spectre系の根は投機実行そのものにあり、完全な無効化は困難なまま残っています。
「アーキ状態は巻き戻るがマイクロアーキ状態(キャッシュ)は残る」が全体の根本原理です。「Spectre=分岐予測の誤訓練で被害者に越境投機させる/Meltdown=例外確定前の不正ロードで権限越え/MDS=内部バッファの残留サンプリング」の対応、計測は「Flush+Reload=共有メモリ前提・高精度/Prime+Probe=共有不要・セット競合で判定」、緩和は「KPTI=Meltdown、retpolineと分岐バリア=Spectre v2、lfenceとマスク=v1、VERW=MDS」を結びつけて覚えましょう。
まとめ
- 投機実行が誤経路でもメモリに触れ、巻き戻されないキャッシュ状態として痕跡を残すことが、全サイドチャネルに共通する根本原因。
- Spectreは分岐予測器を誤訓練して被害者自身に越境ロードさせ、Meltdownは例外確定前の不正ロードで権限を越え、MDSは内部バッファの残留をサンプリングする。
- 残った痕跡は、共有メモリ前提のFlush+Reloadや、セット競合を使うPrime+Probeで秘密の値へと復元される。
- 緩和はKPTIによる空間分離、retpolineと予測器隔離による誤訓練遮断、lfenceやVERWによる投機・残留の停止に整理でき、いずれも投機の利得を削るトレードオフを伴う。
CPU/メモリ/ディスク Article
マイクロアーキ・サイドチャネルの原理 ─ Spectre/Meltdown系を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
サイドチャネル
比較で見る軸
難易度: advanced / カテゴリ: CPU/メモリ/ディスク / タグ数: 6
導入後に効く点
Spectreは分岐予測器を誤訓練して被害者に越境ロードさせ、Meltdownは例外確定前の不正ロードを、MDSは内部バッファの残留データを盗む。痕跡はFlush+ReloadやPrime+Probeで読み出す。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- CPU/メモリ/ディスク
- タグ数
- 6
判断チェックリスト
- 自社の用途が「サイドチャネル / 投機実行」に近いか確認する。
- 強みである「投機実行は誤った経路でも一瞬メモリへ触れ、キャッシュ状態という観測可能な痕跡を残す。アーキ状態は巻き戻されてもマイクロアーキ状態は戻らないのが根本原因。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。