web-dev-qa-db-ja.com

DMA IOMMU分離にもかかわらず攻撃

PCIの動作とLinuxによるDMAバッファの処理)に既に精通している場合は、実際の質問について3番目のセクションに進んでください。そうでない場合は、PCIデバイスがメモリアクセスを実行する方法の簡単な概要を読んでください。 DMAを使用したデバイスとの通信をカーネルがどのように処理するか。同じ質問をしている人々に役立つ情報を提供することを期待し、私の理解が失われた場合に他の人が私を修正する機会を与えるために、これをここに含めました。

(私の理解)PCI、IOMMU、DMA

PCIおよびPCIeデバイスの構成スペースには2バイト コマンドレジスタ があり、これにはいくつかの異なるハードウェア機能を有効または無効にするためのビットマスクが含まれています。ビット2は、バスマスターイネーブルビットであり、これを設定すると、デバイスはDMA=要求を開始できます。このビットとその他のビットはコマンドレジスタは、スーパーバイザモードで実行されているソフトウェアによって(通常はカーネルドライバによって)設定され、PCIデバイスに物理的に格納されているにもかかわらず、それによって変更することはできません(おそらく、PCHは各デバイスのPCI構成スペースのシャドウコピーを保持しますか?) 。IOMMUのないハードウェアでは、デバイスは任意の正当なメモリアドレスへの読み取りと書き込みを要求できます。これは、DMA攻撃または悪バスマスタリングと呼ばれることが多く、保護されていないシステムでの問題です。悪意のあるPCIデバイス。IOMMUは、セキュリティとパフォーマンスの両方を向上させるソリューションとなるはずです。参考までに、インテルの実装であるVT-d(正確には、より新しいVT-d2)について具体的に質問します。

ほとんどのシステムは、DMA再マッピングまたはDMAR用に構成できます。 BIOSに含まれるACPIテーブルには、多くの場合、さまざまなPCIグループがすべてのメモリアクセスをルーティングするアドレスのリストを含むDMARテーブルがあります。これはすべて VT-d仕様 のセクション2.5.1.1で説明されています。ドキュメントのグラフィック:

DMA remapping

LinuxカーネルDMA API

DMARテーブルはBIOSによってハードコードされています。特定のPCIデバイス(または、特定の IOMMUグループ )は、所定のメモリ範囲にのみアクセスできます。カーネルには、そのメモリの場所が通知され、DMA経由で読み取り/書き込み可能にしたくないメモリをそこに割り当てないように指示されます。再マッピング値は、カーネルログバッファーで報告されます。

 DMAR:デバイス0000:00:02.0のIDマップの設定[0xad000000-0xaf1fffff] 
 DMAR:デバイス0000:00:14.0のIDマップの設定[0xa95dc000-0xa95e8fff] 
 DMAR :デバイス0000:00:1a.0のIDマップを設定しています[0xa95dc000-0xa95e8fff] 
DMAR:デバイス0000:00:1d.0のIDマップの設定[0xa95dc000-0xa95e8fff]
 DMAR:LPCの0-16MiBユニティマッピングの準備
 DMAR:デバイス0000:00:1f.0のIDマップの設定[0x0-0xffffff] 
 DMAR:インテル(R)ダイレクトI/Oの仮想化テクノロジー
 iommu:デバイス0000:00:00.0をグループ0に追加
 iommu:デバイス0000:00:01.0をグループ1に追加
 iommu:デバイスを追加0000:00:02.0をグループ2 
 iommuに追加:0000:00:14.0をグループ3 
 iommuに追加:デバイス0000:00:16.0をグループ4 
 iommuに追加:デバイス0000:00:1a.0をグループ5に追加
 iommu:デバイス0000:00:1b.0をグループ6に追加
 iommu:デバイス0000:00:1c.0をグループ7に追加
 iommu:デバイス0000:00:1c.2をグループ8に追加
 iommu:デバイス0000:00:1c.3をグループ9に追加
 iommu:デバイス0000:00を追加: 1c.4からグループ10 
iommu:デバイス0000:00:1d.0をグループ11に追加
 iommu:デバイス0000:00:1f.0をグループ12に追加します
 iommu:デバイス0000:00:1f.2をグループ12に追加します
 iommu:デバイス0000:00を追加します:1f.3からグループ12 
 iommu:デバイス0000:01:00.0をグループ1に追加
 iommu:デバイス0000:03:00.0をグループ13に追加
 iommu:デバイスを追加0000:04:00.0からグループ14 
 iommu:デバイス0000:05:00.0をグループ15 
に追加

太字の行から、グループ11には(のみ)デバイス_0000:00:1d.0_が含まれ、_0xa95dc000 - 0xa95e8fff_の範囲の13ページのメモリに自由にアクセスできることがわかります。グループ11のデバイスへのすべてのアクセスはそこにのみ書き込むことができ、他のDMAバッファー、または関連しないOSコードの内容を変更することを防ぎます。このようにして、デバイスにバスがあってもマスタービットが設定されている場合、書き込み先を追跡する必要はありません。また、(偶然または悪意により)本来の場所に書き込むことはできません。

カーネルドライバーは、DMAを介してデバイスとやり取りする場合、_void *addr = kmalloc(len, GFP_KERNEL | GFP_DMA)などを使用して、この目的のために特別にメモリを割り当てます。これはaddrに、DMAの使用に適したサイズのlenバイトのメモリの連続セクションを指す仮想メモリアドレスを返します。これはすべての詳細は DMA APIドキュメント で説明されています。ドライバは、この共有メモリ領域を介してPCIデバイスと自由に通信できます。簡略化された一連のイベントは、次のようになります。

  • OpenCLドライバは、DMAを使用するために、GPU PCIデバイスと共有されるメモリを割り当てます。
  • ドライバーはいくつかのベクターデータをDMAアドレスに書き込み、他のことをするためにオフになります。
  • GPUはPCIデバイスを介してデータを読み取り、それを処理する低速のタスクを開始します。
  • 終了すると、GPUは終了したデータをバッファーに書き込み、割り込みを開始します。
  • ドライバーは割り込みのために実行中の処理を停止し、レンダリングされたグラフィックをメモリから読み取ります。

カーネルはDMAバッファを信用せず、安全に処理しますか?

カーネルはこれらのバッファーを暗黙的に信頼していますか?DMA=バッファー?悪意のあるまたは侵害されたPCIデバイスは、指定されたバッファー以外に書き込み(IOMMUが他のことを防ぐ)でき、データを悪用してカーネルを侵害できます。それらが共有している構造?明らかな答えは可能性のあるです。これは、メモリの安全でない言語を使用した複雑なデータ構造の共有と解析には、悪用のリスクが伴うためです。しかし、カーネル開発者は、これらのバッファは信頼されており、悪意のあるアクティビティからカーネルを保護するための努力は一切していません(たとえば、非特権ユーザーランドとcopy_from_user()および同様の関数を介してカーネル間で共有されるデータとは異なります)。 IOMMUの制限にもかかわらず、悪意のあるPCIデバイスがホストを危険にさらすことができるかどうかの答えはおそらくだと思います。

このような脆弱性の悪用は次のように機能します。ここで、bufはデバイス制御のDMA書き込み可能なアドレス空間にあり、destはカーネルメモリの他の場所にあります。

  • デバイスは_struct { size_t len; char data[32]; char foo[32]; } buf_としてデータを書き込みます。
  • ドライバは、_struct { char data[32]; bool summon_demons; } dest_のdataにコピーします。
  • デバイスがbuf.len = sizeof(buf.data) + 1および_buf.foo[0] = 1_を悪意を持って設定します。
  • ドライバは、memcpy(dest.data, buf.data, buf.len)を使用して、データを安全にコピーしません。
  • PCIデバイスは、古典的なバッファーオーバーフローでカーネルと魂を制御します。

明らかにこれは不自然な例であり、おそらくそのような明らかなバグがそもそもカーネルに反映されない可能性が高いですが、それは私の要点を示し、私の第一の質問に導きます:

DMAを介して共有されるデータ構造の不適切な処理、またはPCIデバイスからの入力を信頼できるものとして扱う特定のドライバーの脆弱性の例はありますか?

IOMMUとしてのVT-dの制限

私はその制限を認識しており、デバイスがIOMMUを直接回避する方法、またはシステムの制御を取得するために別の抜け穴を使用する方法を説明しようとする答えは望んでいません。知っている:

  • システムを適切に保護することはできません x2APICおよび割り込み再マッピングがサポートされていない場合。
  • アドレス変換サービス(ATS) バイパス可能 IOMMU。
  • 変更されたPCI 拡張ROM は、再起動時にシステムを攻撃する可能性があります。
  • 特定のIOMMUグループ内のすべてのデバイスは、同じメモリにアクセスできます(ACSがない場合)。
  • 一部のBIOSには壊れたDMARテーブルが付属しているため、IOMMUが無効になります。
  • CSME( "Intel ME")は PSFおよびPAVP を介してVT-dを無効にできる場合があります。
  • しかし、未知の攻撃はIOMMUを無効またはバイパスできる可能性があります。

* DMAはダイレクトメモリアクセスを意味します。これは、特定のハードウェアインターフェイス(PCIeなど)がCPUを経由せずにシステムメモリへの直接アクセスを要求できるハードウェア機能です。

23
forest

最近、NDSSS 2019で公開された論文を読んでいましたが、この論文は2月に発表されたので、質問に完全に答えると思います。質問がなされた当時、脆弱性があることに対する答えは はい、しかしそれらは5.0からLinuxカーネルで修正されました のようです。 ネットワークと分散システムのセキュリティシンポジウム2019 で発表された論文に属するスライドは、 こちら にあります。

ThunderboltインターフェースにもDMAがあるため、質問は依然として関連しています。 Linuxのパッチノートは here にあります。

6
LTPCGO