Утечки памяти в пулах ядра

rating_off-9809012rating_off-9809012rating_off-9809012rating_off-9809012rating_off-9809012 (No Ratings Yet)

Всем привет. Сегодня мы рассмотрим еще одну проблему, которая может возникать в коде Kernel Mode и которая связана с утечкой памяти. Мы все понимаем, что такое утечка памяти (это когда код выделяет память а обратно системе ее не возвращает), более того, в большинстве программ написанных с использованием технологий не предусматривающих автоматическую сборку мусора (н-р С/С++) эти утечки встречаются довольно часто. К сожалению это характерно и для систем, который предусматривают автоматическую сборку мусора (С#, Java например), особенно если эти приложения являются серверными.

Чтобы этой проблемы не было, требуется более профессиональный подход в написании кода, дополнительное тестирование (или же дополнительные планки памяти, шутка :)). Для стационарных ПК проблема всегда решается просто, перегрузил и работай по новой, но с серверами, который работают в режиме 24 часа в сутки, все может быть намного сложней и требует вмешательства администраторов.

Что же происходит при утечке в памяти ядра? Как мы знаем, код, который работает в Kernel Mode использует 2-а типа памяти:

Для выделения и освобождения памяти используются функции семейства ExAllocatePool

image_thumb10-3239632

Для освобождения – семейства ExFree

image_thumb11-3733733 

Более детальную информацию об этих функциях смотрите на MSDN.

При нехватке памяти в одном из этих пулов, происходит BSOD, при этом здесь могут быть разные варианты (в зависимости от версии ОС, установленных драйверов). Почему так? Потому что, какой-то драйвер стороннего производителя может в своем коде не предусматривать тот вариант, что возникает проблем с выделением памяти и работать дальше.

Давайте рассмотрим пример, берем NotMyFoult Руссиновича, которую мы уже не раз обсуждали и пытаемся вызывать крах систем в подкачиваемой памяти (выбираем Leak / Leak Paged).

image_thumb12-2305900

Устанавливаем 10 Мбайт в сек, чтобы долго не ждать.

image_thumb13-2572433

Vista x86 (без сторонних драйверов) упорно продолжала держаться, хотя посмотрите на скриншот ниже, все уже и не работало как нужно. Я за час работы так и не дождался краха.

image_thumb14-9270130

Хорошо, перезапускаем виртуальную рабочую станцию и выбираем утечку памяти в NonPaged Pool.

Через время возникает BSOD 0x000000A5 — ACPI_BIOS_ERROR

image_thumb15-8665784

Давайте выполним анализ дампа краха.

************* Symbol Path validation summary **************
Response Time (ms) Location
Deferred srv*C:Symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*C:Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is: Windows Server 2008/Windows Vista Kernel Version 6002 (Service Pack 2) UP Free x86 compatible
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 6002.18005.x86fre.lh_sp2rtm.090410-1830
Machine Name:
Kernel base = 0x81a11000 PsLoadedModuleList = 0x81b28c70
Debug session time: Thu Aug 13 13:09:12.276 2015 (UTC + 3:00)
System Uptime: 0 days 0:05:42.933
Loading Kernel Symbols
...............................................................
................................................................
.........................
Loading User Symbols
Loading unloaded module list
....
*******************************************************************************
* *
* Bugcheck Analysis *
* *
******************************************************************************* Use !analyze -v to get detailed debugging information. BugCheck A5, {3, 0, c000009a, 0} Probably caused by : Unknown_Image ( ANALYSIS_INCONCLUSIVE ) Followup: MachineOwner
--------- kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
******************************************************************************* ACPI_BIOS_ERROR (a5)
The ACPI Bios in the system is not fully compliant with the ACPI specification.
The first value indicates where the incompatibility lies:
This bug check covers a great variety of ACPI problems. If a kernel debugger
is attached, use "!analyze -v". This command will analyze the precise problem,
and display whatever information is most useful for debugging the specific
error.
Arguments:
Arg1: 00000003, ACPI_FAILED_MUST_SUCCEED_METHOD ACPI tried to run a control method while creating device extensions to represent the ACPI namespace, but this control method failed.
Arg2: 00000000, The ACPI Object that was being run
Arg3: c000009a, return value from the interpreter
Arg4: 00000000, Name of the control method (in ULONG format)

Debugging Details:
------------------


ACPI_OBJECT:  00000000

BUGCHECK_STR:  0xA5_ACPI_STATUS_INSUFFICIENT_RESOURCES

CUSTOMER_CRASH_COUNT:  2

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

PROCESS_NAME:  System

CURRENT_IRQL:  2

ANALYSIS_VERSION: 6.3.9600.17298 (debuggers(dbg).141024-1500) amd64fre

DPC_STACK_BASE:  FFFFFFFF8039E000

STACK_TEXT:  
8039df0c 8069141f 000000a5 00000003 00000000 nt!KeBugCheckEx+0x1e
8039df28 80692053 00000000 c000009a 00000000 acpi!ACPIBuildCompleteMustSucceed+0x33
8039df4c 80692608 00000000 81ab7a00 806b9ce0 acpi!ACPIBuildProcessDevicePhaseAdrOrHid+0xef
8039df70 80693260 806b9d30 806b7030 806b9ce0 acpi!ACPIBuildProcessGenericList+0x52
8039df88 81abb6a2 806b9ce0 00000000 00000000 acpi!ACPIBuildDeviceDpc+0xca
8039dff4 81ab92d5 8453e8b0 00000000 00000000 nt!KiRetireDpcList+0x147
8453e8cc 81dd1668 806b9d02 00000000 85f7cad8 nt!KiDispatchInterrupt+0x45
8453e8e8 81dd170c 81dcde00 806b9d00 8453e914 hal!HalpCheckForSoftwareInterrupt+0x64
8453e8f8 81dcdf6b 80692fb7 806b9b60 86abfcb8 hal!KfLowerIrql+0x64
8453e8fc 80692fb7 806b9b60 86abfcb8 00000000 hal!KfReleaseSpinLock+0xb
8453e914 806bbee3 86abfcb8 80691a40 8453e934 acpi!ACPIBuildSpecialSynchronizationRequest+0xf3
8453e944 806962da 86abfcb8 00000000 8453e9cc acpi!ACPIBuildFlushQueue+0x2d
8453e988 806bc64d 85f7bcb8 8453e9cc 00000000 acpi!ACPIDetectPdoDevices+0x92
8453e9a0 806bce74 85f7bcb8 d6644f68 8453e9cc acpi!ACPIBusIrpQueryBusRelations+0x2b
8453e9c0 80698e67 85f7bcb8 00000000 85f7bcb8 acpi!ACPIBusIrpQueryDeviceRelations+0x52
8453e9f0 81cf36be 85f7bcb8 86abfcb8 d6644ffc acpi!ACPIDispatchIrp+0xff
8453ea14 81a5592d d6644fd8 8453ea90 85f7bcb8 nt!IovCallDriver+0x23f
8453ea28 81b763ad 00000000 85f7bcb8 8a630ce8 nt!IofCallDriver+0x1b
8453ea44 81b762e3 8453ea6c 81a1db6e 8a630ce8 nt!PnpAsynchronousCall+0x96
8453ea94 81b7607a 00000000 81a1db6e 8a630ce8 nt!PnpQueryDeviceRelations+0x9b
8453ead8 81b72be2 8a630ce8 00000000 97d756b0 nt!PipEnumerateDevice+0x102
8453ecd4 81b7af31 85f7cea8 97d756b0 8453ed00 nt!PipProcessDevNodeTree+0x317
8453ed08 81a1d6d2 81b1313c 8318ed78 81b43520 nt!PiProcessReenumeration+0x5d
8453ed44 81ab6e22 00000000 00000000 8318ed78 nt!PnpDeviceActionWorker+0x1e7
8453ed7c 81be6c42 00000000 5b903ef3 00000000 nt!ExpWorkerThread+0xfd
8453edc0 81a4fefe 81ab6d25 00000001 00000000 nt!PspSystemThreadStartup+0x9d
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16


STACK_COMMAND:  kb

SYMBOL_NAME:  ANALYSIS_INCONCLUSIVE

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: Unknown_Module

IMAGE_NAME:  Unknown_Image

DEBUG_FLR_IMAGE_TIMESTAMP:  0

IMAGE_VERSION:  

FAILURE_BUCKET_ID:  0xA5_ACPI_STATUS_INSUFFICIENT_RESOURCES_ANALYSIS_INCONCLUSIVE

BUCKET_ID:  0xA5_ACPI_STATUS_INSUFFICIENT_RESOURCES_ANALYSIS_INCONCLUSIVE

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:0xa5_acpi_status_insufficient_resources_analysis_inconclusive

FAILURE_ID_HASH:  {a4542cfc-871a-ff92-6ff2-f09e0216672f}

Followup: MachineOwner

По начальному анализу сложно понять, что у нас за проблема. Кроме того, мы делаем все это на виртуалке, она тоже может вносить свою лепту в то, какой будет стоп код.

Давайте выполним проверку состояния памяти на момент краха. Для этого используется расширение:

!poolused

Однако у меня так ничего и не получилось с отображением данных по пулах. Поэтому переходим на реальный Windows 8 (не на виртуальной рабочей станции). На реальной Windows 8 в итоге были очень большие тормоза в работе системе, но краха не было.

Теперь проверяем Windows XP SP3 на виртуалке. Опять дикие тормоза в ОС, но система без BSOD-а.

Таким образом утечка памяти в ядре один раз вызвала BSOD — ACPI_BIOS_ERROR (a5). В остальных случаях ОС практически не реагировала на действия пользователя.

Автор

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: