NDIS 仮想マシン (VM) 共有メモリのセキュリティ上の問題
このトピックでは、仮想マシン キュー (VMQ) 受信バッファーに対する仮想マシン (VM) からの共有メモリの割り当てに関連する潜在的なセキュリティの問題について説明します。 トピックのセクションは次のとおりです。
注 Hyper-V では、子パーティションは「VM」とも呼ばれます。
VM 共有メモリに関するセキュリティ問題の概要
VM は信頼されたソフトウェア エンティティではありません。 つまり、悪意のある VM が、Hyper-V 親パーティションで実行されている他の VM や管理オペレーティング システムに干渉できないようにする必要があります。 このセクションでは、ドライバー作成者が VMQ のセキュリティの問題と共有メモリの要件を確実に理解するための背景情報と要件について説明します。 共有メモリの詳細については、「VMQ ドライバーの作成」セクションの「共有メモリ リソースの割り当て」トピックを参照してください。
仮想化された環境では、VM 共有メモリを VM で表示または変更できます。 ただし、他の VM に関連付けられているデータの表示または変更は許可されません。 VM は、管理オペレーティング アドレス空間へのアクセスも許可されません。
受信パケットのヘッダー部分を保護する必要があります。 VM は、ネットワーク仮想サービス プロバイダー (VSP) の Hyper-V 拡張可能スイッチの動作に影響を与えることはできません。 そのため、ネットワーク アダプターが DMA を使用して VM 共有メモリにデータを転送する前に、VLAN (仮想 LAN) フィルタリングが行われる必要があります。 また、スイッチのメディア アクセス制御 (MAC) アドレス学習は影響を受けません。
VM に接続されている Hyper-V 拡張可能スイッチ ポートに VLAN 識別子が関連付けられている場合、ホスト コンピューターは、ホストがパケットを VM の仮想ネットワーク アダプターに転送する前に、受信フレームの宛先 MAC アドレスと VLAN 識別子がポートのそれぞれの属性と一致していることを確認する必要があります。 フレームの VLAN 識別子がポートの VLAN 識別子と一致しない場合、パケットは破棄されます。 仮想ネットワーク アダプターの受信バッファーがホスト メモリから割り当てられると、ホストは VLAN 識別子をチェックし、必要に応じてフレームを破棄してから、フレームの内容をターゲット VM に表示することができます。 フレームが VM のアドレス空間にコピーされていない場合、その VM からアクセスすることはできません。
ただし、VMQ が共有メモリを使用するように構成されている場合、ネットワーク アダプターは DMA を使用して受信フレームを VM アドレス空間に直接転送します。 この転送では、VM が、拡張可能スイッチが必要な VLAN フィルタリングを適用するのを待たずに受信フレームの内容を確認できるセキュリティの問題が発生します。
Windows Server 2008 R2 がセキュリティ問題に対処する方法
Windows Server 2008 R2 では、VSP が VM アドレス空間から割り当てられた共有メモリを使用するように VM キューを構成する前に、キューに対して次のフィルタリング テストを使用します。
(MAC address == x) && (VLAN identifier == n)
ネットワーク アダプター ハードウェアが受信バッファーへの DMA 転送前にこのテストをサポートできる場合、ネットワーク アダプターは無効な VLAN 識別子を持つフレームを破棄するか、または拡張可能スイッチによってフィルター処理できるように既定のキューにそれらのフレームを送信できます。 ミニポート ドライバーは、このテストによりキューでフィルターを設定する要求に成功した場合、拡張可能スイッチは、そのキューの VM 共有メモリを使用できます。 ただし、ネットワーク アダプター ハードウェアが宛先 MAC アドレスと VLAN 識別子の両方に基づいてフレームをフィルター処理できない場合、拡張可能スイッチはそのキューにホスト共有メモリを使用します。
拡張可能スイッチは、受信フレームのソース MAC アドレスを検査して、送信フレームのルーティング情報を構成します。つまり、これは物理学習スイッチに似ています。 ファイアウォール フィルター ドライバーをホスト スタックにインストールできます。たとえば、ネットワーク アダプター ハードウェアのミニポート ドライバーの上、拡張可能スイッチ ドライバーの下などです。 ファイアウォール フィルター ドライバーは、拡張可能スイッチ前の受信フレーム内のデータにアクセスできます。 各フレームの受信バッファー全体が VM アドレス空間から割り当てられている場合、悪意のある VM は、ホストで実行されるフィルター ドライバーまたは拡張可能スイッチによって調べられるフレームの一部にアクセスする可能性があります。
このセキュリティ問題に対処するには、VM キューに VM 共有メモリを使用する場合、ネットワーク アダプターは、少なくとも先読みサイズであるバイト オフセット (事前に定義された固定値) でパケットを分割する必要があります。 先読みデータ (先読みサイズのバイト オフセットより前のデータ) は、先読みデータに割り当てられた共有メモリに DMA で転送する必要があります。 フレーム ペイロードの残りの部分である先読み後データは、先読み後データに割り当てられた共有メモリに DMA で転送する必要があります。
次の図は、受信データが先読みと先読み後の共有メモリ バッファーに分割されたときのネットワーク データ構造の関係を示しています。
VMQ 共有メモリの概要要件は次のとおりです。
ネットワーク アダプターは、先読みサイズよりも大きいネットワーク ヘッダー境界で受信フレームを分割できます。 ただし、NDIS によって要求された場合、例外なく、受信して VMQ に割り当てられるすべてのフレームは、NDIS が要求する先読みサイズ境界で、またはそれより大きいサイズ境界で分割する必要があります。
先読みデータは、ミニポート ドライバーによって割り当てられている共有メモリに DMA 転送する必要があります。 ミニポート ドライバーは、メモリが先読みデータに使用される割り当て呼び出しで指定する必要があります。
先読み後データは、ミニポート ドライバーによって割り当てられている共有メモリに DMA 転送する必要があります。 ミニポート ドライバーは、メモリが先読み後データに使用される割り当て呼び出しで指定する必要があります。
ミニポート ドライバーは、共有メモリ割り当て要求を完了するために NDIS が使用するアドレス空間に依存することはできません。 つまり、先読みデータまたは先読み後データの共有メモリ アドレス空間は実装固有です。 多くの場合、NDIS または拡張可能スイッチは、ホスト メモリ アドレス空間から、先読み後の使用に対する要求を含むすべての要求を満たす可能性があります。
VMQ 受信キューでフレームを受信する順序は、そのキュー内のフレームがドライバー スタックの上に示されている場合に保持する必要があります。
ネットワーク アダプターは、各先読みバッファーに十分なバックフィル メモリ領域を割り当てる必要があります。 この割り当てにより、先読みバッファーのバックフィル部分に先読みデータをコピーでき、連続したバッファー内の VM にフレームを送信できます。
VMQ 共有メモリに対するこれらの要件を満たすメカニズムがハードウェアに存在しない場合、受信側でスキャッター ギャザー DMA をサポートするハードウェアは、受信フレームごとに 2 つの受信バッファーを割り当てることで同じ結果を達成する可能性があります。 この場合、最初のバッファーのサイズは、要求された先読みサイズに制限されます。
ネットワーク アダプターがいずれのメソッドでも VMQ 共有メモリのこれらの要件を満たすことができない場合、VSP はホスト アドレス空間から VMQ 受信バッファーのメモリを割り当て、ネットワーク アダプター受信バッファーからの受信パケットを VM アドレス空間にコピーします。
Windows Server 2012 以降のバージョンがセキュリティ問題に対処する方法
Windows Server 2012 以降、VSP は VMQ 受信バッファー用に VM から共有メモリを割り当てません。 代わりに、VSP はホスト アドレス空間から VMQ 受信バッファーのメモリを割り当て、ネットワーク アダプター受信バッファーからの受信パケットを VM アドレス空間にコピーします。
次の点は、Windows Server 2012 以降のバージョンの Windows で実行される VMQ ミニポート ドライバーに適用されます。
NDIS 6.20 VMQ ミニポート ドライバーの場合、変更は必要ありません。 ただし、OID_RECEIVE_FILTER_ALLOCATE_QUEUE OID (オブジェクト識別子) メソッド要求を発行することで VSP が VM キューを割り当てると、NDIS_RECEIVE_QUEUE_PARAMETERS 構造体の LookaheadSize メンバーが 0 に設定されます。 これにより、ミニポート ドライバーが先読み前バッファーと先読み後バッファーにパケットを分割しないように強制されます。
NDIS 6.30 以降では、VMQ ミニポート ドライバーは、先読み前バッファーと先読み後バッファーにパケット データを分割するためのサポートをアドバタイズしてはいけません。 ミニポート ドライバーがその VMQ 機能を登録する場合、NDIS_RECEIVE_FILTER_CAPABILITIES 構造体を初期化するときに、次の規則に従う必要があります。
ミニポート ドライバーは、Flags メンバーに NDIS_RECEIVE_FILTER_LOOKAHEAD_SPLIT_SUPPORTED フラグを設定してはいけません。
ミニポート ドライバーは、MinLookaheadSplitSize メンバーと MaxLookaheadSplitSize メンバーを 0 に設定する必要があります。
VMQ 機能の登録方法の詳細については、「ネットワーク アダプターの VMQ 機能の決定」を参照してください。