Win2000のNtQuerySystemInformationに16年来のバグ
DropBoxがCPU使い切ってフリーズするようになってしまったという報告を受けて調査して分かったことは
psutil._psutil_windows.pyd という、Python のバイナリがNtQuerySystemInformation のSystemProcessInformation命令でぐるぐる回ってることでした。
たいぶろぐ [Rainmeter-dev] Rainmeter on Windows 2000
取得には全プロセス分のバッファが必要になりますが、プロセス数×構造体のサイズ(+α)という単純な方法ではダメなようです。必要なバッ ファサイズはNtQuerySystemInformation APIを呼び出すことで取得できるとドキュメントには記載されていますが、どうもWindows 2000では必ず0が返ってくるようで(XPだとちゃんと必要なバッファサイズが返ってくる)、仕方ないので、成功するまでバッファサイズを 16KB分から倍々に増やしていくようにしています。 |
|。・ω・)。・ω・)。・ω・)な、なんだってー!?
そりゃ、ループするわ。
というわけで、コード書きました
_declspec(naked) _declspec(dllexport) int WINAPI NtQuerySystemInformation(int x,void *y,int s,int *ss){ _asm{ mov eax,00000097h lea edx,[esp+04h] int 2Eh cmp [esp+4],5 jnz ER cmp eax,0xc0000004 jnz ER mov ecx,DWORD PTR[esp+10h] test ecx,ecx jz ER mov ecx,DWORD PTR[ecx] test ecx,ecx jnz ER push ebp |
要するに NtQuerySystemInformationよんで
第一パラメータがSystemProcessInformationの場合でなおかつ結果が 0xc0000004 (STATUS_INFO_LENGTH_MISMATCH)だった場合で、最終パラメータがNULLじゃなかった場合に、
適切な領域を返すように処理を追加。
int 2Ehを見てわかるように本来 NTOSKRNL.EXE 側の処理なのですが、ちょっとデバッグするには無理があるのでNTDLL上で修正コードを書きました。
拡張カーネル v2.6cより変更が反映されています。
※ v2.6cに不具合があったため 20:30に v2.6c2に差し替えてあります
Comments