Прочие проверки
Параметр Прочие проверки средства проверки драйверов отслеживает драйвер на наличие распространенных ошибок, вызывающих сбой драйвера или системы, таких как освобождение памяти, которая по-прежнему содержит активные объекты ядра.
В частности, параметр Прочие проверки ищет следующее неправильное поведение драйвера:
Активные рабочие элементы в освобожденной памяти. Драйвер вызывает ExFreePool , чтобы освободить блок пула, содержащий рабочие элементы, которые были поставлены в очередь с помощью IoQueueWorkItem.
Активные ресурсы в освобожденной памяти. Драйвер вызывает ExFreePool , чтобы освободить блок пула, содержащий активные структуры ERESOURCE. Драйвер должен вызвать ExDeleteResource , чтобы удалить объекты ERESOURCE перед вызовом ExFreePool.
Активные списки lookaside в освобожденной памяти. Драйвер вызывает ExFreePool , чтобы освободить блок пула, который по-прежнему содержит активные списки lookaside (NPAGED_LOOKASIDE_LIST или PAGED_LOOKASIDE_LIST структуры. Драйвер должен вызвать ExDeleteNPagedLookasideList или ExDeletePagedLookasideList , чтобы удалить списки lookaside перед вызовом ExFreePool.
Проблемы с регистрацией инструментария управления Windows (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, в качестве локальных переменных в стеке ядра. Пока процесс загружается в память, стеки ядра его потоков никогда не обрезаются из рабочего набора или не отправляются на диск. Правильное выделение объектов синхронизации в такой памяти, не доступной для страниц.
Однако когда драйверы вызывают API, такие как KeWaitForSingleObject или KeWaitForMultipleObjects , чтобы дождаться объекта, выделенного в стеке, они должны указать значение KernelMode для параметра WaitMode API. Когда все потоки процесса ожидают в режиме UserMode , этот процесс становится доступным для переключения на диск. Таким образом, если драйвер указал UserMode в качестве параметра WaitMode , операционная система может переключить текущий процесс, пока все остальные потоки в том же процессе тоже ожидают , как UserMode. Переключение всего процесса на диск включает разбиение по страницам стеков ядра. Неправильное ожидание объекта синхронизации, который переключила операционная система. В какой-то момент поток должен прийти вместе и сообщить об объекте синхронизации. Сигнал объекта синхронизации включает в себя ядро Windows, манипулируя объектом в IRQL = DISPATCH_LEVEL или выше. Касание разбиения или переключения памяти на 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
Использование диспетчера проверки драйверов
Запустите диспетчер проверки драйверов. Введите 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.
Чтобы исследовать выделение пула, используйте расширение отладчика !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