ドライバー検証ツールの [その他のチェック] オプションは、アクティブなカーネル オブジェクトを含むメモリの解放など、ドライバーまたはシステムがクラッシュする一般的なエラーがないかドライバーを監視します。
具体的には、[その他のチェック] オプションは、次の不適切なドライバーの動作を検索します。
解放されたメモリ内のアクティブな作業項目。 ドライバーは ExFreePool を呼び出して、 IoQueueWorkItem を使用してキューに登録された作業項目を含むプール ブロックを解放します。
解放されたメモリ内のアクティブなリソース。 ドライバーは ExFreePool を呼び出して、アクティブな ERESOURCE 構造体を含むプール ブロックを解放します。 ドライバーは ExFreePool を呼び出す前に、ExDeleteResource を呼び出して ERESOURCE オブジェクトを削除する必要があります。
解放されたメモリ内のアクティブなルックアサイド リスト。 ドライバーは ExFreePool を呼び出して、アクティブなルックアサイド リスト (NPAGED_LOOKASIDE_LIST または PAGED_LOOKASIDE_LIST 構造をまだ含むプール ブロックを解放します。 ExFreePool を呼び出す前に、ExDeleteNPagedLookasideList または ExDeletePagedLookasideList を呼び出してルックアサイド リストを削除する必要があります。
Windows Management Instrumentation (WMI) と Event Tracing for Windows (ETW) の登録に関する問題。 ドライバー検証ツールによって検出されるこのような問題は次のとおりです。
WMI コールバックの登録を解除せずにアンロードを試みるドライバー。
WMI から登録解除されていないデバイス オブジェクトを削除しようとするドライバー。
ETW カーネル モード プロバイダーの登録を解除せずにアンロードを試みるドライバー。
既に登録解除されているプロバイダーの登録を解除しようとするドライバー。
カーネル ハンドルのエラー。 (Windows Vista 以降のバージョン)[その他のチェック] オプションを有効にすると、システム プロセスのハンドル トレースも有効になり、カーネル ハンドルリークと バグ チェック 0x93: INVALID_KERNEL_HANDLEの調査に役立ちます。 ハンドル トレースを有効にすると、カーネルは最近のハンドルのオープン操作とクローズ操作のスタック トレースを収集します。 スタック トレースは、 !htrace デバッガー拡張機能を使用してカーネル デバッガーに表示できます。 !htrace の詳細については、Windows 用デバッグ ツールのドキュメントを参照してください。
カーネル モード アクセスを使用したユーザー モード ハンドル Windows 7 以降では、[その他のチェック] オプションを選択すると、ドライバー検証ツールは ObReferenceObjectByHandle への呼び出しも確認します。 カーネル モード アクセスでユーザー モード ハンドルを渡すことはできません。 このような操作が発生した場合、ドライバー検証ツールはバグ チェック 0xC4を発行し、パラメーター 1 の値を0xF6します。
カーネルスタックに割り当てられた同期オブジェクトのユーザーモードでの待機
Windows 7 以降では、ドライバー検証ツールは、オペレーティング システムが提供するマルチスレッド同期メカニズムをドライバーが誤って使用する可能性がある追加の方法を検出できます。
カーネル スタック上のローカル変数として、KEVENT 構造体などの同期オブジェクトを割り当てることが一般的な方法です。 プロセスがメモリに読み込まれている間、スレッドのカーネル スタックがワーキング セットからトリミングされたり、ディスクにページングされたりすることはありません。 このようなページング不可能なメモリに同期オブジェクトを割り当てることは正しいです。
ただし、ドライバーが KeWaitForSingleObject や KeWaitForMultipleObjects などの API を呼び出してスタックに割り当てられているオブジェクトを待機する場合は、API の WaitMode パラメーターに KernelMode 値を指定する必要があります。 プロセスのすべてのスレッドが UserMode モードで待機している場合、そのプロセスはディスクにスワップアウトされる資格があります。 そのため、ドライバーが WaitMode パラメーターとして UserMode を指定した場合、オペレーティング システムは、同じプロセス内の他のすべてのスレッドも UserMode として待機している限り、現在のプロセスをスワップ アウトできます。 プロセス全体をディスクにスワップアウトするためには、カーネルスタックをページアウトすることが含まれます。 オペレーティング システムがスワップアウトした同期オブジェクトの待機が正しくありません。 ある時点で、スレッドが一緒に来て、同期オブジェクトに通知する必要があります。 同期オブジェクトの通知には、IRQL = DISPATCH_LEVEL 以上でオブジェクトを操作する Windows カーネルが含まれます。 DISPATCH_LEVEL以上でページアウトまたはスワップアウトされたメモリに触れると、システムがクラッシュします。
Windows 7 以降では、[その他のチェック] オプションを選択すると、検証済みドライバーが UserMode で待機するために使用する同期オブジェクトが、現在のスレッドのカーネル スタックに割り当てられないことがドライバー検証ツールによって確認されます。 ドライバー検証ツールは、このような不適切な待機を検出すると、パラメーター 1 の値が 0x123 の場合、バグ チェック 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATIONを発生させます。
カーネル ハンドル参照が正しくありません
各 Windows プロセスにはハンドル テーブルがあります。 ハンドル テーブルは、ハンドル エントリの配列として表示できます。 有効な各ハンドル値は、この配列内の有効なエントリを参照します。
システムプロセスのハンドルテーブルで有効なハンドルとして機能するカーネルハンドル。 システム プロセスを除くすべてのプロセスに対して有効なハンドルとしてのユーザー ハンドル。
Windows 7 では、ドライバー検証ツールは、正しくないカーネル ハンドル値を参照しようとします。 これらのドライバーの欠陥は、ドライバー検証ツールの [その他のチェック] オプションが有効になっている場合、バグ チェック 0x93: INVALID_KERNEL_HANDLE として報告されます。 通常、この種の不適切なハンドル参照は、ドライバーが既にそのハンドルを閉じているが、それを引き続き使用しようとしていることを意味します。 この種の欠陥により、参照されているハンドル値が別の関連のないドライバーによって既に再利用されている可能性があるため、システムに予期しない問題が発生する可能性があります。
カーネル ドライバーが最近カーネル ハンドルを閉じ、後で閉じたハンドルを参照する場合、ドライバー検証ツールは、前に説明したようにバグ チェックを強制します。 この場合、 !htrace デバッガー拡張機能の出力は、このハンドルを閉じたコード パスのスタック トレースを提供します。 !htrace のパラメーターとして、システム プロセスのアドレスを使用します。 システム プロセスのアドレスを検索するには、 !process 4 0 コマンドを 使用します。
Windows 7 以降、ドライバー検証ツールは ObReferenceObjectByHandle にチェックを追加します。 KernelMode アクセスを使用してユーザー空間ハンドルを渡すことが禁止されるようになりました。 このような組み合わせが検出された場合、ドライバー検証ツールは バグ チェック 0xC4を発行します。DRIVER_VERIFIER_DETECTED_VIOLATION、パラメーター 1 の値は0xF6。
このオプションのアクティブ化
ドライバー検証ツール マネージャーまたは Verifier.exe コマンド ラインを使用して、1 つ以上のドライバーの [その他のチェック] オプションを有効にすることができます。 詳細については、「 ドライバー検証ツールオプションの選択」を参照してください。
コマンド ラインで
コマンド ラインでは、[その他のチェック] オプションは ビット 11 (0x800) で表されます。 その他のチェックを有効にするには、0x800のフラグ値を使用するか、フラグ値に0x800を追加します。 例えば次が挙げられます。
verifier /flags 0x800 /driver MyDriver.sysこのオプションは、次のブート後にアクティブになります。
Windows Vista 以降のバージョンの Windows では、 /volatile パラメーターをコマンドに追加することで、コンピューターを再起動せずにその他のチェックをアクティブ化および非アクティブ化することもできます。 例えば次が挙げられます。
verifier /volatile /flags 0x800 /adddriver MyDriver.sysこの設定はすぐに有効ですが、コンピューターをシャットダウンまたは再起動すると失われます。 詳細については、「 揮発性設定の使用」を参照してください。
[その他のチェック] オプションも標準設定に含まれています。 例えば次が挙げられます。
verifier /standard /driver MyDriver.sysドライバー検証ツール マネージャーの使用
ドライバー検証ツール マネージャーを起動します。 コマンド プロンプト ウィンドウに 「Verifier 」と入力します。
(コード開発者向けの) [カスタム設定の作成] を選択し、[次へ] をクリックします。
完全な一覧から [個々の設定を選択] を選択します。
[その他のチェック] を選択します。
その他のチェック機能も標準設定に含まれています。 この機能を使用するには、ドライバー検証ツール マネージャーで、[ 標準設定の作成] をクリックします。
結果の表示
[その他のチェック] オプションの結果を表示するには、カーネル デバッガーで !verifier 拡張機能を使用します。 ( !verifier の詳細については、 Windows 用デバッグ ツール のドキュメントを参照してください)。
次の例では、[その他のチェック] オプションで、ドライバーが解放しようとしているメモリ内のアクティブな ERESOURCE 構造体が検出され、その結果、 バグ チェック 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION。 バグ チェック 0xC4表示には、ERESOURCE のアドレスと影響を受けるメモリが含まれます。
1: kd> !verifier 1
Verify Level 800 ... enabled options are:
Miscellaneous checks enabled
Summary of All Verifier Statistics
RaiseIrqls 0x0
AcquireSpinLocks 0x0
Synch Executions 0x0
Trims 0x0
Pool Allocations Attempted 0x1
Pool Allocations Succeeded 0x1
Pool Allocations Succeeded SpecialPool 0x0
Pool Allocations With NO TAG 0x0
Pool Allocations Failed 0x0
Resource Allocations Failed Deliberately 0x0
Current paged pool allocations 0x0 for 00000000 bytes
Peak paged pool allocations 0x0 for 00000000 bytes
Current nonpaged pool allocations 0x0 for 00000000 bytes
Peak nonpaged pool allocations 0x0 for 00000000 bytes
Driver Verification List
Entry State NonPagedPool PagedPool Module
8459ca50 Loaded 00000000 00000000 buggy.sys
*** Fatal System Error: 0x000000c4
(0x000000D2,0x9655D4A8,0x9655D468,0x000000B0)
0xD2 : Freeing pool allocation that contains active ERESOURCE.
2 - ERESOURCE address.
3 - Pool allocation start address.
4 - Pool allocation size.
プールの割り当てを調査するには、プール割り当ての開始アドレス (9655D468) で !pool デバッガー拡張機能を使用します。 ( 2 フラグは、指定されたアドレスを含むプールのヘッダー情報のみを表示します。他のプールのヘッダー情報は抑制されます)。
1: kd> !pool 9655d468 2
Pool page 9655d468 region is Paged pool
*9655d468 size: b0 previous size: 8 (Allocated) *Bug_
ERESOURCE に関する情報を検索するには、 !locks (!kdext*.locks) デバッガー拡張機能を構造体のアドレスと共に使用します。
1: kd> !locks 0x9655D4A8 <<<<<- ERESOURCE @0x9655D4A8 lives inside the pool block being freed
Resource @ 0x9655d4a8 Available
1 total locks
また、kb デバッガー コマンドを使用して、エラーの原因となった呼び出しのスタック トレースを表示することもできます。 次の例は、ドライバー検証ツールがインターセプトした ExFreePoolWithTag の呼び出しを含むスタックを示しています。
1: kd> kb
ChildEBP RetAddr Args to Child
92f6374c 82c2c95a 00000003 92f68cdc 00000000 nt!RtlpBreakWithStatusInstruction
92f6379c 82c2d345 00000003 9655d468 000000c4 nt!KiBugCheckDebugBreak+0x1c
92f63b48 82c2c804 000000c4 000000d2 9655d4a8 nt!KeBugCheck2+0x5a9
92f63b6c 82e73bae 000000c4 000000d2 9655d4a8 nt!KeBugCheckEx+0x1e
92f63b88 82e78c32 9655d4a8 9655d468 000000b0 nt!VerifierBugCheckIfAppropriate+0x3c
92f63ba4 82ca7dcb 9655d468 000000b0 00000000 nt!VfCheckForResource+0x52
92f63bc8 82e7fb2d 000000b0 00000190 9655d470 nt!ExpCheckForResource+0x21
92f63be4 82e6dc6c 9655d470 92f63c18 89b6c58c nt!ExFreePoolSanityChecks+0x1fb
92f63bf0 89b6c58c 9655d470 00000000 89b74194 nt!VerifierExFreePoolWithTag+0x28
92f63c00 89b6c0f6 846550c8 846550c8 846e2200 buggy!MmTestProbeLockForEverStress+0x2e
92f63c18 82e6c5f1 846e2200 846550c8 85362e30 buggy!TdDeviceControl+0xc4
92f63c38 82c1fd81 82d4d148 846550c8 846e2200 nt!IovCallDriver+0x251
92f63c4c 82d4d148 85362e30 846550c8 84655138 nt!IofCallDriver+0x1b
92f63c6c 82d4df9e 846e2200 85362e30 00000000 nt!IopSynchronousServiceTail+0x1e6
92f63d00 82d527be 00000001 846550c8 00000000 nt!IopXxxControlFile+0x684
92f63d34 82cb9efc 0000004c 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
92f63d34 6a22b204 0000004c 00000000 00000000 nt!KiFastCallEntry+0x12c