cwindowskerneldriverminifilter

PsSuspendProcess blocking / waiting / stuck - Windows Kernel Programming


i come here with a very low level question in the Windows Kernel. I am in a callback function on a minifilter driver. The goal of the driver is to pause any process witch try to open a file I marked as protected. I'm using PsSuspendProcess that I got from this function :

(pPsSuspendProcess)ReturnSystemRoutineAddress(L"PsSuspendProcess");

But when I call it with the above code, my program get stuck at the Suspend call. On the task manager, the process is well suspended, but the driver never ends this function.

It only continues when I unpause manually the process or kill it from taskmgr.

I'm totally blocked, as PsSuspendProcess is an undocumented function...

Here my code:

FLT_PREOP_CALLBACK_STATUS
DfPreCreateCallback(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Outptr_result_maybenull_ PVOID* CompletionContext
    )
{
    PAGED_CODE();
    NTSTATUS status;
    ULONG options = Data->Iopb->Parameters.Create.Options;
    UCHAR disposition = (options >> 24) & 0xff;
    ULONG createOptions = (options << 8) >> 8;

    if ((createOptions & FILE_NON_DIRECTORY_FILE) && (disposition == FILE_OPEN || disposition == FILE_OPEN_IF
        || disposition == FILE_OVERWRITE || disposition == FILE_OVERWRITE_IF))
    {
        HANDLE processId = (HANDLE)FltGetRequestorProcessId(Data);
        PEPROCESS p = FltGetRequestorProcess(Data);
        if (p == NULL)
            goto callback_end;
        LPSTR processName = PsGetProcessImageFileName(p);
        if (processName == NULL)
            goto callback_end;
        for (int i = 0; i < (sizeof(ExcludedProcess) / sizeof(LPCWSTR)); i++)
        {
            if (strcmp(processName, ExcludedProcess[i]) == 0)
                goto callback_end;
        }

        PFLT_FILE_NAME_INFORMATION FileInfo;
        status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &FileInfo);
        if (NT_ERROR(status))
            goto callback_end;
        if (!IsProtected(&FileInfo->Name))
            goto callback_end;
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DBG PROTECTED %wZ", FileInfo->Name);

        PsSuspendProcess(p);

        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DBG SUSPENDED")
    }
    callback_end:
    CompletionContext = NULL;
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

Solution

  • you call by fact

    PsSuspendProcess(FltGetRequestorProcess(Data));
    

    but for file operations Pre Callbacks almost always called in context of thread that requested a given I/O operation. so almost always

    FltGetRequestorProcess(Data) == IoGetCurrentProcess();
    

    so you suspend current process and current thread. as result next line

    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DBG SUSPENDED");
    

    of course will be not executed until thread will be not resumed