menu

北方天空下

i am not a man of too many faces,the mask i wear is one...

Avatar

驱动程序内存池泄漏导致系统死机的调试

最近S告诉我说电脑老是死机,现象就是用着用着系统就无响应了,键盘鼠标无响应。每周出现上1-2次。。由于环境拿不到没法现场调试,所以只能获取dump来调试了。
对于系统hang住,要获取内存转储可通过键盘手动触发,系统无响应的时候,键盘CTRL+SCROLL LOCK+SCROLL LOCK,就可以生成dump,配置可参考这个:http://support.microsoft.com/kb/244139。

接到Dump后调试一把,windbg显示原因是键盘驱动,Probably caused by : i8042prt.sys ( i8042prt!I8xProcessCrashDump+237 ),当然了,蓝屏就是按出来的。
再看一下内存池的使用

kd> !vm
*** Virtual Memory Usage ***
	Physical Memory:       63358 (    253432 Kb)
	Page File: \??\C:\pagefile.sys
	  Current:    393216 Kb  Free Space:    191636 Kb
	  Minimum:    393216 Kb  Maximum:       786432 Kb
	Available Pages:        5596 (     22384 Kb)
	ResAvail Pages:        21461 (     85844 Kb)
	Locked IO Pages:          48 (       192 Kb)
	Free System PTEs:     236827 (    947308 Kb)
	Free NP PTEs:              0 (         0 Kb)
	Free Special NP:           0 (         0 Kb)
	Modified Pages:          641 (      2564 Kb)
	Modified PF Pages:       641 (      2564 Kb)
	NonPagedPool Usage:    24926 (     99704 Kb)
	NonPagedPool Max:      24927 (     99708 Kb)
	********** Excessive NonPaged Pool Usage *****
	PagedPool 0 Usage:      5233 (     20932 Kb)
	PagedPool 1 Usage:       875 (      3500 Kb)
	PagedPool 2 Usage:       878 (      3512 Kb)
	PagedPool Usage:        6986 (     27944 Kb)
	PagedPool Maximum:     50176 (    200704 Kb)

	********** 102904 pool allocations have failed **********

	Shared Commit:         17737 (     70948 Kb)
	Special Pool:              0 (         0 Kb)
	Shared Process:         2593 (     10372 Kb)
	PagedPool Commit:       6986 (     27944 Kb)
	Driver Commit:          2869 (     11476 Kb)
	Committed pages:      107348 (    429392 Kb)
	Commit limit:         154891 (    619564 Kb)


其中内核非换页池用光了,这估计是死机无响应的直接原因。
NonPagedPool Usage: 24926 ( 99704 Kb)
NonPagedPool Max: 24927 ( 99708 Kb)

很遗憾,生成这个dump的时候S的机器没有启用内核池标签,所以这个dump无法知道是谁用了最多的内存池。于是我又发个工具帮助打开池tag,下次获取的dump才更有意义。
同时,上面这个dump的其他信息显示系统安装了RX和360的驱动,有比较大的嫌疑,所以引入DriverVerifier可以更快的确认问题。有问题的机器上使用DriverVerifier(开始运行输入Verifier),选择对内核驱动程序进行池跟踪(Pool Tracking)检查:
接着在驱动程序列表中选中所有的RX和360的驱动,一共11个
重启系统,果然蓝屏了。。再次打开Dump这次显示是RX的内核驱动HookNtos.sys,说明它存在池泄漏的Bug.

STACK_TEXT:  
f96c7acc 80994673 000000c4 0000003c cdefb104 nt!KeBugCheckEx+0x1b
f96c7aec b9945698 cdefb104 000f0000 82317040 nt!VerifierReferenceObjectByHandle+0x6c
WARNING: Stack unwind information not available. Following frames may be wrong.
f96c7b14 b9945715 00000000 f96c7b24 00000000 HookNtos+0x2698
f96c7d48 808077ec cdefb104 7c94da87 000d8b58 HookNtos+0x2715
f96c7d48 7c92eb94 cdefb104 7c94da87 000d8b58 nt!KiFastCallEntry+0xf8
018efe40 00000000 00000000 00000000 00000000 0x7c92eb94

这次蓝屏的时候池的使用情况:

NonPagedPool Usage:    11110 (     44440 Kb)
NonPagedPool Max:        24927 (     99708 Kb)


虽然没有满,但是用了将近一半。。也不正常。所以要看看都是谁在用:

kd> !poolused 2
   Sorting by  NonPaged Pool Consumed
   Pool Used:
            NonPaged            Paged
 Tag    Allocs     Used    Allocs     Used
GetGlobalValue: unable to get nt!KeNumberProcessors type size
 SaMo       97 25170576         0        0	UNKNOWN pooltag 'SaMo', please update pooltag.txt
 Wdm       765 13461944        22     1688	WDM 
 Ddk       536  1144104         6      336	Default for driver allocated memory (user's of ntddk.h) 
 DmaB       34   729088         0        0	UNKNOWN pooltag 'DmaB', please update pooltag.txt
 063p        6   247384         0        0	UNKNOWN pooltag '063p', please update pooltag.txt
。。。

这是由NonePagedPool使用由多到少的排序,这几个都比较可疑:SaMo ,Ddk ,063p 我怎么知道这些池Tag对应哪些驱动呢?使用Poolmon(win2k3DDK中的工具),使用Poolmon /c 参数后它将扫描所有System32\Drivers目录下的驱动文件,并生成一个驱动和它使用Tag的一个对应清单,在这台机器上这里查到的是:


Ddk    -     HookHelp
Ddk    -     HookSys
Ddk    -     HookCont
Ddk    -     HOOKREG
Ddk    -     HookNtos
Ddk    -     rfwbase
PIAM   -     rfwbase
SaMo   -     SafeboxKrnl
Ddk    -     SafeboxKrnl
063p   -     360AntiARP

这次我的推断是,周老大的SafeboxKrnl(SaMo)在这里使用了最多的非换页池,周老大联手RX的一堆驱动一起(Ddk)取得第三,360AntiARP(063p)也挤进前五。非换页池是Windows内核使用的,内存池耗尽或者不足的时候会影响系统稳定性。

为了验证,系统正常运行时,我使用Poolmon在这台机器上记录了日志,这是实时的日志:


Tag  Type      Diff   Bytes    Per Alloc    Mapped_Driver
 SaMo Nonp        86 19824384     230516        [SafeboxKrnl]
 Wdm  Nonp       771 13464208      17463        [cinemst2][cpqdap01][nikedrv][rio8drv][riodrv][tsbvcap][drmk]
 Ddk  Nonp      1473  996960        676        [ptilink][nv4_mini][basetdi][HookHelp][HookSys][HookCont]
 DmaB Nonp        34  729088      21443        [ALCXWDM]
 File Nonp      1982  336496        169        [<unknown>    - File objects]
 Thre Nonp       505  319160        632        [nt!ps        - Thread objects]
 063p Nonp         6  247384      41230        [360AntiARP]
。。。

,和系统蓝屏的时候差不太多。

至此推断的原因可能是:RX的一个驱动存在内存泄漏,在分配NonePagedPool后,卸载时没有去Free,加上有其他大亨也占用了很多NonePagedPool,所以NonePagedPool最终耗尽了,系统挂起。由于暂时还没有拿到系统死机时带有池标签的Dump文件,所以还不能最终确认。但DriverVerifier检查出的池泄漏的结论是一定的。

P.S. 至于为什么系统在装了杀软后会变慢,这也是其中原因之一了。

强帖留名

未分页内存没有到256MB呢吧?才90多MB?
如果是未分页内存导致的down机,是没有dump的。。。
我以前专门测试过,把一个win2003 32位的nonpagedpool 搞到250MB以上
眼睁睁就不动了。。。没有dump生成。。。。
windows直接歇菜。。。

@PC
Q:未分页内存没有到256MB呢吧?才90多MB?
A:不同系统的池上限是不一定的,Windows会依据系统实际内存大小进行分配,在上述第一个dump的机器上(耗尽挂起),非换页池只有99708Kbytes(99M),在调试器中直接查看系统非换页池的内核变量:
kd> dd mmmaximumnonpagedpoolinbytes l1
80887ec4 0615f000
kd> ? 80887ec4
Evaluate expression: -2138538300 = 80887ec4
kd> ? 615f000
Evaluate expression: 102100992 = 0615f000
102100992/1024=99708 <----这个就是当前实际的非换上限,如果你先看你现在机器上池上限是多少,可以用ProcessExplorer,配上Symbols后在System Infomation里就可以看到了:Paged limit和Nonpaged limit

Q:如果是未分页内存导致的down机,是没有dump的。。。
A:是的,因为系统挂起了,所以要手动用键盘生成dump
见这个链接:http://support.microsoft.com/kb/244139
对系统和键盘类型有一定要求(比如ps2口)

oh,my god...

评论已关闭