none
Debugging issues in NDIS driver during unload RRS feed

  • Question

  • Hi,

    We've recently encountered an issue during NDIS miniport driver unload. It seems that there is a kind of memory corruption and BSOD occurs during an attempt to free memory that should be allocated. I would appreciate some insights on these items:

    a) What are the recommended methods to debug such issue? Since the problem occurs during unload, all the internal driver structures are already not in memory so I can't check their internal state. Also, obviously there are no logs available.

    b) I'm trying to get to the root cause of the problem and the only valid possibility seems to be a failure during DriverEntry execution that occurred before the relevant memory was properly initialized. I didn't see in the documentation what will be the NDIS behavior in such case. Will it call the unload handler immediately upon DriverEntry completion? I suppose it's not possible if the failure occurred before NdisMRegisterMiniportDriver was called. And what if the failure is due to NdisMRegisterMiniportDriver failure, will the unload handler be called in this case? Anyway, is it a non-theoretical possibility for NdisMRegisterMiniportDriver to fail during stress testing?

    Thanks

    Sunday, March 1, 2015 9:03 AM

Answers

  • Verifier is usually the best way to tackle memory corruption. "!verifier 80 <address>" will tell you who allocated the memory & freed it last.  You might need to do ".reload /unl" to get the callstack to resolve, if your driver is unloaded.

    If DriverEntry fails, then nobody will call into your DriverUnload handler.  The OS will only "enable" your DriverUnload handler if DriverEntry itself returns STATUS_SUCCESS.  As a result, it's common to manually call your DriverUnload handler at the end of DriverEntry:

    NDIS_HANDLE g_NdisDriverHandle = NULL;
    
    NTSTATUS DriverEntry(...)
    {
        . . .
    
        NdisStatus = NdisMRegisterMiniportDriver(..., &g_NdisDriverHandle);
        if (NdisStatus != NDIS_STATUS_SUCCESS)
        {
            NtStatus = STATUS_UNSUCCESSFUL;
            goto Cleanup;
        }
    
        . . .
    
    Cleanup:
    
        if (!NT_SUCCESS(NtStatus))
            MyDriverUnload(DriverObject);
    
        return NtStatus;
    }
    
    VOID MyDriverUnload(...)
    {
        if (g_NdisDriverHandle != NULL)
            NdisMDeregisterMiniportDriver(g_NdisDriverHandle);
    }

    • Marked as answer by -IgorC- Wednesday, March 4, 2015 9:46 PM
    Tuesday, March 3, 2015 10:03 PM

All replies

  • Verifier is usually the best way to tackle memory corruption. "!verifier 80 <address>" will tell you who allocated the memory & freed it last.  You might need to do ".reload /unl" to get the callstack to resolve, if your driver is unloaded.

    If DriverEntry fails, then nobody will call into your DriverUnload handler.  The OS will only "enable" your DriverUnload handler if DriverEntry itself returns STATUS_SUCCESS.  As a result, it's common to manually call your DriverUnload handler at the end of DriverEntry:

    NDIS_HANDLE g_NdisDriverHandle = NULL;
    
    NTSTATUS DriverEntry(...)
    {
        . . .
    
        NdisStatus = NdisMRegisterMiniportDriver(..., &g_NdisDriverHandle);
        if (NdisStatus != NDIS_STATUS_SUCCESS)
        {
            NtStatus = STATUS_UNSUCCESSFUL;
            goto Cleanup;
        }
    
        . . .
    
    Cleanup:
    
        if (!NT_SUCCESS(NtStatus))
            MyDriverUnload(DriverObject);
    
        return NtStatus;
    }
    
    VOID MyDriverUnload(...)
    {
        if (g_NdisDriverHandle != NULL)
            NdisMDeregisterMiniportDriver(g_NdisDriverHandle);
    }

    • Marked as answer by -IgorC- Wednesday, March 4, 2015 9:46 PM
    Tuesday, March 3, 2015 10:03 PM
  • Thanks everyone - cool tips.
    Wednesday, March 4, 2015 9:47 PM