Files
8damon-Blackbird-Platform/Kernel/core/control/control_common.c
T
dutchpsycho bc0fb44a09 kernel/control: retire MarkInterfaceReady handler and instrument IOCTL hot paths
Remove BLACKBIRDHandleMarkInterfaceReadyIoctl and its auth predicate. The
MarkControllerReady path is simplified to call BLACKBIRDProcessMonitorRegisterControllerPid
directly, dropping the now-redundant process-monitor membership check.

Add Tempus timing around BLACKBIRDPublishRecordToSubscribers, BLACKBIRDHandleGetEventIoctl,
and BLACKBIRDHandleGetStatsIoctl. The stats response now exposes TempusEnabled,
TempusSubsystemCount, TempusQpcFrequency, and the per-subsystem bucket array so the
analysis interface can surface kernel-side timing data.
2026-04-14 09:00:00 +00:00

984 lines
29 KiB
C

#include "control_private.h"
BOOLEAN BLACKBIRDModeAllowed(_In_ WDFREQUEST Request)
{
return (WdfRequestGetRequestorMode(Request) == UserMode);
}
ULONG BLACKBIRDGetRequestorPid(VOID)
{
return (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
}
PCSTR BLACKBIRDIoctlName(_In_ ULONG Ioctl)
{
switch (Ioctl)
{
case IOCTL_BLACKBIRD_SUBSCRIBE:
return "SUBSCRIBE";
case IOCTL_BLACKBIRD_UNSUBSCRIBE:
return "UNSUBSCRIBE";
case IOCTL_BLACKBIRD_GET_EVENT:
return "GET_EVENT";
case IOCTL_BLACKBIRD_GET_STATS:
return "GET_STATS";
case IOCTL_BLACKBIRD_SET_PIDS:
return "SET_PIDS";
case IOCTL_BLACKBIRD_QUERY_PROCESS_IMAGE:
return "QUERY_PROCESS_IMAGE";
case IOCTL_BLACKBIRD_SET_SHUTDOWN_MODE:
return "SET_SHUTDOWN_MODE";
case IOCTL_BLACKBIRD_GET_HEALTH:
return "GET_HEALTH";
case IOCTL_BLACKBIRD_ARM_PENDING_LAUNCH:
return "ARM_PENDING_LAUNCH";
case IOCTL_BLACKBIRD_CONTROL_EXECUTION:
return "CONTROL_EXECUTION";
case IOCTL_BLACKBIRD_SET_RUNTIME_CONFIG:
return "SET_RUNTIME_CONFIG";
case IOCTL_BLACKBIRD_GET_RUNTIME_CONFIG:
return "GET_RUNTIME_CONFIG";
default:
return "UNKNOWN_IOCTL";
}
}
BOOLEAN BLACKBIRDControlIsShutdown(VOID)
{
return (InterlockedCompareExchange(&g_ControlShutdown, 0, 0) != 0);
}
static BOOLEAN BLACKBIRDTryAcquireGlobalQueueSlot(VOID)
{
LONG current;
for (;;)
{
current = InterlockedCompareExchange(&g_ControlTotalQueuedEvents, 0, 0);
if (current >= BLACKBIRD_MAX_TOTAL_QUEUED_EVENTS)
{
return FALSE;
}
if (InterlockedCompareExchange(&g_ControlTotalQueuedEvents, current + 1, current) == current)
{
return TRUE;
}
}
}
VOID BLACKBIRDReleaseGlobalQueueSlot(VOID)
{
LONG remaining;
remaining = InterlockedDecrement(&g_ControlTotalQueuedEvents);
NT_ASSERT(remaining >= 0);
if (remaining < 0)
{
InterlockedExchange(&g_ControlTotalQueuedEvents, 0);
}
}
BOOLEAN BLACKBIRDClientConsumeQueryBudgetLocked(_Inout_ PBLACKBIRD_CLIENT Client)
{
ULONGLONG now;
now = KeQueryInterruptTime();
if (Client->QueryWindowStart100ns == 0 || now < Client->QueryWindowStart100ns ||
(now - Client->QueryWindowStart100ns) >= BLACKBIRD_QUERY_IMAGE_WINDOW_100NS)
{
Client->QueryWindowStart100ns = now;
Client->QueryWindowCount = 1;
return TRUE;
}
if (Client->QueryWindowCount >= BLACKBIRD_QUERY_IMAGE_MAX_PER_WINDOW)
{
return FALSE;
}
Client->QueryWindowCount += 1;
return TRUE;
}
BOOLEAN BLACKBIRDTryAcquireQueryInflightSlot(VOID)
{
LONG current;
for (;;)
{
current = InterlockedCompareExchange(&g_QueryImageInflight, 0, 0);
if (current >= BLACKBIRD_QUERY_IMAGE_MAX_INFLIGHT)
{
return FALSE;
}
if (InterlockedCompareExchange(&g_QueryImageInflight, current + 1, current) == current)
{
return TRUE;
}
}
}
VOID BLACKBIRDReleaseQueryInflightSlot(VOID)
{
LONG remaining;
remaining = InterlockedDecrement(&g_QueryImageInflight);
NT_ASSERT(remaining >= 0);
if (remaining < 0)
{
InterlockedExchange(&g_QueryImageInflight, 0);
}
}
VOID BLACKBIRDClientFreeQueuedEvents(_Inout_ PBLACKBIRD_CLIENT Client)
{
while (!IsListEmpty(&Client->EventQueue))
{
PLIST_ENTRY entry = RemoveHeadList(&Client->EventQueue);
PBLACKBIRD_EVENT_NODE node = CONTAINING_RECORD(entry, BLACKBIRD_EVENT_NODE, Link);
ExFreePoolWithTag(node, BLACKBIRD_POOL_TAG);
BLACKBIRDReleaseGlobalQueueSlot();
}
Client->QueueDepth = 0;
}
VOID BLACKBIRDClientRelease(_Inout_ PBLACKBIRD_CLIENT Client)
{
if (InterlockedDecrement(&Client->RefCount) != 0)
{
return;
}
ExAcquireFastMutex(&Client->Lock);
BLACKBIRDClientFreeQueuedEvents(Client);
ExReleaseFastMutex(&Client->Lock);
ExFreePoolWithTag(Client, BLACKBIRD_POOL_TAG);
}
VOID BLACKBIRDClientReference(_Inout_ PBLACKBIRD_CLIENT Client)
{
(void)InterlockedIncrement(&Client->RefCount);
}
BOOLEAN BLACKBIRDControlIsValidStreamMask(_In_ UINT32 StreamMask)
{
return ((StreamMask & (BLACKBIRD_STREAM_HANDLE | BLACKBIRD_STREAM_MEMORY | BLACKBIRD_STREAM_THREAD |
BLACKBIRD_STREAM_FILESYSTEM)) != 0);
}
VOID BLACKBIRDClientClearPendingLaunchLocked(_Inout_ PBLACKBIRD_CLIENT Client)
{
if (Client == NULL)
{
return;
}
Client->PendingLaunchArmed = FALSE;
Client->PendingLaunchStreamMask = 0;
Client->PendingLaunchPathNormDos[0] = L'\0';
Client->PendingLaunchPathNormNt[0] = L'\0';
Client->PendingLaunchPathTail[0] = L'\0';
}
VOID BLACKBIRDClientConfigurePendingLaunchLocked(_Inout_ PBLACKBIRD_CLIENT Client,
_In_opt_ const BLACKBIRD_ARM_PENDING_LAUNCH_REQUEST *Request)
{
BLACKBIRDClientClearPendingLaunchLocked(Client);
if (Client == NULL || Request == NULL)
{
return;
}
Client->PendingLaunchStreamMask = Request->StreamMask;
Client->PendingLaunchArmed = TRUE;
(void)RtlStringCchCopyW(Client->PendingLaunchPathNormDos, RTL_NUMBER_OF(Client->PendingLaunchPathNormDos),
Request->ImagePathNormDos);
(void)RtlStringCchCopyW(Client->PendingLaunchPathNormNt, RTL_NUMBER_OF(Client->PendingLaunchPathNormNt),
Request->ImagePathNormNt);
(void)RtlStringCchCopyW(Client->PendingLaunchPathTail, RTL_NUMBER_OF(Client->PendingLaunchPathTail),
Request->ImagePathTail);
}
static PCWSTR BLACKBIRDSkipKnownPathPrefixes(_In_opt_z_ PCWSTR Input)
{
if (Input == NULL)
{
return NULL;
}
if ((Input[0] == L'\\' && Input[1] == L'\\' && Input[2] == L'?' && Input[3] == L'\\') ||
(Input[0] == L'\\' && Input[1] == L'?' && Input[2] == L'?' && Input[3] == L'\\'))
{
return Input + 4;
}
return Input;
}
static VOID BLACKBIRDNormalizeWidePathForCompare(_In_opt_z_ PCWSTR Input, _Out_writes_z_(OutputChars) PWSTR Output,
_In_ SIZE_T OutputChars)
{
SIZE_T i;
SIZE_T written = 0;
if (Output == NULL || OutputChars == 0)
{
return;
}
Output[0] = L'\0';
if (Input == NULL)
{
return;
}
Input = BLACKBIRDSkipKnownPathPrefixes(Input);
if (Input == NULL)
{
return;
}
for (i = 0; Input[i] != L'\0' && (written + 1) < OutputChars; ++i)
{
WCHAR ch = Input[i];
if (ch == L'/')
{
ch = L'\\';
}
Output[written++] = RtlDowncaseUnicodeChar(ch);
}
Output[written] = L'\0';
}
static VOID BLACKBIRDNormalizeUnicodePathForCompare(_In_opt_ PCUNICODE_STRING Input,
_Out_writes_z_(OutputChars) PWSTR Output, _In_ SIZE_T OutputChars)
{
SIZE_T i;
SIZE_T inputChars;
SIZE_T written = 0;
PCWSTR inputBuffer;
if (Output == NULL || OutputChars == 0)
{
return;
}
Output[0] = L'\0';
if (Input == NULL || Input->Buffer == NULL || Input->Length == 0)
{
return;
}
inputBuffer = BLACKBIRDSkipKnownPathPrefixes(Input->Buffer);
if (inputBuffer == NULL)
{
return;
}
inputChars = Input->Length / sizeof(WCHAR);
if (inputBuffer > Input->Buffer)
{
SIZE_T skippedChars = (SIZE_T)(inputBuffer - Input->Buffer);
if (skippedChars >= inputChars)
{
return;
}
inputChars -= skippedChars;
}
for (i = 0; i < inputChars && (written + 1) < OutputChars; ++i)
{
WCHAR ch = inputBuffer[i];
if (ch == L'/')
{
ch = L'\\';
}
Output[written++] = RtlDowncaseUnicodeChar(ch);
}
Output[written] = L'\0';
}
static BOOLEAN BLACKBIRDPathHasTrailingSegmentInsensitive(_In_z_ PCWSTR Path, _In_z_ PCWSTR Tail)
{
SIZE_T pathLen;
SIZE_T tailLen;
PCWSTR end;
if (Path == NULL || Tail == NULL || Tail[0] == L'\0')
{
return FALSE;
}
pathLen = wcslen(Path);
tailLen = wcslen(Tail);
if (tailLen > pathLen)
{
return FALSE;
}
end = Path + (pathLen - tailLen);
if (_wcsicmp(end, Tail) != 0)
{
return FALSE;
}
if (end == Path)
{
return TRUE;
}
return (end[-1] == L'\\');
}
static BOOLEAN BLACKBIRDClientPathMatchesPendingLaunchLocked(_In_ const BLACKBIRD_CLIENT *Client,
_In_z_ PCWSTR CandidateNorm)
{
if (Client == NULL || CandidateNorm == NULL || CandidateNorm[0] == L'\0' || !Client->PendingLaunchArmed)
{
return FALSE;
}
if (Client->PendingLaunchPathNormNt[0] != L'\0' && _wcsicmp(Client->PendingLaunchPathNormNt, CandidateNorm) == 0)
{
return TRUE;
}
if (Client->PendingLaunchPathNormDos[0] != L'\0' && _wcsicmp(Client->PendingLaunchPathNormDos, CandidateNorm) == 0)
{
return TRUE;
}
if (Client->PendingLaunchPathTail[0] != L'\0' &&
BLACKBIRDPathHasTrailingSegmentInsensitive(CandidateNorm, Client->PendingLaunchPathTail))
{
return TRUE;
}
return FALSE;
}
BOOLEAN BLACKBIRDClientAddOrUpdateSubscriptionLocked(_Inout_ PBLACKBIRD_CLIENT Client, _In_ UINT32 ProcessId,
_In_ UINT32 StreamMask)
{
UINT32 i;
if (Client == NULL || ProcessId == 0 || StreamMask == 0)
{
return FALSE;
}
for (i = 0; i < Client->SubscriptionCount; ++i)
{
if (Client->Subscriptions[i].ProcessId == ProcessId)
{
Client->Subscriptions[i].StreamMask |= StreamMask;
return TRUE;
}
}
if (Client->SubscriptionCount >= BLACKBIRD_MAX_CLIENT_SUBSCRIPTIONS)
{
return FALSE;
}
Client->Subscriptions[Client->SubscriptionCount].ProcessId = ProcessId;
Client->Subscriptions[Client->SubscriptionCount].StreamMask = StreamMask;
Client->SubscriptionCount += 1;
return TRUE;
}
BOOLEAN BLACKBIRDClientRemoveSubscriptionLocked(_Inout_ PBLACKBIRD_CLIENT Client, _In_ UINT32 ProcessId)
{
UINT32 i;
if (Client == NULL || ProcessId == 0)
{
return FALSE;
}
for (i = 0; i < Client->SubscriptionCount; ++i)
{
if (Client->Subscriptions[i].ProcessId == ProcessId)
{
UINT32 tail = Client->SubscriptionCount - 1;
if (i != tail)
{
Client->Subscriptions[i] = Client->Subscriptions[tail];
}
Client->SubscriptionCount -= 1;
return TRUE;
}
}
return FALSE;
}
UINT32 BLACKBIRDClientReplaceSubscriptionsLocked(_Inout_ PBLACKBIRD_CLIENT Client,
_In_reads_(ProcessCount) const UINT32 *ProcessIds,
_In_ UINT32 ProcessCount, _In_ UINT32 StreamMask)
{
UINT32 i;
if (Client == NULL || ProcessIds == NULL || ProcessCount == 0 || StreamMask == 0)
{
return 0;
}
Client->SubscriptionCount = 0;
for (i = 0; i < ProcessCount; ++i)
{
UINT32 pid = ProcessIds[i];
if (pid == 0)
{
continue;
}
(void)BLACKBIRDClientAddOrUpdateSubscriptionLocked(Client, pid, StreamMask);
}
return Client->SubscriptionCount;
}
static VOID BLACKBIRDControlFlushAllClientState(VOID)
{
PBLACKBIRD_CLIENT snapshot[BLACKBIRD_MAX_TOTAL_CLIENTS];
UINT32 snapshotCount = 0;
UINT32 i;
PLIST_ENTRY e;
ExAcquireFastMutex(&g_ClientListLock);
for (e = g_ClientList.Flink; e != &g_ClientList; e = e->Flink)
{
PBLACKBIRD_CLIENT c = CONTAINING_RECORD(e, BLACKBIRD_CLIENT, Link);
if (snapshotCount >= RTL_NUMBER_OF(snapshot))
{
break;
}
BLACKBIRDClientReference(c);
snapshot[snapshotCount++] = c;
}
ExReleaseFastMutex(&g_ClientListLock);
for (i = 0; i < snapshotCount; ++i)
{
PBLACKBIRD_CLIENT c = snapshot[i];
WDFQUEUE pendingQueue = NULL;
ExAcquireFastMutex(&c->Lock);
pendingQueue = c->PendingGetEventQueue;
c->PendingGetEventQueue = NULL;
c->SubscriptionCount = 0;
BLACKBIRDClientClearPendingLaunchLocked(c);
BLACKBIRDClientFreeQueuedEvents(c);
ExReleaseFastMutex(&c->Lock);
if (pendingQueue != NULL)
{
WdfIoQueuePurgeSynchronously(pendingQueue);
}
BLACKBIRDClientRelease(c);
}
}
VOID BLACKBIRDControlRefreshArmedState(VOID)
{
PBLACKBIRD_CLIENT snapshot[BLACKBIRD_MAX_TOTAL_CLIENTS];
UINT32 snapshotCount = 0;
UINT32 i;
PLIST_ENTRY entry;
BOOLEAN armed = FALSE;
ExAcquireFastMutex(&g_ClientListLock);
for (entry = g_ClientList.Flink; entry != &g_ClientList; entry = entry->Flink)
{
PBLACKBIRD_CLIENT client = CONTAINING_RECORD(entry, BLACKBIRD_CLIENT, Link);
if (snapshotCount >= RTL_NUMBER_OF(snapshot))
{
break;
}
BLACKBIRDClientReference(client);
snapshot[snapshotCount++] = client;
}
ExReleaseFastMutex(&g_ClientListLock);
for (i = 0; i < snapshotCount; ++i)
{
PBLACKBIRD_CLIENT client = snapshot[i];
ExAcquireFastMutex(&client->Lock);
if (client->SubscriptionCount != 0)
{
armed = TRUE;
}
ExReleaseFastMutex(&client->Lock);
BLACKBIRDClientRelease(client);
if (armed)
{
break;
}
}
for (++i; i < snapshotCount; ++i)
{
BLACKBIRDClientRelease(snapshot[i]);
}
InterlockedExchange(&g_ControlTelemetryArmed, armed ? 1 : 0);
}
VOID BLACKBIRDControlBeginShutdown(VOID)
{
if (InterlockedExchange(&g_ControlShutdown, 1) == 0)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "BLACKBIRD: control plane entering shutdown mode.\n");
}
BLACKBIRDControlFlushAllClientState();
InterlockedExchange(&g_ControlTelemetryArmed, 0);
}
static PBLACKBIRD_CLIENT BLACKBIRDClientCreate(VOID)
{
PBLACKBIRD_CLIENT client;
client = (PBLACKBIRD_CLIENT)BLACKBIRDAllocatePoolCompat(POOL_FLAG_NON_PAGED, sizeof(*client), BLACKBIRD_POOL_TAG);
if (client == NULL)
{
return NULL;
}
RtlZeroMemory(client, sizeof(*client));
InitializeListHead(&client->EventQueue);
client->PendingGetEventQueue = NULL;
ExInitializeFastMutex(&client->Lock);
client->RefCount = 1;
return client;
}
BOOLEAN BLACKBIRDClientMatchSubscriptionEither(_In_ PBLACKBIRD_CLIENT Client, _In_ UINT32 PrimaryProcessId,
_In_ UINT32 SecondaryProcessId, _In_ UINT32 StreamMask)
{
UINT32 i;
for (i = 0; i < Client->SubscriptionCount; ++i)
{
UINT32 subscribedPid;
UINT32 subscribedMask;
subscribedPid = Client->Subscriptions[i].ProcessId;
subscribedMask = Client->Subscriptions[i].StreamMask;
if ((subscribedMask & StreamMask) == 0)
{
continue;
}
if (subscribedPid == PrimaryProcessId || (SecondaryProcessId != 0 && subscribedPid == SecondaryProcessId))
{
return TRUE;
}
}
return FALSE;
}
BOOLEAN
BLACKBIRDControlBindPendingLaunchProcess(_In_ UINT32 ProcessId, _In_opt_ PCUNICODE_STRING ImagePath)
{
PBLACKBIRD_CLIENT snapshot[BLACKBIRD_MAX_TOTAL_CLIENTS];
WCHAR candidateNorm[BLACKBIRD_MAX_IMAGE_PATH_CHARS];
UINT32 snapshotCount = 0;
UINT32 i;
PLIST_ENTRY entry;
BOOLEAN matchedAny = FALSE;
if (ProcessId == 0 || ImagePath == NULL || ImagePath->Buffer == NULL || ImagePath->Length == 0)
{
return FALSE;
}
if (!BLACKBIRDControlHasClientsFast())
{
return FALSE;
}
BLACKBIRDNormalizeUnicodePathForCompare(ImagePath, candidateNorm, RTL_NUMBER_OF(candidateNorm));
if (candidateNorm[0] == L'\0')
{
return FALSE;
}
ExAcquireFastMutex(&g_ClientListLock);
for (entry = g_ClientList.Flink; entry != &g_ClientList; entry = entry->Flink)
{
PBLACKBIRD_CLIENT client = CONTAINING_RECORD(entry, BLACKBIRD_CLIENT, Link);
if (snapshotCount >= RTL_NUMBER_OF(snapshot))
{
break;
}
BLACKBIRDClientReference(client);
snapshot[snapshotCount++] = client;
}
ExReleaseFastMutex(&g_ClientListLock);
for (i = 0; i < snapshotCount; ++i)
{
PBLACKBIRD_CLIENT client = snapshot[i];
ExAcquireFastMutex(&client->Lock);
if (BLACKBIRDClientPathMatchesPendingLaunchLocked(client, candidateNorm))
{
UINT32 streamMask = client->PendingLaunchStreamMask;
BOOLEAN subscribed = BLACKBIRDClientAddOrUpdateSubscriptionLocked(client, ProcessId, streamMask);
BLACKBIRDClientClearPendingLaunchLocked(client);
if (subscribed)
{
matchedAny = TRUE;
InterlockedExchange(&g_ControlTelemetryArmed, 1);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"BLACKBIRD: pending launch bound targetPid=%lu streamMask=0x%08X image=%ws.\n", ProcessId,
streamMask, candidateNorm);
}
else
{
DbgPrintEx(
DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL,
"BLACKBIRD: pending launch match could not bind targetPid=%lu image=%ws reason=subscription-capacity.\n",
ProcessId, candidateNorm);
}
}
ExReleaseFastMutex(&client->Lock);
BLACKBIRDClientRelease(client);
}
return matchedAny;
}
static VOID BLACKBIRDClientEnqueueEvent(_Inout_ PBLACKBIRD_CLIENT Client, _In_ const BLACKBIRD_EVENT_RECORD *Source)
{
PBLACKBIRD_EVENT_NODE node;
LONG dropLogCounter;
if (Client->QueueDepth >= BLACKBIRD_MAX_CLIENT_QUEUE_DEPTH)
{
Client->DroppedEvents += 1;
dropLogCounter = InterlockedIncrement(&g_ControlQueueDropLogCounter);
if (dropLogCounter == 1 || ((dropLogCounter & 0xFF) == 0))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL,
"BLACKBIRD: queue drop (client depth cap=%lu) totalDrops=%lu clientDrops=%u queueDepth=%u.\n",
BLACKBIRD_MAX_CLIENT_QUEUE_DEPTH, (ULONG)dropLogCounter, Client->DroppedEvents,
Client->QueueDepth);
}
return;
}
if (!BLACKBIRDTryAcquireGlobalQueueSlot())
{
Client->DroppedEvents += 1;
dropLogCounter = InterlockedIncrement(&g_ControlQueueDropLogCounter);
if (dropLogCounter == 1 || ((dropLogCounter & 0xFF) == 0))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL,
"BLACKBIRD: queue drop (global cap=%lu) totalDrops=%lu clientDrops=%u globalQueued=%ld.\n",
BLACKBIRD_MAX_TOTAL_QUEUED_EVENTS, (ULONG)dropLogCounter, Client->DroppedEvents,
InterlockedCompareExchange(&g_ControlTotalQueuedEvents, 0, 0));
}
return;
}
node = (PBLACKBIRD_EVENT_NODE)BLACKBIRDAllocatePoolCompat(POOL_FLAG_NON_PAGED, sizeof(*node), BLACKBIRD_POOL_TAG);
if (node == NULL)
{
BLACKBIRDReleaseGlobalQueueSlot();
Client->DroppedEvents += 1;
dropLogCounter = InterlockedIncrement(&g_ControlQueueDropLogCounter);
if (dropLogCounter == 1 || ((dropLogCounter & 0xFF) == 0))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL,
"BLACKBIRD: queue drop (alloc failure) totalDrops=%lu clientDrops=%u queueDepth=%u.\n",
(ULONG)dropLogCounter, Client->DroppedEvents, Client->QueueDepth);
}
return;
}
RtlZeroMemory(node, sizeof(*node));
RtlCopyMemory(&node->Record, Source, sizeof(node->Record));
InsertTailList(&Client->EventQueue, &node->Link);
Client->QueueDepth += 1;
}
static BOOLEAN BLACKBIRDClientTryTakePendingGetEventRequestLocked(_In_ PBLACKBIRD_CLIENT Client,
_Out_ WDFREQUEST *Request)
{
NTSTATUS status;
if (Request == NULL)
{
return FALSE;
}
*Request = NULL;
if (Client == NULL || Client->PendingGetEventQueue == NULL)
{
return FALSE;
}
status = WdfIoQueueRetrieveNextRequest(Client->PendingGetEventQueue, Request);
return NT_SUCCESS(status);
}
static NTSTATUS BLACKBIRDCompleteGetEventRequestWithRecord(_In_ WDFREQUEST Request,
_In_ const BLACKBIRD_EVENT_RECORD *Record)
{
NTSTATUS status;
PBLACKBIRD_EVENT_RECORD out;
size_t outSize;
LONG deliverCounter;
ULONG requesterPid;
if (Request == NULL || Record == NULL)
{
return STATUS_INVALID_PARAMETER;
}
status = WdfRequestRetrieveOutputBuffer(Request, sizeof(*out), (PVOID *)&out, &outSize);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, status);
return status;
}
if (outSize < sizeof(*out))
{
WdfRequestComplete(Request, STATUS_BUFFER_TOO_SMALL);
return STATUS_BUFFER_TOO_SMALL;
}
RtlCopyMemory(out, Record, sizeof(*out));
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(*out));
deliverCounter = InterlockedIncrement(&g_IoctlGetEventDeliverCounter);
if (deliverCounter == 1 || ((deliverCounter & 0x1FF) == 0))
{
requesterPid = BLACKBIRDGetRequestorPid();
DbgPrintEx(
DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"BLACKBIRD: get-event delivered(pended) requesterPid=%lu deliveredCount=%ld eventType=%lu seq=%lu.\n",
requesterPid, deliverCounter, Record->Header.Type, Record->Header.Sequence);
}
return STATUS_SUCCESS;
}
VOID BLACKBIRDPublishRecordToSubscribers(_In_ UINT32 PrimaryPid, _In_ UINT32 SecondaryPid, _In_ UINT32 StreamMask,
_In_ BLACKBIRD_EVENT_RECORD *Record)
{
ULONGLONG tempusStartQpc = BLACKBIRDTempusEnter(BlackbirdTempusSubsystemControl);
PBLACKBIRD_CLIENT snapshot[BLACKBIRD_MAX_TOTAL_CLIENTS];
UINT32 snapshotCount = 0;
UINT32 i;
PLIST_ENTRY e;
if (InterlockedCompareExchange(&g_ControlInitialized, 0, 0) == 0)
{
BLACKBIRDTempusLeave(BlackbirdTempusSubsystemControl, tempusStartQpc);
return;
}
if (BLACKBIRDControlIsShutdown())
{
BLACKBIRDTempusLeave(BlackbirdTempusSubsystemControl, tempusStartQpc);
return;
}
ExAcquireFastMutex(&g_ClientListLock);
for (e = g_ClientList.Flink; e != &g_ClientList; e = e->Flink)
{
PBLACKBIRD_CLIENT c = CONTAINING_RECORD(e, BLACKBIRD_CLIENT, Link);
if (snapshotCount >= RTL_NUMBER_OF(snapshot))
{
break;
}
BLACKBIRDClientReference(c);
snapshot[snapshotCount++] = c;
}
ExReleaseFastMutex(&g_ClientListLock);
for (i = 0; i < snapshotCount; ++i)
{
PBLACKBIRD_CLIENT c = snapshot[i];
WDFREQUEST pendingRequest = NULL;
BLACKBIRD_EVENT_RECORD stagedRecord;
BOOLEAN matched = FALSE;
NTSTATUS deliverStatus = STATUS_UNSUCCESSFUL;
RtlZeroMemory(&stagedRecord, sizeof(stagedRecord));
ExAcquireFastMutex(&c->Lock);
if (BLACKBIRDClientMatchSubscriptionEither(c, PrimaryPid, SecondaryPid, StreamMask))
{
matched = TRUE;
RtlCopyMemory(&stagedRecord, Record, sizeof(stagedRecord));
stagedRecord.Header.Sequence = ++c->Sequence;
if (!BLACKBIRDClientTryTakePendingGetEventRequestLocked(c, &pendingRequest))
{
BLACKBIRDClientEnqueueEvent(c, &stagedRecord);
}
}
ExReleaseFastMutex(&c->Lock);
if (matched && pendingRequest != NULL)
{
deliverStatus = BLACKBIRDCompleteGetEventRequestWithRecord(pendingRequest, &stagedRecord);
if (!NT_SUCCESS(deliverStatus) && !BLACKBIRDControlIsShutdown())
{
ExAcquireFastMutex(&c->Lock);
BLACKBIRDClientEnqueueEvent(c, &stagedRecord);
ExReleaseFastMutex(&c->Lock);
}
}
BLACKBIRDClientRelease(c);
}
BLACKBIRDTempusLeave(BlackbirdTempusSubsystemControl, tempusStartQpc);
}
EVT_WDF_DEVICE_FILE_CREATE BLACKBIRDEvtFileCreate;
EVT_WDF_FILE_CLEANUP BLACKBIRDEvtFileCleanup;
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL BLACKBIRDEvtIoDeviceControl;
_Use_decl_annotations_ VOID BLACKBIRDEvtFileCreate(WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject)
{
PBLACKBIRD_FILE_CONTEXT ctx;
PBLACKBIRD_CLIENT client;
WDF_IO_QUEUE_CONFIG queueConfig;
WDF_OBJECT_ATTRIBUTES queueAttrs;
WDFQUEUE pendingQueue = NULL;
NTSTATUS queueStatus = STATUS_SUCCESS;
ULONG requesterPid;
LONG clientCountSnapshot;
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
WdfRequestComplete(Request, STATUS_INVALID_DEVICE_STATE);
return;
}
if (BLACKBIRDControlIsShutdown())
{
WdfRequestComplete(Request, STATUS_DELETE_PENDING);
return;
}
client = BLACKBIRDClientCreate();
if (client == NULL)
{
WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
return;
}
ExAcquireFastMutex(&g_ClientListLock);
if (g_ClientCount >= BLACKBIRD_MAX_TOTAL_CLIENTS)
{
ExReleaseFastMutex(&g_ClientListLock);
BLACKBIRDClientRelease(client);
WdfRequestComplete(Request, STATUS_QUOTA_EXCEEDED);
return;
}
InsertTailList(&g_ClientList, &client->Link);
g_ClientCount += 1;
clientCountSnapshot = g_ClientCount;
ExReleaseFastMutex(&g_ClientListLock);
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);
queueConfig.PowerManaged = WdfFalse;
WDF_OBJECT_ATTRIBUTES_INIT(&queueAttrs);
queueAttrs.ParentObject = FileObject;
queueStatus = WdfIoQueueCreate(Device, &queueConfig, &queueAttrs, &pendingQueue);
if (!NT_SUCCESS(queueStatus))
{
ExAcquireFastMutex(&g_ClientListLock);
RemoveEntryList(&client->Link);
InitializeListHead(&client->Link);
if (g_ClientCount > 0)
{
g_ClientCount -= 1;
}
ExReleaseFastMutex(&g_ClientListLock);
BLACKBIRDClientRelease(client);
WdfRequestComplete(Request, queueStatus);
return;
}
client->PendingGetEventQueue = pendingQueue;
ctx = BLACKBIRDGetFileContext(FileObject);
ctx->Client = client;
requesterPid = BLACKBIRDGetRequestorPid();
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"BLACKBIRD: client attached pid=%lu activeClients=%ld fileObj=0x%p.\n", requesterPid,
clientCountSnapshot, FileObject);
WdfRequestComplete(Request, STATUS_SUCCESS);
}
_Use_decl_annotations_ VOID BLACKBIRDEvtFileCleanup(WDFFILEOBJECT FileObject)
{
PBLACKBIRD_FILE_CONTEXT ctx = BLACKBIRDGetFileContext(FileObject);
PBLACKBIRD_CLIENT client = ctx->Client;
PLIST_ENTRY e;
LONG clientCountSnapshot = 0;
UINT32 subscriptionCountSnapshot = 0;
UINT32 queueDepthSnapshot = 0;
UINT32 droppedSnapshot = 0;
ULONG requesterPid;
if (client == NULL)
{
return;
}
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
return;
}
ExAcquireFastMutex(&g_ClientListLock);
for (e = g_ClientList.Flink; e != &g_ClientList; e = e->Flink)
{
if (CONTAINING_RECORD(e, BLACKBIRD_CLIENT, Link) == client)
{
RemoveEntryList(e);
if (g_ClientCount > 0)
{
g_ClientCount -= 1;
}
clientCountSnapshot = g_ClientCount;
break;
}
}
ExReleaseFastMutex(&g_ClientListLock);
if (clientCountSnapshot == 0)
{
InterlockedExchange(&g_ControlTelemetryArmed, 0);
}
else
{
BLACKBIRDControlRefreshArmedState();
}
ExAcquireFastMutex(&client->Lock);
{
WDFQUEUE pendingQueue = client->PendingGetEventQueue;
client->PendingGetEventQueue = NULL;
subscriptionCountSnapshot = client->SubscriptionCount;
queueDepthSnapshot = client->QueueDepth;
droppedSnapshot = client->DroppedEvents;
ExReleaseFastMutex(&client->Lock);
if (pendingQueue != NULL)
{
WdfIoQueuePurgeSynchronously(pendingQueue);
}
}
requesterPid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
DbgPrintEx(
DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"BLACKBIRD: client detached pid=%lu activeClients=%ld subscriptions=%lu queueDepth=%lu dropped=%lu fileObj=0x%p.\n",
requesterPid, clientCountSnapshot, subscriptionCountSnapshot, queueDepthSnapshot, droppedSnapshot, FileObject);
BLACKBIRDClientRelease(client);
ctx->Client = NULL;
}