cdriverwdkwfpirql

Seemingly impossible bugcheck


I am writing my first kernel driver, and it's crashing on the following line in DriverEntry:

status = FwpsCalloutRegister(wdfDevice, &sCallout, &Globals.FlowCalloutId);

!analyze v in WinDbg outputs the following:

*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00001df79f0fe5b8, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000001, bitfield :
    bit 0 : value 0 = read operation, 1 = write operation
    bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: fffff803392e1640, address which referenced memory

Debugging Details:
------------------


DUMP_CLASS: 1

DUMP_QUALIFIER: 0

BUILD_VERSION_STRING:  16299.15.amd64fre.rs3_release.170928-1534

DUMP_TYPE:  0

BUGCHECK_P1: 1df79f0fe5b8

BUGCHECK_P2: 2

BUGCHECK_P3: 1

BUGCHECK_P4: fffff803392e1640

WRITE_ADDRESS:  00001df79f0fe5b8 

CURRENT_IRQL:  2

FAULTING_IP: 
nt!ObfReferenceObject+20
fffff803`392e1640 f0480fc11f      lock xadd qword ptr [rdi],rbx

CPU_COUNT: 4

CPU_MHZ: 8f7

CPU_VENDOR:  GenuineIntel

CPU_FAMILY: 6

CPU_MODEL: 2a

CPU_STEPPING: 7

CPU_MICROCODE: 6,2a,7,0 (F,M,S,R)  SIG: 29'00000000 (cache) 29'00000000 (init)

DEFAULT_BUCKET_ID:  WIN8_DRIVER_FAULT

BUGCHECK_STR:  AV

PROCESS_NAME:  System

ANALYSIS_SESSION_HOST:  ELI-DESKTOP

ANALYSIS_SESSION_TIME:  04-28-2018 22:38:52.0588

ANALYSIS_VERSION: 10.0.16299.15 amd64fre

TRAP_FRAME:  ffff8905265e2200 -- (.trap 0xffff8905265e2200)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000001 rbx=0000000000000000 rcx=00001df79f0fe5e8
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff803392e1640 rsp=ffff8905265e2390 rbp=0000000000000126
 r8=0000000000000000  r9=0000000000000006 r10=0000000000000000
r11=fffff800601e7c17 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
nt!ObfReferenceObject+0x20:
fffff803`392e1640 f0480fc11f      lock xadd qword ptr [rdi],rbx ds:00000000`00000000=????????????????
Resetting default scope

LAST_CONTROL_TRANSFER:  from fffff80339499a02 to fffff80339414bf0

STACK_TEXT:  
ffff8905`265e18f8 fffff803`39499a02 : 00001df7`9f0fe5b8 ffffe208`5d475700 ffff8905`265e1a60 fffff803`393d6540 : nt!DbgBreakPointWithStatus
ffff8905`265e1900 fffff803`39499287 : 00000000`00000003 ffff8905`265e1a60 fffff803`394212c0 00000000`0000000a : nt!KiBugCheckDebugBreak+0x12
ffff8905`265e1960 fffff803`3940ca37 : 00000000`00000000 fffff803`39383e01 00000000`00000001 ffff8a81`d7f52a20 : nt!KeBugCheck2+0x937
ffff8905`265e2080 fffff803`3941eae9 : 00000000`0000000a 00001df7`9f0fe5b8 00000000`00000002 00000000`00000001 : nt!KeBugCheckEx+0x107
ffff8905`265e20c0 fffff803`3941b1fe : ffff8905`265e2310 fffff803`3932e308 fffff803`38db3180 fffff800`00000000 : nt!KiBugCheckDispatch+0x69
ffff8905`265e2200 fffff803`392e1640 : ffffe208`5dfebba0 fffff800`5fa7f5ab ffffc985`1b0b4090 ffff8905`265e25a8 : nt!KiPageFault+0x47e
ffff8905`265e2390 fffff800`601e5273 : ffffe208`5e805be0 00000000`00000000 00000000`00000000 fffff803`392e1776 : nt!ObfReferenceObject+0x20
ffff8905`265e23d0 fffff800`60103e4f : ffff8905`265e25a8 00000000`00000000 ffffc985`13eca4c0 00001df7`9f0fe5e8 : NETIO!KfdAddCalloutEntry+0x1d3
ffff8905`265e2420 fffff800`6010321a : 00000000`00000000 ffffc985`13eca4c0 fffff800`63b44380 00001df7`9f0fe5e8 : fwpkclnt!FwppCalloutRegister+0x9f
ffff8905`265e2490 fffff800`63b4145d : 00000000`00000000 00000000`00000000 fffff800`63b43120 badbadfa`badbadfa : fwpkclnt!FwpsCalloutRegister3+0x6a
ffff8905`265e24d0 fffff800`63b4290d : ffffe208`60827940 ffffe208`5f3b9000 ffffc985`1cb31c90 ffffe208`6083fe10 : KmdfStart!DriverEntry+0x45d [c:\develop\tanwash\kmdfstart\driver.c @ 272]
ffff8905`265e2940 fffff803`39741ad6 : 00000000`00000000 ffff8905`265e2a70 ffffe208`60827940 ffffffff`80002d58 : KmdfStart!FxDriverEntryWorker+0xb9 [d:\th\minkernel\wdf\framework\kmdf\src\dynamic\stub\stub.cpp @ 325]
ffff8905`265e2970 fffff803`3980b7d7 : 00000000`00000000 00000000`00000000 00000000`00000000 fffff803`395f5b40 : nt!IopLoadDriver+0x4da
ffff8905`265e2b40 fffff803`392d24d5 : ffffe208`00000000 ffffffff`80002d58 ffffe208`5d4ce300 ffffe208`5d475700 : nt!IopLoadUnloadDriver+0x57
ffff8905`265e2b80 fffff803`393adc07 : ffffe208`5d475700 00000000`00000080 ffffe208`5d450440 ffffe208`5d475700 : nt!ExpWorkerThread+0xf5
ffff8905`265e2c10 fffff803`39414366 : ffff8a81`d7ec0180 ffffe208`5d475700 fffff803`393adbc0 00000000`00000000 : nt!PspSystemThreadStartup+0x47
ffff8905`265e2c60 00000000`00000000 : ffff8905`265e3000 ffff8905`265dd000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x16


THREAD_SHA1_HASH_MOD_FUNC:  3968ac24ad304ae3e12d211656861bc3d31ba01b

THREAD_SHA1_HASH_MOD_FUNC_OFFSET:  42d7be29acc2a96618b5dfd9cf0528fdc2d10bc5

THREAD_SHA1_HASH_MOD:  d06099ec8ea3db5426a6cfa7d3673b217e8490ba

FOLLOWUP_IP: 
NETIO!KfdAddCalloutEntry+1d3
fffff800`601e5273 48897340        mov     qword ptr [rbx+40h],rsi

FAULT_INSTR_CODE:  40738948

SYMBOL_STACK_INDEX:  7

SYMBOL_NAME:  NETIO!KfdAddCalloutEntry+1d3

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: NETIO

IMAGE_NAME:  NETIO.SYS

DEBUG_FLR_IMAGE_TIMESTAMP:  5b0597f3

STACK_COMMAND:  .thread ; .cxr ; kb

BUCKET_ID_FUNC_OFFSET:  1d3

FAILURE_BUCKET_ID:  AV_NETIO!KfdAddCalloutEntry

BUCKET_ID:  AV_NETIO!KfdAddCalloutEntry

PRIMARY_PROBLEM_CLASS:  AV_NETIO!KfdAddCalloutEntry

TARGET_TIME:  2018-04-28T19:25:44.000Z

OSBUILD:  16299

OSSERVICEPACK:  0

SERVICEPACK_NUMBER: 0

OS_REVISION: 0

SUITE_MASK:  784

PRODUCT_TYPE:  1

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

OSEDITION:  Windows 10 WinNt TerminalServer SingleUserTS Personal

OS_LOCALE:  

USER_LCID:  0

OSBUILD_TIMESTAMP:  2018-03-29 20:22:49

BUILDDATESTAMP_STR:  170928-1534

BUILDLAB_STR:  rs3_release

BUILDOSVER_STR:  10.0.16299.15.amd64fre.rs3_release.170928-1534

ANALYSIS_SESSION_ELAPSED_TIME:  d13

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:av_netio!kfdaddcalloutentry

FAILURE_ID_HASH:  {70a7358f-b067-d8c1-c0fa-9641a6376c65}

Followup:     MachineOwner
---------

I am trying to understand the issue, and there are 2 things I don't understand - firstly why there is any pageable memory involved, since I'm just passing in to the function global variables and local variables, both of which are non-paged. (See here and here.)

Secondly why IRQL is above 0, since I'm in DriverEntry. (See here the DriverEntry runs at PASSIVE_LEVEL.

My code is as follows. It crashes on the last line posted - anything else is not relevant as it never gets there.

NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
)
{
    WDF_DRIVER_CONFIG config;
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;
    PWDFDEVICE_INIT pInit = NULL;
    WDFDRIVER wdfDriver;
    WDFDEVICE wdfDevice;
    //
    // Initialize WPP Tracing
    //
    WPP_INIT_TRACING(DriverObject, RegistryPath);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //driver
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = KmdfStartEvtDriverContextCleanup;

    WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);

    status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &wdfDriver);

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
        //EvtCleanupCallback won't be called here, since the driver wasn't created
        WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
        goto DriverEntryErr;
    }

    //setup device
    pInit = WdfControlDeviceInitAllocate(wdfDriver, &SDDL_DEVOBJ_KERNEL_ONLY);
    if (pInit == NULL) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfControlDeviceInitAllocate failed");
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto DriverEntryErr;
    }

    WdfDeviceInitSetCharacteristics(pInit, FILE_AUTOGENERATED_DEVICE_NAME, TRUE);
    WdfDeviceInitSetDeviceClass(pInit, &WFP_DRIVER_CLASS_GUID);
    WdfDeviceInitSetCharacteristics(pInit, FILE_DEVICE_SECURE_OPEN, TRUE);

    status = WdfDeviceCreate(&pInit, WDF_NO_OBJECT_ATTRIBUTES, &wdfDevice);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
        WdfDeviceInitFree(pInit);
        goto DriverEntryErr;
    }

    WdfControlFinishInitializing(wdfDevice);

    //engine
    FWPM_SESSION session = { 0 };
    session.flags = FWPM_SESSION_FLAG_DYNAMIC;
    status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &Globals.EngineHandle);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "FwpmEngineOpen failed %!STATUS!", status);
        goto DriverEntryErr;
    }

    //start transaction
    status = FwpmTransactionBegin(Globals.EngineHandle, 0);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "FwpmTransactionBegin failed %!STATUS!", status);
        goto DriverEntryErr;
    }

    //sublayer
    FWPM_SUBLAYER0 kstSubLayer = { 0 };
    kstSubLayer.subLayerKey = KST_SUBLAYER;
    kstSubLayer.displayData.name = L"KmdfStart Sub-Layer";
    kstSubLayer.displayData.description = L"KmdfStart Sub-Layer for callouts";
    kstSubLayer.weight = 0x40;
    status = FwpmSubLayerAdd(Globals.EngineHandle, &kstSubLayer, NULL);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "FwpmSubLayerAdd failed %!STATUS!", status);
        goto DriverEntryErr;
    }

    //flow callout register
    FWPS_CALLOUT sCallout = { 0 };
    sCallout.calloutKey = KST_FLOW_ESTABLISHED_CALLOUT_V4;
    sCallout.classifyFn = KmdfStartFlowEstablishedClassify;
    sCallout.notifyFn = KmdfStartNotifyFunction;
    status = FwpsCalloutRegister(wdfDevice, &sCallout, &Globals.FlowCalloutId);

Solution

  • The first parameter of FwpsCalloutRegister is of type *deviceObject, not wdfDevice.

    You can get an instance of *deviceObject by calling WdfDeviceWdmGetDeviceObject(wdfDevice);.