共用方式為


其他檢查

[驅動程式驗證程式] 的 [其他檢查] 選項會監視驅動程式是否有導致驅動程式或系統損毀的常見錯誤,例如釋放仍然包含作用中核心物件的記憶體。

具體而言,[其他檢查] 選項會尋找下列不正確的驅動程式行為:

  • 釋放記憶體中的使用中工作專案。 驅動程式會呼叫 ExFreePool 來釋放集區區塊,其中包含使用 IoQueueWorkItem排入佇列的工作專案。

  • 釋放記憶體中的使用中資源。 驅動程式會呼叫 ExFreePool 以釋放包含使用 中 ERESOURCE 結構的集區區塊。 驅動程式應該先呼叫 ExDeleteResource 來刪除 ERESOURCE 物件,再呼叫 ExFreePool

  • 可用記憶體中的作用中外觀清單。 驅動程式會呼叫 ExFreePool 來釋放仍包含作用中外觀清單的集區區塊, (NPAGED_LOOKASIDE_LISTPAGED_LOOKASIDE_LIST 結構。 驅動程式應該先呼叫 ExDeleteNPagedLopoolsideListExDeletePagedLo才能 刪除 lookaside 清單,再呼叫 ExFreePool

  • Windows Management Instrumentation (WMI) 和 Windows (ETW 的事件追蹤) 註冊問題。 驅動程式驗證器偵測到的這類問題包括:

    • 嘗試卸載而不註冊其 WMI 回呼的驅動程式。

    • 嘗試刪除尚未從 WMI 取消註冊之裝置物件的驅動程式。

    • 嘗試卸載的驅動程式,而不註冊其 ETW 核心模式提供者。

    • 嘗試取消註冊已取消註冊提供者的驅動程式。

  • 核心處理錯誤。 (Windows Vista 和更新版本) 啟用 [其他檢查] 選項也會啟用系統程式的追蹤,以協助調查核心控制碼流失和 錯誤檢查0x93:INVALID_KERNEL_HANDLE。 啟用控制碼追蹤後,核心會收集最近開啟和關閉作業的堆疊追蹤。 堆疊追蹤可以使用 !htrace 偵錯工具擴充功能,在核心偵錯工具中顯示。 如需 !htrace的詳細資訊,請參閱 Windows 的偵錯工具檔。

  • 具有核心模式存取的使用者模式控制碼 從 Windows 7 開始,當您選取 [其他檢查] 選項時,驅動程式驗證器也會檢查 對 ObReferenceObjectByHandle的呼叫。 您無法傳遞具有核心模式存取權的使用者模式控制碼。 如果發生這類作業,驅動程式驗證程式會發出錯誤檢查0xC4,參數 1 值為 0xF6。

  • UserMode 等候在核心堆疊上配置的同步處理物件

    從 Windows 7 開始,驅動程式驗證器可以偵測驅動程式無法正確使用作業系統所提供的多執行緒同步處理機制的其他方式。

    配置同步處理物件,例如 KEVENT 結構,作為核心堆疊上的區域變數是常見的作法。 當進程載入記憶體時,其執行緒的核心堆疊永遠不會從工作集修剪,或分頁到磁片。 在這類不可分頁的記憶體中配置同步處理物件是正確的。

    不過,當驅動程式呼叫如 KeWaitForSingleObjectKeWaitForMultipleObjects等 API 以等候堆疊上配置的物件時,它們必須指定 API 的WaitMode 參數的 KernelMode值。 當進程的所有線程在 UserMode 模式中等候時,該進程就有資格交換至磁片。 因此,如果驅動程式將 UserMode 指定為 WaitMode 參數,只要相同進程中的所有其他執行緒正在等候 UserMode,作業系統就可以交換目前的進程。 將整個進程交換至磁片包括分頁其核心堆疊。 等候作業系統交換的同步處理物件不正確。 在某個時間點,執行緒必須一起出現,併發出同步處理物件的訊號。 發出同步處理物件的訊號牽涉到在 IRQL = DISPATCH_LEVEL或更新版本操作物件的 Windows 核心。 在DISPATCH_LEVEL或更新版本觸碰分頁或交換記憶體會導致系統當機。

    從 Windows 7 開始,當您選取 [其他檢查] 選項時,驅動程式驗證程式會檢查已驗證驅動程式在 UserMode 中等候的同步處理物件是否未配置在目前線程的核心堆疊上。 當驅動程式驗證器偵測到這類不正確的等候時,它會發出 錯誤檢查0xC4:DRIVER_VERIFIER_DETECTED_VIOLATION,且參數 1 值為 0x123。

  • 不正確的核心控制碼參考

    每個 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 命令列,為一或多個驅動程式啟用 [其他檢查] 選項。 如需詳細資訊,請參閱 選取驅動程式驗證器選項

  • 在命令列

    在命令列中,[其他檢查] 選項是由 位 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
    
  • 使用驅動程式驗證器管理員

    1. 啟動驅動程式驗證器管理員。 在 [命令提示字元] 視窗中輸入 驗證程式

    2. 選取 [為程式碼開發人員建立自訂設定] () ,然後按 [ 下一步]。

    3. 從完整清單中選取 [選取個別設定]。

    4. 選取 [其他檢查]。

    其他檢查功能也會包含在標準設定中。 若要使用此功能,請在 [驅動程式驗證器管理員] 中,按一下 [ 建立標準設定]。

檢視結果

若要檢視 [其他檢查] 選項的結果,請在核心偵錯工具中使用 !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.

若要調查集區配置,請使用 !pool 偵錯工具延伸模組搭配集區配置的起始位址 9655D468。 (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