Windows Server 2003 でストップエラーが頻発する

こんにちは。プラットフォーム クリティカル レスポンス チームの川上です。

今日は最近複数のお客様からお問い合わせ頂いた Windows Server 2003 のストップエラーが頻発する現象についてお話しします。

インストールしているドライバも更新していないし、ハードウェアにも問題がない。それにも関わらずブルースクリーンが頻発するようになった。そんな状況に陥ったら一度、サポート技術情報 948289 を確認してみてください。

 

 

Error message on a Windows Server 2003-based computer: "Stop error code 0x00000019"

https://support.microsoft.com/kb/948289

 

 

このサポート技術情報を理解するためには、ショートファイル名を知っておく必要があります。

Windows OSで使用しているファイルシステムでは、空白などを含む長いファイル名(ロングファイル名)を扱えますが、以前の MS-DOSでは 8.3形式の短いファイル名(ショートファイル名)しか使用できませんでした。

8.3形式は、ファイル名の部分が最大8文字、拡張子が最大で3文字のファイル名の形式です。現在の Windows ではこのショートファイル名 8.3形式ではなく、ロングファイル名を使用できますが、下位互換性のためにデフォルトではロングファイル名とショートファイル名の両方が管理されています。

ショートファイル名を確認したい場合、dir /x コマンドで見ることができます。

clip_image001

この例ではロングファイル名 testfile1.dat のファイルを dir /x コマンドで確認すると、このファイルはショートファイル名では TESTFI~1.DAT となっている事が確認できます。このようにショートファイル名は同一フォルダ内で重複しないようにチルダ記号 ~ の後に追番を付ける形で8.3形式で作成されます。

 

通常の運用では問題ありませんが、一部アプリケーションソフトウェアなどで単一のフォルダー配下に極端に大量のファイルを作成してしまう場合があります。

このような場合、Windows Server 2003 ではこの追番が長くなりすぎる事を想定していないため、8.3形式に収まらず、関係ないメモリ管理領域まで破壊してしまう場合があります。結果としてプールの管理領域が破壊された事を意味するストップエラー 0x19 (BAD_POOL_HEADER) が発生してしまいます。

clip_image002

 

ブルースクリーンの左上に BAD_POOL_HEADER と表示されている事が確認できます。

 

この問題に対して残念ながら修正プログラムを提供しておりませんが、ショートファイル名の生成を行わないようにする事で現象を回避する事ができます。

まずブルースクリーンが頻発して起動できない場合は、起動時に F8 を押下して Windows 拡張オプションメニューを表示し、セーフモードで起動します。通常起動できるのであれば敢えてセーフモードで起動する必要はありません。

clip_image003

起動したらログオンを行い、コマンドプロンプトからfsutil behavior set disable8dot3 1と入力します。

clip_image004

あとは再起動をすればファイルシステムがショートファイル名を生成しないようになり、今までのようにストップエラーが発生しなくなります。

この現象の詳細はサポート技術情報948289 に詳しく記載されておりますので、合わせてご確認下さい。

この回避手順を行ったことでショートファイル名の作成は行われなくなりますが、この事でアプリケーションソフトウェアに予期せぬ影響などがでた場合、

fsutil behavior set disable8dot3 0 と入力し再起動すればデフォルトの状態に戻すことができます。

 

 

 

補足

この現象が発生した際、あらかじめメモリダンプを出力するように設定している場合はメモリダンプファイルが出力されます。このダンプファイルをデバッカーで解析すると、前述の現象が発生している事が簡単に確認でき、サポート技術情報948289 に合致しているか確認する事ができます。

まずバグチェックコードが 0x19 BAD_POOL_HEADER である事を確認します。

 

1: kd> .bugcheck Bugcheck code 00000019 Arguments 00000020 e142ee08 e142ee70 0c0d040b

 

 

続けてコールスタックを確認するとプール解放中に問題が検出された事が確認でき、IRP から処理しているファイル名はロングファイル名でcore_etest_20131231255999.dmpである事が確認できます。

1: kd> !thread THREAD 89b07020 Cid 0c5c.0c60 Teb: 7ffdf000 Win32Thread: e27cc6d0 IRP List: 89b928d8: (0006,0190) Flags: 00000884 Mdl: 00000000 Not impersonating DeviceMap e10038a8 Owning Process 89b08510 Image: emagent.exe Attached Process N/A Image: N/A Wait Start TickCount 14353 Ticks: 0 Context Switch Count 58882 IdealProcessor: 1 UserTime 00:00:00.015 KernelTime 00:00:07.656 Win32 Start Address 0x004013dc Start Address 0x7c8217f8 Stack Init b9e45000 Current b9e43acc Base b9e45000 Limit b9e41000 Priority 8 BasePriority 8 PriorityDecrement 0 ChildEBP RetAddr b9e44350 808927bb nt!KeBugCheckEx+0x1b (FPO: [Non-Fpo]) b9e443b8 f7b7ac3c nt!ExFreePoolWithTag+0x477 (FPO: [Non-Fpo]) b9e44470 f7b7ac7f Ntfs!NtfsAddDosOnlyName+0x1d1 (FPO: [SEH]) b9e444ac f7b904af Ntfs!NtfsAddLink+0xac (FPO: [Non-Fpo]) b9e446a8 f7b94a04 Ntfs!NtfsCreateNewFile+0x847 (FPO: [Non-Fpo]) b9e448cc f7b91ef8 Ntfs!NtfsCommonCreate+0x1226 (FPO: [Non-Fpo]) b9e449d0 8081df85 Ntfs!NtfsFsdCreate+0x17d (FPO: [Non-Fpo]) b9e449e4 f76f4458 nt!IofCallDriver+0x45 (FPO: [Non-Fpo]) b9e44a10 8081df85 fltmgr!FltpCreate+0xe4 (FPO: [Non-Fpo]) b9e44a24 808f8f71 nt!IofCallDriver+0x45 (FPO: [Non-Fpo]) b9e44b0c 808f93b8 nt!IopParseDevice+0xa35 (FPO: [Non-Fpo]) b9e44b44 809374b1 nt!IopParseFile+0x46 (FPO: [Non-Fpo]) b9e44bc4 80933a76 nt!ObpLookupObjectName+0x11f (FPO: [Non-Fpo]) b9e44c18 808eae25 nt!ObOpenObjectByName+0xea (FPO: [Non-Fpo]) b9e44c94 808ec0bf nt!IopCreateFile+0x447 (FPO: [Non-Fpo]) b9e44cf0 808eeb4e nt!IoCreateFile+0xa3 (FPO: [Non-Fpo]) b9e44d30 808897bc nt!NtCreateFile+0x30 (FPO: [Non-Fpo]) b9e44d30 7c97860c nt!KiFastCallEntry+0xfc )

 

 

 

1: kd> !irp 89b928d8 Irp is active with 8 stacks 8 is current (= 0x89b92a44) No Mdl: No System Buffer: Thread 89b07020: Irp stack trace. cmd flg cl Device File Completion-Context [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 [ 0, 0] 0 0 00000000 00000000 00000000-00000000 Args: 00000000 00000000 00000000 00000000 >[ 0, 0] 0 0 89aa5188 89074ab0 00000000-00000000 \FileSystem\Ntfs Args: b9e44a50 05000060 00010080 00000000

1: kd> !fileobj 89074ab0 \test\product\core_etest_20131231255999.dmp

Related File Object: 0x88f94dd0

Device Object: 0x89d48a60 \Driver\Ftdisk Vpb: 0x89f25ae0 Access: Write SharedRead

Flags: 0x42 Synchronous IO Cache Supported

FsContext: 0xe271fda0 FsContext2: 0xe271fee8 CurrentByteOffset: 0 Cache Data: Section Object Pointers: 890fd91c Shared Cache Map: 00000000

 

 

 

 

もう一度バグチェックコードを確認し、第2引数には問題を検出したプール領域アドレスが格納されている事を確認します。今回の例ではe142ee08 が問題が検出された領域になります。

1: kd> .bugcheck Bugcheck code 00000019 Arguments 00000020 e142ee08 e142ee70 0c0d040b

 

 

問題が検出されたプール領域の付近を !pool 確認すると破損が検出されます。

1: kd> !pool e142ee08 Pool page e142ee08 region is Paged pool e142e000 size: 58 previous size: 0 (Allocated) CMDa e142e058 size: 10 previous size: 58 (Allocated) Wmip

( 途中省略 )

e142e068 size: 18 previous size: 10 (Allocated) Pp e142e080 size: 40 previous size: 18 (Allocated) Pp e142ecd8 size: 68 previous size: 20 (Allocated) Key (Protected) e142ed40 size: 68 previous size: 68 (Allocated) Key (Protected) e142eda8 size: 8 previous size: 68 (Free) CMVa e142edb0 size: 58 previous size: 8 (Allocated) Sect (Protected) *e142ee08 size: 68 previous size: 58 (Allocated) *NtFA Pooltag NtFA : AttrSup.c, Binary : ntfs.sys

e142ee70 doesn't look like a valid small pool allocation, checking to see

if the entire page is actually part of a large page allocation...

e142ee70 is not a valid large pool allocation, checking large session pool... e142ee70 is freed (or corrupt) pool

Bad previous allocation size @e142ee70, last size was d *** *** An error (or corruption) in the pool was detected; *** Attempting to diagnose the problem. *** *** Use !poolval e142e000 for more details.

 

 

それでは、もう少し詳細に確認していきましょう。

プール領域e142ee08 は0x68 バイト確保されている事がわかりますので、e142ee08 から内容を表示してみますと、先ほどのロングファイル名core_etest_20131231255999.dmp を変換したと考えられるCORE_E~1000005.DMP の文字列が確認できます。

1: kd> dc e142ee08 e142ee08 0c0d040b 4146744e 0000b565 00010000 ....NtFAe....... e142ee18 12eb10da 01ce7095 12eb10da 01ce7095 .....p.......p.. e142ee28 12eb10da 01ce7095 12eb10da 01ce7095 .....p.......p.. e142ee38 00000000 00000000 00000000 00000000 ................ e142ee48 00000020 00000000 00430212 0052004f .........C.O.R. e142ee58 005f0045 007e0045 00300031 00300030 E._.E.~.1.0.0.0. e142ee68 00300030 002e0035 004d0044 20370050 0.0.5...D.M.P.7 e142ee78 e101bd30 e18b93d0 00001000 00d0e000 0...............

 

 

しかしながら赤い部分が 0x68 バイトになりますので、この0x68 バイト分で確保したプール領域を超えて、直後の黄色の管理領域まで上書きしてしまった事が確認できます。このような状態であればサポート技術情報948289 の現象と同一であると判断する事ができます。