WinDbg のカーネルデバッガに10年以上前からある致命的な欠陥

Windows 8 (x64)向けのドライバ開発で、メモリリークが発生して WinDbgで リーク場所探してたんですが…。

Debugging memory leaks - DRIVER_VERIFIER_DETECTED_VIOLATION (C4): 0x62 (Windows Drivers)

*** Fatal System Error: 0x000000c4
                       (0x0000000000000062,0xFFFFE0000015F508,0xFFFFE000032B2500,0x0000000000000001)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

nt!DbgBreakPointWithStatus:
fffff801`e9d5d890 cc              int     3

0: kd> !verifier 3 mofusb64.sys

Verify Flags Level 0x000209bb

  STANDARD FLAGS:
    [X] (0x00000000) Automatic Checks
    [X] (0x00000001) Special pool
    [X] (0x00000002) Force IRQL checking
    [X] (0x00000008) Pool tracking
    [X] (0x00000010) I/O verification
    [X] (0x00000020) Deadlock detection
    [X] (0x00000080) DMA checking
    [X] (0x00000100) Security checks
    [X] (0x00000800) Miscellaneous checks
    [X] (0x00020000) DDI compliance checking

  ADDITIONAL FLAGS:
    [ ] (0x00000004) Randomized low resources simulation
    [ ] (0x00000200) Force pending I/O requests
    [ ] (0x00000400) IRP logging
    [ ] (0x00002000) Invariant MDL checking for stack
    [ ] (0x00004000) Invariant MDL checking for driver
    [ ] (0x00008000) Power framework delay fuzzing
    [ ] (0x00040000) Systematic low resources simulation
    [ ] (0x00080000) DDI compliance checking (additional)
    [ ] (0x00200000) NDIS/WIFI verification
    [ ] (0x00800000) Kernel synchronization delay fuzzing
    [ ] (0x01000000) VM switch verification

    [X] Indicates flag is enabled

Summary of All Verifier Statistics

  RaiseIrqls           0xe
  AcquireSpinLocks     0x0
  Synch Executions     0x1
  Trims                0x360

  Pool Allocations Attempted             0x2b85
  Pool Allocations Succeeded             0x2b85
  Pool Allocations Succeeded SpecialPool 0x2b85
  Pool Allocations With NO TAG           0x0
  Pool Allocations Failed                0x0

  Current paged pool allocations         0x5a for 00002E13 bytes
  Peak paged pool allocations            0x67 for 00008DBA bytes
  Current nonpaged pool allocations      0x325 for 00055EF3 bytes
  Peak nonpaged pool allocations         0x32e for 000565E0 bytes

Driver Verification List
------------------------

  MODULE: 0xffffe00000058960 mofusb64.sys (Loaded)

    Pool Allocation Statistics: ( NonPagedPool / PagedPool )

      Current Pool Allocations: ( 0x00000001 / 0x00000001 )
      Current Pool Bytes:       ( 0x00000013 / 0x00000039 )

      Peak Pool Allocations:    ( 0x00000001 / 0x00000002 )
      Peak Pool Bytes:          ( 0x00000013 / 0x000000ab )
      Contiguous Memory Bytes:       0x00000000
      Peak Contiguous Memory Bytes:  0x00000000

    Pool Allocations:

      Address             Length      Tag   Caller Address    
      ------------------  ----------  ----  ------------------
なぜか表示されない

    Contiguous allocations are not displayed with public symbols.

コマンド !verifier 3 ドライバ名 で表示されるはずが何も表示されない…!
いや、 Current Pool Allocations にちゃんと 1って出てる!

ネットで調べてみたところ驚愕の事実が発覚!・ω・


OSR's ntdev List: !verifier analysis question

Crash, but allocations not showing in list:
--------------------------------------------------
This is an issue with the Verifier debugger extension and how the pool
alloc/free information is stored. The leaked allocations were all an odd number
of bytes, and when walking through the list of allocations and frees for a
driver, when the number of bytes is odd (non-even), that allocation is not
displayed in the list.

The three allocations in the !analyze output from the first post add up to 0x85
bytes, meaning at least one had to be odd. As it turns out, all three were odd,
and hence, none were displayed in the "!verifier 3 MyDriver.sys" output. (Had 2
been even and 1 odd, the 2 evens would've shown up, no matter their place in the
list).
Thanks again for bringing these to our attention, Dave! Determining what to do
and "fixing" these is already under way.

メモリリークした確保領域のサイズが奇数バイトだと表示されない

ちょっww!
|・ω・)・ω・)・ω・)  な、なんだってー!?

どうやら、このバグ10年以上前からあるらしいんですがw。

メモリーリーク場所を突き止めた後で、偶数バイトにしてみました

Driver Verification List
------------------------

  MODULE: 0xffffe00000058960 Mofusb64.sys (Loaded)

    Pool Allocation Statistics: ( NonPagedPool / PagedPool )

      Current Pool Allocations: ( 0x00000002 / 0x00000000 )
      Current Pool Bytes:       ( 0x0000008a / 0x00000000 )
      Peak Pool Allocations:    ( 0x00000005 / 0x00000002 )
      Peak Pool Bytes:          ( 0x00000600 / 0x000000ab )
      Contiguous Memory Bytes:       0x00000000
      Peak Contiguous Memory Bytes:  0x00000000

    Pool Allocations:

      Address             Length      Tag   Caller Address    
      ------------------  ----------  ----  ------------------
      0xffffcf8001d02f80  0x00000078  MOFI  0xfffff80003202f5c  MofUsb64!sMofusb_SelectInterfaces
      0xffffcf8001780fe0  0x00000012  MOFD  0xfffff80003203798  MofUsb64!sMofusb_StartDevice

    Contiguous allocations are not displayed with public symbols.

出てきたー!

・ω・ すげー悩んじまったわい。

おすすめ

2件のフィードバック

  1. さまよえるPC-9821使い より:

    Pentium以降だとメモリに対しては4Byteアクセスなので偶数アドレスにアラインされているのが当然という考え方なんでしょうね。
    インテル系は奇数番地からの読み書きだとその分ペナルティが発生しますが、とりあえず動きます。
    RISC系だともっと深刻で例外割り込みが発生して停まってしまうこともあるようですね。

  2. 黒翼猫 より:

    データーの割り当てアドレスは8の倍数を指定しています。
    その割り当てサイズが奇数だった場合でてこないのです・ω・

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です