Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Windows WFP Driver: Getting BSOD when processing packets in ClassifyFn callback

ViottoViotto Member Posts: 6

Hi,

I am trying to code a simple firewall application which can allow or block network connection attempts made from userlevel processes.
To do so, following the WFPStarterKit tutorial, I created a WFP Driver which is set to intercept data at FWPM_LAYER_OUTBOUND_TRANSPORT_V4 layer.
The ClassifyFn callback function is responsible for intercepting the connection attempt, and either allow or deny it.
Once the ClassifyFn callback gets hit, the ProcessID of the packet is sent, along with a few other info, to a userlevel process through the FltSendMessage function.
The userlevel process receives the message, checks the ProcessID, and replies a boolean allow/deny command to the driver.

While this approach works when blocking a first packet,
in some cases (expecially when allowing multiple packets) the code generates a BSOD with the INVALID_PROCESS_ATTACH_ATTEMPT error code.
The error is triggered at the call to FltSendMessage.

While I am still unable to pinpoint the exact problem, it seems that making the callout thread wait (through FltSendMessage) for a reply from userlevel can generate this BSOD error on some conditions.

I would be very grateful if you can point me to the right direction.

Here is the function where I register the callout:

NTSTATUS register_example_callout(DEVICE_OBJECT * wdm_device)
{
    NTSTATUS status = STATUS_SUCCESS;
    FWPS_CALLOUT s_callout = { 0 };
    FWPM_CALLOUT m_callout = { 0 };
    FWPM_DISPLAY_DATA display_data = { 0 };

    if (filter_engine_handle == NULL)
        return STATUS_INVALID_HANDLE;

    display_data.name = EXAMPLE_CALLOUT_NAME;
    display_data.description = EXAMPLE_CALLOUT_DESCRIPTION;

    // Register a new Callout with the Filter Engine using the provided callout functions
    s_callout.calloutKey = EXAMPLE_CALLOUT_GUID;
    s_callout.classifyFn = example_classify;
    s_callout.notifyFn = example_notify;
    s_callout.flowDeleteFn = example_flow_delete;
    status = FwpsCalloutRegister((void *)wdm_device, &s_callout, &example_callout_id);
    if (!NT_SUCCESS(status)) {
        DbgPrint("Failed to register callout functions for example callout, status 0x%08x", status);
        goto Exit;
    }

    // Setup a FWPM_CALLOUT structure to store/track the state associated with the FWPS_CALLOUT
    m_callout.calloutKey = EXAMPLE_CALLOUT_GUID;
    m_callout.displayData = display_data;
    m_callout.applicableLayer = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    m_callout.flags = 0;
    status = FwpmCalloutAdd(filter_engine_handle, &m_callout, NULL, NULL);
    if (!NT_SUCCESS(status)) {
        DbgPrint("Failed to register example callout, status 0x%08x", status);
    }
    else {
        DbgPrint("Example Callout Registered");
    }

Exit:
    return status;
}

Here is the callout function:

 /*************************
ClassifyFn Function
**************************/
void example_classify(
    const FWPS_INCOMING_VALUES * inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES * inMetaValues,
    void * layerData,
    const void * classifyContext,
    const FWPS_FILTER * filter,
    UINT64 flowContext,
    FWPS_CLASSIFY_OUT * classifyOut)
{
    UNREFERENCED_PARAMETER(layerData);
    UNREFERENCED_PARAMETER(classifyContext);
    UNREFERENCED_PARAMETER(flowContext);
    UNREFERENCED_PARAMETER(filter);
    UNREFERENCED_PARAMETER(inMetaValues);

    NETWORK_ACCESS_QUERY AccessQuery;
    BOOLEAN SafeToOpen = TRUE;
    classifyOut->actionType = FWP_ACTION_PERMIT;

    AccessQuery.remote_address = inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_REMOTE_ADDRESS].value.uint32;
    AccessQuery.remote_port = inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_REMOTE_PORT].value.uint16;

    // Get Process ID
    AccessQuery.ProcessId = (UINT64)PsGetCurrentProcessId();

    if (!AccessQuery.ProcessId) 
    {
        return;
    }

    // Here we connect to our userlevel application using FltSendMessage.
    // Some checks are done and the SafeToOpen variable is populated with a BOOLEAN which indicates if to allow or block the packet.
    // However, sometimes, a BSOD is generated with an INVALID_PROCESS_ATTACH_ATTEMPT error on the FltSendMessage call
    QueryUserLevel(QUERY_NETWORK, &AccessQuery, sizeof(NETWORK_ACCESS_QUERY), &SafeToOpen, NULL, 0);

    if (!SafeToOpen) {
        classifyOut->actionType = FWP_ACTION_BLOCK;
    }

    return;
}

Comments

  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,343

    This callback can be called at IRQL DISPATCH_LEVEL, which would make it illegal to use a communication port. Enable Driver Verifier and always post the !analyze -v output if you have a crash.

    -scott
    OSR

  • ViottoViotto Member Posts: 6

    @Scott_Noone_(OSR) said:
    This callback can be called at IRQL DISPATCH_LEVEL, which would make it illegal to use a communication port. Enable Driver Verifier and always post the !analyze -v output if you have a crash.

    Hello Scott,
    thank you for your reply.
    Since I cannot use a communication port through FltSendMessage inside this function,
    how would you suggest I should communicate with userlevel?
    FltSendMessage was the easiest option since it waits for response by the userlevel process.

    Here is the !analyze -v log:


    • *
    • Bugcheck Analysis *
    • *

    INVALID_PROCESS_ATTACH_ATTEMPT (5)
    Arguments:
    Arg1: ffffa98d439b2080
    Arg2: ffffa98d402581c0
    Arg3: 0000000000000001
    Arg4: 0000000000000001

    Debugging Details:

    DUMP_CLASS: 1

    DUMP_QUALIFIER: 0

    BUILD_VERSION_STRING: 15046.0.amd64fre.rs2_release.170224-1700

    DUMP_TYPE: 0

    BUGCHECK_P1: ffffa98d439b2080

    BUGCHECK_P2: ffffa98d402581c0

    BUGCHECK_P3: 1

    BUGCHECK_P4: 1

    CPU_COUNT: 4

    CPU_MHZ: fa8

    CPU_VENDOR: GenuineIntel

    CPU_FAMILY: 6

    CPU_MODEL: 5e

    CPU_STEPPING: 3

    CPU_MICROCODE: 6,5e,3,0 (F,M,S,R) SIG: BA'00000000 (cache) BA'00000000 (init)

    DEFAULT_BUCKET_ID: WIN8_DRIVER_FAULT

    BUGCHECK_STR: 0x5

    PROCESS_NAME: System

    CURRENT_IRQL: 2

    ANALYSIS_SESSION_HOST: DESKTOP-NQ55126

    ANALYSIS_SESSION_TIME: 02-29-2020 17:41:58.0187

    ANALYSIS_VERSION: 10.0.16299.15 amd64fre

    LAST_CONTROL_TRANSFER: from fffff802489f6812 to fffff80248972cc0

  • ViottoViotto Member Posts: 6
    edited March 2

    I already switched to FWPM_LAYER_ALE_AUTH_CONNECT_V4 since a while now:

        m_callout.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
        //m_callout.applicableLayer = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    

    Which is definitely better for my purpose.
    Although the issue occurrs more rarely now, sometimes there is still the same BSOD error INVALID_PROCESS_ATTACH_ATTEMPT when calling FltSendMessage. :(
    On StackOverflow I was suggested to use the inverted call model instead of FltSendMessage.
    This would require some protocol rewriting, but I can go for it, or do you have any other better approach in mind? =)

    Thank you

  • Sergey_PisarevSergey_Pisarev Member - All Emails Posts: 259
    > @Viotto said:
    > (Quote)
    > I already switched to FWPM_LAYER_ALE_AUTH_CONNECT_V4 since a while now:
    >
    > m_callout.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4; //m_callout.applicableLayer = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    >
    > Which is definitely better for my purpose.
    > Although the issue occurrs more rarely now, sometimes there is still the same BSOD error INVALID_PROCESS_ATTACH_ATTEMPT when calling FltSendMessage. :(
    > On StackOverflow I was suggested to use the inverted call model instead of FltSendMessage.
    > This would require some protocol rewriting, but I can go for it, or do you have any other better approach in mind? =)
    >
    > Thank you

    You expecting current implementation somehow magically start working ?
  • ViottoViotto Member Posts: 6

    @Sergey_Pisarev said:

    @Viotto said:
    (Quote)
    I already switched to FWPM_LAYER_ALE_AUTH_CONNECT_V4 since a while now:

    m_callout.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4;    //m_callout.applicableLayer = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    

    Which is definitely better for my purpose.
    Although the issue occurrs more rarely now, sometimes there is still the same BSOD error INVALID_PROCESS_ATTACH_ATTEMPT when calling FltSendMessage. :(
    On StackOverflow I was suggested to use the inverted call model instead of FltSendMessage.
    This would require some protocol rewriting, but I can go for it, or do you have any other better approach in mind? =)

    Thank you

    You expecting current implementation somehow magically start working ?

    If you did read the thread, you would have understood that the implementation usually works, except on some random cases which throw the INVALID_PROCESS_ATTACH_ATTEMPT error.
    I opened the thread to get a direction regarding the reason and solution for this error.
    Do you have something actually useful to add? =)

  • Sergey_PisarevSergey_Pisarev Member - All Emails Posts: 259
    edited March 2

    @Viotto said:

    @Sergey_Pisarev said:

    @Viotto said:
    (Quote)
    I already switched to FWPM_LAYER_ALE_AUTH_CONNECT_V4 since a while now:

    m_callout.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4;    //m_callout.applicableLayer = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    

    Which is definitely better for my purpose.
    Although the issue occurrs more rarely now, sometimes there is still the same BSOD error INVALID_PROCESS_ATTACH_ATTEMPT when calling FltSendMessage. :(
    On StackOverflow I was suggested to use the inverted call model instead of FltSendMessage.
    This would require some protocol rewriting, but I can go for it, or do you have any other better approach in mind? =)

    Thank you

    You expecting current implementation somehow magically start working ?

    If you did read the thread, you would have understood that the implementation usually works, except on some random cases which throw the INVALID_PROCESS_ATTACH_ATTEMPT error.
    I opened the thread to get a direction regarding the reason and solution for this error.
    Do you have something actually useful to add? =)

    No. Bsod = doesn’t work. You solution doesn’t work. You should understand that you can’t use fltsendmessage at dispatch. This is said in function documentation. You implementation is flawed on conceptual level, it can’t be fixed. You need to change your model.
    And remember: work most of the time = doesn’t work

  • ViottoViotto Member Posts: 6

    I believe at this point that the best thing to do is remove FltSendMessage and use inverted call model for communication instead.
    Each time I get an event in the ClassifyFn callback, I will communicate this to userlevel by completing one of the pending IOCTL...
    Unless somebody has got some direction for me, that's the way I'll go

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Internals & Software Drivers 25 Jan 2021 LIVE ONLINE
Developing Minifilters Early 2021 LIVE ONLINE