bad_pool_header

Тема в разделе "WASM.NT.KERNEL", создана пользователем tapa, 30 янв 2011.

  1. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    привет. при вызове NdisZeroMemory получаю bsod(BAD_POOL_HEADER)

    Вызов DeviceIoControl из польз. режима
    Код (Text):
    1. //..
    2.     typedef __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) QueryBindingCharBuf;        
    3.     QueryBindingCharBuf     Buf[1024];
    4.     DWORD                   BufLength = sizeof(Buf);
    5.     DWORD                   BytesWritten;
    6.     PTELINK_QUERY_BINDING   pQueryBinding;
    7.  
    8.     pQueryBinding = (PTELINK_QUERY_BINDING)Buf;
    9.  
    10.    if(DeviceIoControl(hndl, IOCTL_TELINK_QUERY_BINDING, pQueryBinding, sizeof(TELINK_QUERY_BINDING),Buf, BufLength, &BytesWritten, NULL))
    11.    {
    12.    //...
    13.    }
    14. //..
    Обработчик IRP_MJ_DEVICE_CONTROL
    Код (Text):
    1. //...
    2.     case IOCTL_TELINK_QUERY_BINDING:
    3.         Status = TeLinkQueryBinding((PUCHAR)pIrp->AssociatedIrp.SystemBuffer,
    4.                             pIrpStk->Parameters.DeviceIoControl.InputBufferLength,
    5.                             pIrpStk->Parameters.DeviceIoControl.OutputBufferLength,
    6.                             &Bts);
    7.  
    8.         NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
    9.         break;
    10. //..
    TeLinkQueryBinding
    Код (Text):
    1. NTSTATUS TeLinkQueryBinding(IN PUCHAR pBuffer, IN ULONG InputLength, IN ULONG OutputLength, OUT PULONG pBytesReturned)
    2. {
    3.     PLIST_ENTRY pEnt;
    4.     NDIS_STATUS Status;
    5.     ULONG Remaining;
    6.     PTELINK_QUERY_BINDING pQueryBinding;
    7.     ULONG BindingIndex;
    8.     t_nic* nic;
    9.    
    10.     do
    11.     {
    12.         if (InputLength < sizeof(TELINK_QUERY_BINDING))
    13.         {
    14.             Status = NDIS_STATUS_RESOURCES;
    15.             //break;
    16.         }
    17.         if (OutputLength < sizeof(TELINK_QUERY_BINDING))
    18.         {
    19.             Status = NDIS_STATUS_BUFFER_OVERFLOW;
    20.             //break;
    21.         }
    22.  
    23.         Remaining = OutputLength - sizeof(TELINK_QUERY_BINDING);
    24.  
    25.         pQueryBinding = (PTELINK_QUERY_BINDING)pBuffer;
    26.         BindingIndex = pQueryBinding->BindingIndex;
    27.  
    28.         Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
    29.  
    30.         nic = NULL;
    31.  
    32.         NdisAcquireSpinLock(&GLOBAL_DATA.NDIS_LOCK);
    33.  
    34.         for (pEnt = GLOBAL_DATA.NICs.Flink; pEnt != &GLOBAL_DATA.NICs; pEnt = pEnt->Flink)
    35.         {
    36.             nic = CONTAINING_RECORD(pEnt, t_nic, Link);
    37.            
    38.             NdisAcquireSpinLock(&nic->Lock);       
    39.  
    40.             //NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
    41.  
    42.  
    43.             if(BindingIndex == 0)
    44.             {      
    45.            
    46.                 pQueryBinding->DeviceNameLength = nic->Name.Length + sizeof(WCHAR);
    47.                 pQueryBinding->DeviceDescrLength = nic->FriendlyName.Length + sizeof(WCHAR);
    48.  
    49.                 if (Remaining < pQueryBinding->DeviceNameLength +
    50.                                 pQueryBinding->DeviceDescrLength)
    51.                 {
    52.                     NdisReleaseSpinLock(&nic->Lock);
    53.                     Status = NDIS_STATUS_BUFFER_OVERFLOW;
    54.                     break;
    55.                 }
    56.         //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    57.                 NdisZeroMemory((PUCHAR)pBuffer + sizeof(TELINK_QUERY_BINDING),
    58.                                 pQueryBinding->DeviceNameLength +
    59.                                 pQueryBinding->DeviceDescrLength);
    60.                
    61.                 pQueryBinding->DeviceNameOffset = sizeof(TELINK_QUERY_BINDING);
    62.                 NdisMoveMemory((PUCHAR)pBuffer + pQueryBinding->DeviceNameOffset,
    63.                                 nic->Name.Buffer,
    64.                                 nic->Name.Length);
    65.                
    66.                 pQueryBinding->DeviceDescrOffset = pQueryBinding->DeviceNameOffset +
    67.                                                     pQueryBinding->DeviceNameLength;
    68.                 NdisMoveMemory((PUCHAR)pBuffer + pQueryBinding->DeviceDescrOffset,
    69.                                 nic->FriendlyName.Buffer,
    70.                                 nic->FriendlyName.Length);
    71.                
    72.                 NdisReleaseSpinLock(&nic->Lock);
    73.  
    74.                 *pBytesReturned = pQueryBinding->DeviceDescrOffset + pQueryBinding->DeviceDescrLength;
    75.                            */    
    76.                
    77.                 Status = NDIS_STATUS_SUCCESS;
    78.                 break;
    79.             }
    80.             NdisReleaseSpinLock(&nic->Lock);
    81.             BindingIndex--;
    82.         }
    83.  
    84.         NdisReleaseSpinLock(&GLOBAL_DATA.NDIS_LOCK);
    85.     }
    86.     while(FALSE);
    87.     return (Status);
    88. }
    TELINK_QUERY_BINDING
    Код (Text):
    1. typedef struct _TELINK_QUERY_BINDING
    2. {
    3.     ULONG            BindingIndex;      
    4.     ULONG            DeviceNameOffset;  
    5.     ULONG            DeviceNameLength;    
    6.     ULONG            DeviceDescrOffset;  
    7.     ULONG            DeviceDescrLength;  
    8.  
    9. } TELINK_QUERY_BINDING, *PTELINK_QUERY_BINDING;
    kd> !analyze -v
    Код (Text):
    1. *******************************************************************************
    2. *                                                                             *
    3. *                        Bugcheck Analysis                                    *
    4. *                                                                             *
    5. *******************************************************************************
    6.  
    7. BAD_POOL_HEADER (19)
    8. The pool is already corrupt at the time of the current request.
    9. This may or may not be due to the caller.
    10. The internal pool links must be walked to figure out a possible cause of
    11. the problem, and then special pool applied to the suspect tags or the driver
    12. verifier to a suspect driver.
    13. Arguments:
    14. Arg1: 00000020, a pool block header size is corrupt.
    15. Arg2: 8a209a50, The pool entry we were looking for within the page.
    16. Arg3: 8a209a70, The next pool entry.
    17. Arg4: 1a040001, (reserved)
    18.  
    19. Debugging Details:
    20. ------------------
    21.  
    22.  
    23. BUGCHECK_STR:  0x19_20
    24.  
    25. POOL_ADDRESS:  8a209a50
    26.  
    27. CUSTOMER_CRASH_COUNT:  4
    28.  
    29. DEFAULT_BUCKET_ID:  COMMON_SYSTEM_FAULT
    30.  
    31. PROCESS_NAME:  utelink.exe
    32.  
    33. IRP_ADDRESS:  8a20f150
    34.  
    35. LAST_CONTROL_TRANSFER:  from 80874583 to 80822f43
    36.  
    37. STACK_TEXT:  
    38. b319aa40 80874583 00000019 00000020 8a209a50 nt!KeBugCheckEx+0x1b
    39. b319aa90 8081dc20 8a209a58 00000000 8a20f190 nt!ExFreePoolWithTag+0x2a3
    40. b319aae8 80828853 8a20f190 b319ab34 b319ab28 nt!IopCompleteRequest+0xf4
    41. b319ab38 80a0fef2 00000000 00000000 b319ab50 nt!KiDeliverApc+0xb3
    42. b319ab38 80a0fae4 00000000 00000000 b319ab50 hal!HalpApcInterrupt+0xc6
    43. b319abc0 808254f7 8a20f190 8a20f150 00000000 hal!KeReleaseQueuedSpinLock+0x3c
    44. b319abe0 8081a7f6 8a20f190 8a0e7470 00000000 nt!KeInsertQueueApc+0x6d
    45. b319ac14 b8488e35 00000005 00000000 0006ff60 nt!IopfCompleteRequest+0x1d8
    46. WARNING: Stack unwind information not available. Following frames may be wrong.
    47. b319ac40 8081819f 8a23b780 8a20f150 80a0f410 TeLink+0xe35
    48. b319ac50 808a8982 8a20f1c0 8a0e7470 8a20f150 nt!IopfCallDriver+0x31
    49. b319ac64 808a97f7 8a23b780 8a20f150 8a0e7470 nt!IopSynchronousServiceTail+0x70
    50. b319ad00 808a2274 0000001c 00000000 00000000 nt!IopXxxControlFile+0x5c5
    51. b319ad34 8086a64c 0000001c 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
    52. b319ad34 7c90e514 0000001c 00000000 00000000 nt!KiFastCallEntry+0xfc
    53. 0006ef28 00000000 00000000 00000000 00000000 0x7c90e514
    54.  
    55.  
    56. STACK_COMMAND:  kb
    57.  
    58. FOLLOWUP_IP:
    59. TeLink+e35
    60. b8488e35 ??              ???
    61.  
    62. SYMBOL_STACK_INDEX:  8
    63.  
    64. SYMBOL_NAME:  TeLink+e35
    65.  
    66. FOLLOWUP_NAME:  MachineOwner
    67.  
    68. MODULE_NAME: TeLink
    69.  
    70. IMAGE_NAME:  TeLink.sys
    71.  
    72. DEBUG_FLR_IMAGE_TIMESTAMP:  4d458dd7
    73.  
    74. FAILURE_BUCKET_ID:  0x19_20_TeLink+e35
    75.  
    76. BUCKET_ID:  0x19_20_TeLink+e35
    77.  
    78. Followup: MachineOwner
    79. ---------
    Оригинал D:\WinDDK\src\network\ndis\ndisprot\5x.
    Не пойму где я лажаю(
     
  2. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Ошибка в работе с выделенной через ExAllocatePoolWithTag памятью. Переписан заголовок, такое часто бывает при выходе за границу массива.
     
  3. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    Не пойму - как это связано. ExAllocatePoolWithTag у меня вызывается один раз, при инициализации протокола.
    ps: посмотрел в windbg, всё падает на IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     
  4. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    Код (Text):
    1.    
    2.    Remaining = OutputLength - sizeof(TELINK_QUERY_BINDING); //OutputLength - pIrpStk->Parameters.DeviceIoControl.OutputBufferLength,
    3.    //....Помещается ли имя адаптера в буфер
    4.    pQueryBinding->DeviceNameLength = nic->Name.Length + sizeof(WCHAR);
    5.    pQueryBinding->DeviceDescrLength = nic->FriendlyName.Length + sizeof(WCHAR);
    6.  
    7.    if (Remaining < pQueryBinding->DeviceNameLength + pQueryBinding->DeviceDescrLength)
    8.    {
    9.        NdisReleaseSpinLock(&nic->Lock);
    10.        Status = NDIS_STATUS_BUFFER_OVERFLOW;
    11.        break;
    12.    }
    13.    //всё ок, забиваем нулями нужный кусок памяти
    14.    NdisZeroMemory((PUCHAR)pBuffer + sizeof(TELINK_QUERY_BINDING),
    15.            pQueryBinding->DeviceNameLength + pQueryBinding->DeviceDescrLength);
    И всё равно всё слетает.

    В отладчике при входе в IRP_MJ_DEVICE_CONTROL
    pBuffer - 0x8211ae50 ""

    И затем
    BugCheck 19, {20, 8211ae48, 8211ae68, 1a040001}

    И в NdisZeroMemory понятно, что затираю заголовок. Но почему pIrp->AssociatedIrp.SystemBuffer указывает на эту область(NonPaged pool table?),а не на выделенный кусок памяти?
     
  5. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Не уловил двух вещей:

    1. Как инициализируется pBuffer?
    2. Почему pIrp->AssociatedIrp.SystemBuffer должно указывать на некий выделенный кусок памяти? Его выделяет и заполняет I/O Manager же.
     
  6. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    1.
    Код (Text):
    1. NTSTATUS TeLinkQueryBinding(IN PUCHAR pBuffer, IN ULONG InputLength, IN ULONG OutputLength, OUT PULONG pBytesReturned)
    2. {
    3. //...
    4. }
    Вызов:
    Код (Text):
    1.      Status = TeLinkQueryBinding((PUCHAR)pIrp->AssociatedIrp.SystemBuffer,
    2.                             pIrpStk->Parameters.DeviceIoControl.InputBufferLength,
    3.                             pIrpStk->Parameters.DeviceIoControl.OutputBufferLength,
    4.                             &Bts);
    Т.е. pBuffer == (PUCHAR)pIrp->AssociatedIrp.SystemBuffer

    2.
    Я в юзер моде вызываю
    Код (Text):
    1.    if(DeviceIoControl(hndl, IOCTL_TELINK_QUERY_BINDING, pQueryBinding, sizeof(TELINK_QUERY_BINDING),Buf, BufLength, &BytesWritten, NULL))
    2.    {
    3.    //...
    4.    }
    Т.е. Buf
    Ну я имел ввиду, что на кусок памяти(выделенный I/O Manager), объёмом указанным в параметре DeviceIoControl

    зы:
    Получили BugCheck 19, {20, 8211ae48, 8211ae68, 1a040001}
    8211ae68 - 8211ae48 = 00000020 это размер памяти pIrp->AssociatedIrp.SystemBuffer?
     
  7. ntkernelspawn

    ntkernelspawn New Member

    Публикаций:
    0
    Регистрация:
    17 дек 2010
    Сообщения:
    61
    Почему pIrp->AssociatedIrp.SystemBuffer должно указывать на некий выделенный кусок памяти? Его выделяет и заполняет I/O Manager же.
    http://msdn.microsoft.com/en-us/library/ff554436%28v=VS.85%29.aspx
     
  8. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Надо полагать, что вызов должен быть таким:
    Код (Text):
    1.    NdisZeroMemory((PUCHAR)pBuffer + sizeof(TELINK_QUERY_BINDING),
    2.            pQueryBinding->DeviceNameLength + pQueryBinding->DeviceDescrLength - sizeof(TELINK_QUERY_BINDING));
     
  9. ntkernelspawn

    ntkernelspawn New Member

    Публикаций:
    0
    Регистрация:
    17 дек 2010
    Сообщения:
    61
    pBuffer валидный или нет?
     
  10. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    ntkernelspawn
    Ну да, мне просто показалось, что tapa пытается сам выделить/освободить SystemBuffer.
     
  11. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    DeviceIoControl(IOCTL_TELINK_QUERY_BINDING) -> I/O Manager -> IRP
    -----
    NTSTATUS TeLinkIoControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) - > (pIrp->AssociatedIrp.SystemBuffer)

    Если он будет таким, то не влезет имя адаптера.


    зы вот
    pIrpStk->Parameters.DeviceIoControl.InputBufferLength //20 байт sizeof(TELINK_QUERY_BINDING)
    pIrpStk->Parameters.DeviceIoControl.OutputBufferLength //4096 (1024*4)
     
  12. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    Я правильно понимаю, что в юзер моде передал указатель на кусок памяти. I/O Manager сделал "нешто" и в обработчике TeLinkIoControl, вынимая pIrp->AssociatedIrp.SystemBuffer,
    я могу работать как с буфером из юзер мода? И по завершению I/O Manager скопирует данные в буфер юзер мода?
     
  13. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Да, точно, сейчас внимательнее посмотрел. А Remaining объявлена как знаковая переменная? Если беззнаковая и 'Remaining = OutputLength - sizeof(TELINK_QUERY_BINDING);' дает отрицательное значение, то сравнение 'if (Remaining < pQueryBinding->DeviceNameLength + pQueryBinding->DeviceDescrLength)' даст неверный результат.
     
  14. ntkernelspawn

    ntkernelspawn New Member

    Публикаций:
    0
    Регистрация:
    17 дек 2010
    Сообщения:
    61
    tapa
    Да, но при работе с драйвером есть несколько методов в частности DO_BUFFERED_IO, DO_DIRECT_IO, neither как выбрали вы?
     
  15. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    pQueryBinding->DeviceNameLength 0х5e
    pQueryBinding->DeviceDescrLength 0x96

    OutputLength 0x1000
    sizeof(TELINK_QUERY_BINDING) 0x14
    ==============================
    Remaining =0x1000 - 0x14 = 0xfec

    Это частный случай, но всё равно ошибка


    NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
    {
    PDEVICE_OBJECT nt_dev_object;
    //....
    nt_dev_object->Flags |= DO_DIRECT_IO;
    }

    В обработчике "IRP_MJ_DEVICE_CONTROL"

    Код (Text):
    1.         if (pIrp->Flags&DO_BUFFERED_IO)
    2.             DbgPrint("DO_BUFFERED_IO");
    3.         else if (pIrp->Flags&DO_DIRECT_IO)
    4.             DbgPrint("DO_DIRECT_IO");
    DO_DIRECT_IO.

    Понимаю, что по логике должно быть MdlAddress.
    Но в примере DDK
    Код (Text):
    1. NTSTATUS
    2. DriverEntry(
    3.     IN PDRIVER_OBJECT   pDriverObject,
    4.     IN PUNICODE_STRING  pRegistryPath
    5.     ){
    6. //..
    7.         deviceObject->Flags |= DO_DIRECT_IO;
    8. }
    Код (Text):
    1.     case IOCTL_NDISPROT_QUERY_BINDING:
    2.            
    3.             NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED);
    4.  
    5.             Status = ndisprotQueryBinding(
    6.                             pIrp->AssociatedIrp.SystemBuffer,
    7.                             pIrpSp->Parameters.DeviceIoControl.InputBufferLength,
    8.                             pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
    9.                             &BytesReturned
    10.                             );
    11.  
    12.             NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
    13.  
    14.             DEBUGP(DL_LOUD, ("IoControl: QueryBinding returning %x\n", NtStatus));
    Так что оставил как есть, может я какой-то момент пропустил и поэтому такая фигня?
     
  16. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    tapa
    Да, но для DEVICE_IO_CONTROL (и для INTERNAL_DEVICE_CONTROL) метод передачи задается в самой константе IOCTL_XXX.
     
  17. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    Охх, ну я олень..
    Mika0x65,ntkernelspawn Спасибо :)
     
  18. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    tapa
    А в чем дело-то было? :)
     
  19. tapa

    tapa New Member

    Публикаций:
    0
    Регистрация:
    30 дек 2010
    Сообщения:
    13
    #define IOCTL_TELINK_QUERY_BINDING 5

    И забыл про него нафик...:)