レガシーガジェット研究所

気になったことのあれこれ。

Foreshadow/L1TF(Level 1 Terminal Failure)について

ソースは以下。

当ドキュメントは上記の全訳となる。

L1TFとは

PTEの存在フラグ(Pesent. PTEの0bit目)がクリアされている、若しくは他の予約済みフラグがセットされている読み取り可能なPTE(page table entry)が仮想アドレスを扱う際に、L1キャッシュを用いた権限の無い投機的実行によるデータアクセスを可能とするハードウェアに起因する脆弱性である。

影響のあるプロセッサ

Intel製CPUのほとんどに影響がある。なお以下のプロセッサは該当しない。

  • Centaur, AMD製などのIntel以外のプロセッサ
  • CPU familyが6未満の古いモデル
  • Intel Atomシリーズ
  • Intel Core Duo Yonahの派生
  • Intel ZEON PHI Family
  • IntelのMSRに"IA32_ARCH_CAPABILITIES"を持っており且つ"ARCH_CAP_RDCL_NO"フラグがセットされているプロセッサ

関連CVE

  • CVE-2018-3615 L1 Terminal Fault SGX related aspects
  • CVE-2018-3620 L1 Terminal Fault OS, SMM related aspects
  • CVE-2018-3646 L1 Terminal Fault Virtualization related aspects

問題

存在フラグがクリアされており且つその他のフラグがセットされているPTEに関連する仮想アドレスに命令がアクセスすると、投機実行された命令が無効なPTEを無視し、あたかも当該ページがメモリ上に存在しアクセス可能で、アドレスbitを用いてページ変換をしたかのように、L1キャッシュからデータを読み出す。

これが投機実行のメカニズムであり、最終的にその命令はページフォールト例外を発生させる。このデータ読み込みの本来の振る舞いが他の投機実行命令に対してMeltdownのようなサイド・チャネル攻撃を可能とするような機会を悪意あるコードに与えてしまう。

Meltdownがユーザ領域を壊しカーネル保護領域まで到達できるように、L1TFもシステム全ての物理メモリに攻撃可能で、且つ全ての保護ドメインにアクセスが可能となる。投機実行はEPT保護の仕組みをバイパスできるためMeltdownのようにSGXの攻撃や仮想マシン内部からも攻撃が可能となる。

攻撃の流れ

1. 悪意あるユーザ領域

存在フラグがクリアされたPTEのアドレス部には任意の値をOSが設定する。これは悪意あるユーザアプリケーションに当該PTEが解決する物理アドレスへの攻撃を可能にしてしまう。いくつかのケースではユーザ領域から悪意を持ってPTEのアドレス部に影響を与えることもできる、よって当該攻撃が決定的となり、より実践的なものとなる。

Linux Kernelでは当該攻撃ベクターに対する緩和策、"PTE Inversion"を保持しており、恒久的に有効でパフォーマンスにも影響はない。Linux Kernelでは存在フラグがクリアされているPTEのアドレス部が、キャッシュ済みの物理アドレス領域を指さないことを保証している。

最近のカーネルにアップデートされているシステムは悪意あるユーザ領域アプリケーションからの攻撃に対して保護されていると言える。

2. 悪意あるゲストマシン

L1TFが直接PTEを操作できるような悪意のあるゲストOSに全てのドメイン保護を破壊することを可能としてしまったり、"PTE Inversion"緩和策が無効で保護されていないゲストカーネルで動作している悪意あるユーザ領域アプリケーションにホストの物理メモリに対する攻撃を可能にしてしまう。

仮想化コンテキスト内部のL1TFにおける特別な側面は、同期マルチスレッド(SMT)である。Intelの実装ではSMTはHyperThreadingと呼ばれている。影響下にあるプロセッサ上のスレッドがL1キャッシュを共有しているのは今回とても大切な要素となってくる。この不備がL1キャッシュに存在するデータに対する攻撃を可能にするので、1つスレッド上で動作している悪意あるゲストマシンは同一のCPUコア上のスレッドで動作しているコンテキストで扱っているL1キャッシュに存在するデータに攻撃することができる。当該コンテキストはホストOS領域、ホストユーザ領域、若しくは他のゲストマシン領域に成り得る。

プロセッサがEPTをサポートしていない場合は、シャドウページングのコンテンツをハイパーバイザが検査していない場合のみ、攻撃が成功する。

これらの攻撃ベクタへの緩和策は存在するが、パフォーマンスに著しく影響を与えることを理由にLinux Kernelではデフォルトで緩和策は有効となっていない。カーネルはデプロイ方法に依存するその問題に対してアプローチするために活用できるメカニズムを複数提供している。その緩和策、保護領域そして影響については次のセクションで言及する。

デフォルト緩和策とその選択方法に関する根本原理については当ドキュメントの最後に記載している。

L1TFに関連するシステム情報

Linux KernelはL1TFのステータス情報を列挙するためのsysfsインターフェースを用意している。システムが脆弱かどうか、どの緩和策が有効になっているかなどがある。

関連のあるファイルは以下となる。

/sys/devices/system/cpu/vulnerabilities/l1tf

上記ファイルに設定可能な値は以下。

指定 説明
Not affected プロセッサが脆弱ではない
MitigationPTE Inversion ホスト保護が有効である

もしKVM/VMXが有効でプロセッサが脆弱だった場合は以下の情報を"Mitigation: PTE Inversion"のパートに追記する。

  • SMT status
指定 説明
VMX: SMT valnerable SMTが有効
VMX: SMT disabled SMTが無効
  • L1D Flush mode
指定 説明
L1D vulnerable L1Dフラッシュが無効
L1D conditional cache flushes L1Dフラッシュがある条件下のみ有効
L1D cache flushes L1Dフラッシュが無条件で有効

各保護手法を適応した結果については次のセクションで言及する。

ホストに対する緩和策のメカニズム

カーネルは悪意あるユーザ領域のアプリケーションから行われるL1TFの攻撃に対して保護されている。

ゲストに対する緩和策のメカニズム

1. VMENTER時のL1Dフラッシュ

ゲストマシンからL1キャッシュ状に存在するデータに対して攻撃を不可能にすることを確実にするため、ハイパーバイザではゲストモードに入る前にL1キャッシュをフラッシュする。

L1キャッシュをフラッシュすることは、悪意のあるゲストマシンからアクセスされるべきではないデータを取り除くだけでなく、そのゲストOS自体のデータもフラッシュすることになる。L1キャッシュをフラッシュすることは、プロセッサがフラッシュしたデータを再びL1キャッシュに乗せるためのパフォーマンス的な影響が起こる。それはVMEXIT/VMENTERを行う頻度に依存し、そして計算の種類によっては1 ~ 50%の範囲でパフォーマンスの低下が見受けられる。ゲストマシンのVMEXIT/VMENTERがレアなケースではぺフォーマンスの低下は最小にとどまる。Virtioと割り込みを送信するようなメカニズムは、VMEXITの呼び出しに限定され、そして最小となるようにデザインされているが、特殊な設定とアプリケーションの動作によってはVMEXITの高い呼び出し頻度の影響を受けるかもしれない。

カーネルは以下の2種類のL1キャッシュのフラッシュモードを提供している。

  • conditional(cond)
  • unconditional(always)

"conditional"モードでは、VMENTER前の検査されたコードの実行を行うためのVMEXIT後のL1キャッシュのフラッシュを回避する。それらのコードは秘密情報や他のデータの漏洩を避けるために検証されているが、攻撃者はハイパーバイザのメモリレイアウト情報を漏洩することができる。

"unconditional"モードではVMENTERの呼び出しの度にL1キャッシュをフラッシュするため、保護効果を最大化できる。オーバーヘッドは"conditional"より大きくなる。VMEXITの回数やプロセスの動作に依存するのでオーバーヘッドに関しては正確に定量評価することはできない。

一般的に推奨されるのはVMENTER時にL1キャッシュをフラッシュすることである。カーネルのデフォルトでは影響のあるプロセッサに対して"conditional"モードとなる。

注意:同一コア上で動作するスレッドはL1キャッシュにそのデータを書き戻すため再度攻撃可能となるのでL1キャッシュのフラッシュ自体がSMTの問題を解決することはできない。

L1キャッシュはカーネルコマンドライン若しくはsysfsのコントロールファイルを通して管理者権限で操作することができる。

2. ゲストマシンの論理CPUを指定した物理CPUに束縛する

SMTの問題への取り組みとして、ゲストを指定の物理コアに束縛することが可能である。この適切なメカニズムは占有したCPUを使用することで、他のゲストおよびホストが当該CPU上で動作を行わないことが確実となる。

ゲストマシンが同じ物理コア上のスレッド上で動作した場合、自身の限られたホストのメモリ又は自身のメモリ領域にのみ攻撃が成功することになる。

他のゲストOSのコンテキストとホストOS(ハイパーバイザ)のコンテキストが対になるスレッド上で動作する場合、ホストのメモリは攻撃可能となる。ホストOS上のコンテキスト情報はホストOSの実行に依存する、割り込みや例外そしてカーネルスレッドが例として挙がる。それらのコンテキスト上のあるデータは、コードに対する深い視察をしない攻撃者にとっては有益でない情報にはなり得ない。(攻撃者にとって有益である)

注意:ゲストマシンを物理CPUに束縛することは、ホストの動作におけるCPUの利用に不利な影響を与え、CPUのバランシング処理にも影響を及ぼすだろう。特定の状況ではSMTを無効にすることが現実的な選択肢をなるかもしれない。

3. 割り込みの相関関係

割り込みを論理CPUに束縛することは可能である。これは一般的に言うと正しいわけではない、なぜなら割り込みのタイプによってはそのCPUに対して起こるものも存在するからだ、ローカルタイマー割り込みなどが例としてあげられる。管理者が操作しなくともマルチキューデバイスの割り込みは特定のCPUに割り当てられる。

信頼できないゲストマシンが動作するCPUに対する割り込みの発行を避けることで、攻撃対象領域を減らすこともできる。

信頼できないゲストマシンが動作しているCPUに対して割り込みが束縛されているかというのは、システム設定やシステムの状態に依存するので、攻撃者に有益な情報を提供してしまう。いくつかの割り込みはホストOSのメモリレイアウトのヒントを与えるに過ぎず有益な情報を露呈することはないと仮定されるが、一般的な推測を立てるのは不可能であると言える。

/proc/irq/$NR/smp_affinity[_list]ファイルを管理を通して設定することで割り込みを操作することができる。

4. SMTの操作

SMTの問題を回避するにはおそらくSMTを完全に無効とするほかないだろう。SMTを無効にすることはパフォーマンスに致命的な影響を与えるが、それはホストの状態や動作に依存する。SMTを無効にすることに係る影響は、特定のCPUにゲストマシンを束縛するような他の緩和策による影響に対して不利に働くだろう。

カーネルはSMTのステータスを取得、操作するためのsysfsインターフェースを提供している。加えてSMTを操作するためのCLIを提供する。

カーネルCLIは以下のオプションから形成される。

モード 説明
nosmt ブート中に2番目のCPUに影響する。カーネルはブートプロセス中に存在する全てのオンラインなCPUを用いようとする。"nosmt"は各コアのプライマリスレッドだけを有効化する。マシンチェック例外に関連するIntelプロセッサの設計不備のため、プライマリでないスレッドは一時的に使用される。"nosmt"はsysfsのインターフェースを通じて解除できる。
nosmt=force "nosmt"と同等の影響を持つが、sysfsを通じて解除できない。

sysfsインターフェースは以下の2種類のファイルを提供する。

  • /sys/devices/system/cpu/smt/control
  • /sys/devices/system/cpu/smt/active

/sys/devices/system/cpu/smt/control

当該ファイルSMTの操作状況の読み出しやSMTの有効無効を切り替える機能を提供する。

ステータスは以下。

モード 説明
on SMTをCPUがサポートしており且つ有効となっている。全ての論理CPUは全ての制限無しで有効/無効が切り替わる
off SMTをCPUがサポートしているが無効となっている。プライマリスレッドのみが全ての制限無しで有効/無効と切り替わる。プライマリスレッド以外を有効にすることはできない。
forceoff "off"と同じだが操作はできない。ファイルの書き込みでの操作はできない
notsupported CPUがSMTをサポートしていないため、SMTに起因するL1TFの影響を受けない。ファイルヘの書き込みで行うSMTの操作はできない

当該ファイルに書き込むことで設定可能なオプションは以下の通り。

  • on
  • off
  • forceoff

/sys/devices/system/cpu/smt/active

当該ファイルはSMTが有効になっているのかを保持している。例えば物理コアやスレッドが有効になっているかなど

SMTの操作はブート時にカーネルコマンドラインを通じて、L1キャッシュの設定と組み合わせて指定可能である。

5. EPTの無効化

EPTを無効にすることはSMTが有効になっていたとしても仮想マシンにはL1TFに対する最大の緩和策となる、なぜなら仮想マシンのEPTはハイパーバイザによって管理され精査されるからである(シャドーページング)。特にMeltdownの緩和策を有効にしている時は、EPTを無効にすることはパフォーマンスに重大な影響を及ぼす。

EPTはハイパーバイザ内の"kvm-intel.ept"パラメータを通して無効にすることができる。

SMT、EPTの無効化に係るパフォーマンスに対する影響に取り組むため、現在も新たな緩和策を調査・開発している。

カーネルコマンドライン上での緩和操作

カーネルコマンドラインはL1TFを操作することをブート時の"l1tf="オプションを用いることで可能とする。有効なパラメータは以下。

パラメータ 説明
full L1TFの脆弱性に対する完全な緩和策を提供とする。SMTを無効にし、ハイパーバイザに対して全ての緩和策を講じる。例:無条件でL1キャッシュをフラッシュする。
full,force fullと同じだが、SMTとL1キャッシュを動作中に操作することは不可能。暗黙的にコマンドラインオプションで"nosmt=force"を指定したことになる。例:sysfsの操作でSMTを無効化
flush SMTを有効のままにし、ハイパーバイザのデフォルトの緩和策を有効にする。例:条件付きのL1フラッシュなど。ブート後もsysfsと通じてSMTとL1キャッシュのフラッシュを操作できる。ハイパーバイザは最初のVMを起動した際に安全でない可能性がある設定に対して警告を表示するだろう。例:SMTを有効にし、L1キャッシュを無効化する
flush,nosmt SMTを無効にし、ハイパーバイザのデフォルトの緩和策を有効にする。例:条件付きでL1キャッシュをフラッシュする。ブート後もsysfsを通じてSMTの操作とL1キャッシュの操作は可能。ハイパーバイザは最初のVMを起動した際に安全でない可能性がある設定に対して警告を表示する。例:SMTを有効にし、L1キャシュを無効化する
flush,nowarn "flush"を同じだが、ハイパーバイザは安全でない可能性がある設定に対して最初のVM起動時に警告を出すことは無い。
off ハイパーバイザの緩和策を無効とし、警告は出さない。

デフォルトでは"flush"となっている。

KVMに対する緩和操作 - モジュールパラメータ

KVMハイパーバイザの緩和策のメカニズムは、ゲストOSに入る際にL1キャッシュをフラッシュするもので、モジュールパラメータで操作することができる。

パラメータは"kvm-intel.vmentry_l1d_flush="で、以下の引数と取る。

パラメータ 説明
always L1キャシュをVMENTER時に毎回フラッシュする
cond 対象のコードがVMEXITとEXENTERに挟まれており、攻撃者に対して有益なホストのメモリが露呈する際に、L1キャッシュをフラッシュする。しかし以前ホストのメモリが露呈してしまう。例:ホストメモリのアドレスレイアウトなど
never 緩和策を無効にする

上記のパラメータは、sysfsを通じて動作中に渡すか、モジュールを読み込む際にモジュールパラメータとしてカーネルコマンドラインから渡すことができる。当該パラメータは以下のファイルを使って渡すことができる。

/sys/module/kvm_intel/parameters/vmentry_l1d_flush

デフォルトは"cond"である。‘l1tf=full,force’がカーネルコマンドラインに渡された場合は、"always"が適応されるので、kvm-intel.vmentry_l1d_flushは無視され、sysfsファイルへの書き込みはできなくなる。

緩和策選択ガイド

1. 仮想化行なっていない場合

カーネルによってシステムは無条件に保護され、特に何かを行う必要はない。

2. 信頼できるゲストでの仮想化

ゲストマシンが信頼できるソースからのもので、そのカーネルがシステム内部でL1TFの緩和策を行なっていることが保証されている場合、完全にL1TFから保護されており、それ以上の対策は不必要である。

VMENTERでのL1キャッシュのフラッシュに起因するオーバヘッドを回避するために、管理者はカーネルコマンドライン若しくはsysfsファイル経由でフラッシュを無効にすることができる。

3. 信頼できないゲストでの仮想化

3.1 SMTがサポートされていない又は無効

SMTがプロセッサにサポートされていないかBIOS又はカーネルを通じて無効にされている場合は、VMENTERの際にL1キャッシュをフラッシュするだけで良い。

条件下でのL1キャッシュのフラッシュはデフォルトでの挙動となるが変更することもできる。

3.2. EPTがサポートされていない又は無効

EPTがプロセッサにサポートされていないかハイパーバイザによって無効されている場合は、システムは完全に保護されている。SMTは有効のまま、VMENTER毎にL1キャッシュをフラッシュする必要もない。

EPTは"kvm-intel.ept"パラメータを通じてハイパーバイザで無効化できる。

3.3 SMT及びEPTがサポートされており且つ有効

SMT及びEPTがサポートされており且つ有効である場合、様々な角度からの緩和策が考えられる。

  • VMENTERの際にL1キャッシュのフラッシュ:

    VMENTER時のL1キャッシュのフラッシュは最低限の保護設定となる、だがこれは他の対策と組み合わせて効果を発揮する。

    条件付きのL1キャッシュのフラッシュはデフォルトの挙動となるが、これは設定が可能。

  • ゲストマシンの束縛:

    ゲストマシンを特定のプロセッサに束縛し他のプロセッサで動作させないようにすることは、攻撃対象を減らすことに大いに貢献する。だが割り込みや、ソフトウェア割り込み、カーネルスレッドなどは依然として攻撃者に対して有益な情報を露呈してしまう。

  • 割り込みの隔離:

    ゲストCPUを割り込みから隔離することはアタックサーフェースを減少させることができる。だが依然として悪意あるゲストマシンに部分的なホストの物理メモリを露呈させることを可能としてしまう。これは最低限のホストメモリレイアウトの知見を得ることに使用されること可能性がある。ゲストマシンに割り当てられた論理CPUに対してのみ起こる割り込みは状況に依存するソフトウェア割り込みを発行することができ、有益な情報を露呈するカーネルスレッドをスケジュールすることができる。

上記の3つの対策は組み合わせることで、ある側面に対して有効な対策となる、だがアタックサーフェースのは依然として健在し、適当に調査されるべきである。完全な安全策を構築するには以下の対策が有効であれば良い。

  • SMTの無効化:

    SMTを無効にし、L1キャッシュのフラッシュを強制することは保護の効力を最大化する。これは他の対策に依存することはない。

    SMTの操作とL1キャッシュのフラッシュはコマンドラインの"nosmt"、"l1tf"、"kvm-intel.vmentry_l1d_flush"で設定できる。そして動作中であればsysfsのファイルで行える。

  • EPTの無効化:

    EPTの無効化は同じく保護の効果を最大化できる。これは上記の方法に依存していない。SMTは有効のまま、L1キャシュのフラッシュも必要としない。だがパフォーマンスへの影響は大いにある。

    EPTはハイパーバイザのパラメータである"kvm-intel.ept"でも無効化できる。

3.4 ネストされた仮想マシン

ネストされた仮想化が使用されている際、3種類のOSが関係していることになる。物理のハイパーバイザ、ネストされたハイパーバイザ、ネストされた仮想マシン。ネストされたハイパーバイザからネストされた仮想マシンへのVMENTERは常に物理のハイパーバイザによって処理される。KVMが物理でもハイパーバイザは以下の挙動をとる。

  • ネストされたハイパーバイザからネストされた仮想マシンに切り替わる度にL1キャッシュをフラッシュする。よってネストされたハイパーバイザの情報はネストされた稼働マシンに露呈することはない。

  • ネストされた仮想マシンからネストされたネストされたハイパーバイザに切り替わる度にL1キャッシュをフラッシュする。これは煩雑な処理であり、L1キャッシュのフラッシュはネストされた仮想マシンに対して物理ハイパーバイザの機密情報を露呈されることを回避できる。

  • ネストされたハイパーバイザにL1キャッシュのフラッシュを行わないように支持する。これは2重にL1キャッシュをフラッシュしてしまうのを防ぐことができる。

デフォルトの対策

脆弱なCPUに対するカーネルの対策は以下となる。

  • PTE Inversionで悪意あるユーザ空間から保護する。これは無条件で行われ、コントロールすることはできない。

  • ゲストに対してEPTが有効となっている際はL1キャッシュをVMENTER時に条件付きでフラッシュする。

カーネルはデフォルトではSMTを無効にすることを強制はしない。それはSMTシステムを脆弱な状態で、信頼できないゲストをEPTを有効したまま動作させるということになる。

この選択の根拠は以下。

  • 特にアップデートをおろそかにしている場合、SMTの無効化を強制することは既存の設定を壊してしまう。

  • 通常のユーザが信頼できないゲストマシンを動作させている場合、L1TFは信頼できないゲスト内部で組み込まれたマルウェアのターゲットになってしまう。例:スパムボットやローカルネットワークからの攻撃。

    他の信頼できないマシンからユーザを守ること技術的な手立てはない。

  • 厳密にいうとこれはかなり起こりにくい、そして今日の知見では、Javascriptなどを用いて行う有名な攻撃を通じてL1TFに対してエクスプロイトすることは不可能とさえ言える、なぜならPTEを操作する方法がないからである。仮にそれが可能で、緩和策が他にない場合、デフォルトは変わってくるだろう。

  • クラウドの管理者やホスティング事業者は慎重にこリスクについて調査する必要があり、適当な対策を選ばなければならない。これはデプロイされているマシンによってかなり異なるだろう、そして全ての設定は異なるものになるだろう。これはあるシチュエーションに対して適当な対策をデフォルトでカーネルは提供できないからである。