windows-nt/Source/XPSP1/NT/base/win32/verifier/support.c
2020-09-26 16:20:57 +08:00

469 lines
8.9 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
support.c
Abstract:
This module implements internal support for the verification code.
Author:
Silviu Calinoiu (SilviuC) 1-Mar-2001
Revision History:
--*/
#include "pch.h"
#include "verifier.h"
#include "support.h"
//
// Security checks
//
VOID
CheckObjectAttributes (
POBJECT_ATTRIBUTES Object
)
{
if (Object /* && Object->ObjectName */) {
if (Object->ObjectName == NULL) {
DbgPrint ("Object attributes @ %p with null name \n", Object);
DbgBreakPoint ();
}
if (Object->SecurityDescriptor == NULL) {
DbgPrint ("Object attributes @ %p with null security descriptor \n", Object);
DbgBreakPoint ();
}
}
}
//
// Handle management
//
LIST_ENTRY HandleList;
RTL_CRITICAL_SECTION HandleLock;
ULONG HandleBreakOnDelayed = 1;
VOID
HandleInitialize (
)
{
InitializeListHead (&HandleList);
RtlInitializeCriticalSection (&HandleLock);
}
PAVRF_HANDLE
HandleFind (
HANDLE Handle
)
{
PLIST_ENTRY Current;
PAVRF_HANDLE Entry;
RtlEnterCriticalSection (&HandleLock);
Current = HandleList.Flink;
while (Current != &HandleList) {
Entry = CONTAINING_RECORD (Current,
AVRF_HANDLE,
Links);
Current = Current->Flink;
if (Entry->Handle == Handle) {
RtlLeaveCriticalSection (&HandleLock);
return Entry;
}
}
RtlLeaveCriticalSection (&HandleLock);
return NULL;
}
PWSTR
HandleName (
PAVRF_HANDLE Handle
)
{
if (Handle) {
if (Handle->Name) {
return Handle->Name;
}
else {
if (Handle->Delayed) {
return L"<noname:ntdll>";
}
else {
return L"<noname>";
}
}
}
return L"<null>";
}
PAVRF_HANDLE
HandleAdd (
HANDLE Handle,
ULONG Type,
BOOLEAN Delayed,
PWSTR Name,
PVOID Context
)
{
PLIST_ENTRY Current;
PAVRF_HANDLE Entry;
PWSTR NameCopy;
ULONG Hash;
if (HandleBreakOnDelayed && Delayed) {
DbgPrint (" --- dumping ... %p \n", HandleList.Flink);
HandleDump (NULL);
DbgPrint ("AVRF: undetected handle \n");
DbgBreakPoint ();
}
Entry = (PAVRF_HANDLE) RtlAllocateHeap (RtlProcessHeap(),
0,
sizeof *Entry);
if (Entry == NULL) {
return NULL;
}
if (Name) {
NameCopy = (PWSTR) RtlAllocateHeap (RtlProcessHeap(),
0,
2 * (wcslen(Name) + 1));
if (NameCopy == NULL) {
RtlFreeHeap (RtlProcessHeap(), 0, Entry);
return NULL;
}
wcscpy (NameCopy, Name);
}
else {
NameCopy = NULL;
}
RtlZeroMemory (Entry, sizeof *Entry);
Entry->Handle = Handle;
Entry->Type = Type;
Entry->Delayed = Delayed ? 1 : 0;
Entry->Context = Context;
Entry->Name = NameCopy;
RtlCaptureStackBackTrace (2,
MAX_TRACE_DEPTH,
Entry->Trace,
&Hash);
RtlEnterCriticalSection (&HandleLock);
InsertHeadList (&HandleList,
&(Entry->Links));
RtlLeaveCriticalSection (&HandleLock);
return Entry;
}
VOID
HandleDelete (
HANDLE Handle,
PAVRF_HANDLE Entry
)
{
RtlEnterCriticalSection (&HandleLock);
RemoveEntryList (&(Entry->Links));
RtlLeaveCriticalSection (&HandleLock);
if (Entry->Name) {
RtlFreeHeap (RtlProcessHeap(), 0, Entry->Name);
}
RtlFreeHeap (RtlProcessHeap(), 0, Entry);
}
VOID
HandleDump (
HANDLE Handle
)
{
PLIST_ENTRY Current;
PAVRF_HANDLE Entry;
RtlEnterCriticalSection (&HandleLock);
Current = HandleList.Flink;
while (Current != &HandleList) {
Entry = CONTAINING_RECORD (Current,
AVRF_HANDLE,
Links);
Current = Current->Flink;
if (Handle == NULL || Entry->Handle == Handle) {
DbgPrint ("HNDL: %08X %04u `%ws' \n",
HandleToUlong(Entry->Handle),
Entry->Type,
HandleName(Entry));
}
}
RtlLeaveCriticalSection (&HandleLock);
}
//
// Virtual space operations tracking.
//
typedef struct _VS_CALL {
struct {
ULONG Type : 4;
ULONG Trace : 16;
ULONG Thread : 12;
};
PVOID Address;
SIZE_T Size;
ULONG Operation;
ULONG Protection;
} VS_CALL, *PVS_CALL;
#define NO_OF_VS_CALLS 8192
VS_CALL VsCalls [NO_OF_VS_CALLS];
LONG VsCallsIndex;
VOID
VsLogCall (
VS_CALL_TYPE Type,
PVOID Address,
SIZE_T Size,
ULONG Operation,
ULONG Protection
)
{
ULONG Index;
ULONG Hash;
Index = (ULONG)InterlockedIncrement (&VsCallsIndex);
Index %= NO_OF_VS_CALLS;
//RtlZeroMemory (&(VsCalls[Index]), sizeof (VS_CALL));
VsCalls[Index].Address = Address;
VsCalls[Index].Type = Type;
VsCalls[Index].Trace = RtlLogStackBackTrace();
VsCalls[Index].Thread = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
VsCalls[Index].Size = Size;
VsCalls[Index].Operation = Operation;
VsCalls[Index].Protection = Protection;
if (AVrfpProvider.VerifierDebug) {
DbgPrint ("AVRF:VS: %01u (%04X): %p %p %X %X \n",
Type,
(ULONG)(VsCalls[Index].Trace),
Address, Size, Operation, Protection);
}
}
//
// Heap operations tracking
//
typedef struct _HEAP_CALL {
struct {
ULONG Reserved : 4;
ULONG Trace : 16;
ULONG Thread : 12;
};
PVOID Address;
SIZE_T Size;
} HEAP_CALL, *PHEAP_CALL;
#define NO_OF_HEAP_CALLS 8192
HEAP_CALL HeapCalls [NO_OF_HEAP_CALLS];
LONG HeapCallsIndex;
VOID
HeapLogCall (
PVOID Address,
SIZE_T Size
)
{
ULONG Index;
ULONG Hash;
Index = (ULONG)InterlockedIncrement (&HeapCallsIndex);
Index %= NO_OF_HEAP_CALLS;
//RtlZeroMemory (&(HeapCalls[Index]), sizeof (HEAP_CALL));
HeapCalls[Index].Address = Address;
HeapCalls[Index].Trace = RtlLogStackBackTrace();
HeapCalls[Index].Thread = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
HeapCalls[Index].Size = Size;
if (AVrfpProvider.VerifierDebug) {
DbgPrint ("AVRF:HEAP: %04X (%04X): %p %p \n",
(ULONG)(HeapCalls[Index].Thread),
(ULONG)(HeapCalls[Index].Trace),
Address, Size);
}
}
VOID
AVrfpDirtyThreadStack (
)
{
PTEB Teb = NtCurrentTeb();
ULONG_PTR StackStart;
ULONG_PTR StackEnd;
try {
StackStart = (ULONG_PTR)(Teb->NtTib.StackLimit);
//
// ISSUE: SilviuC: we should dirty stacks on all architectures
//
#if defined(_X86_)
_asm mov StackEnd, ESP;
#else
StackEnd = StackStart;
#endif
//
// Limit stack dirtying to only 8K.
//
if (StackStart < StackEnd - 0x2000) {
StackStart = StackEnd - 0x2000;
}
if (AVrfpProvider.VerifierDebug) {
DbgPrint ("Dirtying stack range %p - %p for thread %p \n",
StackStart, StackEnd, Teb->ClientId.UniqueThread);
}
while (StackStart < StackEnd) {
*((PULONG)StackStart) = 0xBAD1BAD1;
StackStart += sizeof(ULONG);
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
// nothing
}
}
//
// Standard function used for hooked CreateThread.
//
ULONG
AVrfpThreadFunctionExceptionFilter (
ULONG ExceptionCode,
PVOID ExceptionRecord
)
{
VERIFIER_STOP (APPLICATION_VERIFIER_UNEXPECTED_EXCEPTION,
"unexpected exception raised in thread function",
ExceptionCode, "Exception code",
ExceptionRecord, "Exception record (.exr on 1st word, .cxr on 2nd word)",
0, "",
0, "");
return EXCEPTION_EXECUTE_HANDLER;
}
DWORD
WINAPI
AVrfpStandardThreadFunction (
LPVOID Context
)
{
PAVRF_THREAD_INFO Info = (PAVRF_THREAD_INFO)Context;
DWORD Result;
try {
//
// Call the real thing.
//
Result = (Info->Function)(Info->Parameter);
}
except (AVrfpThreadFunctionExceptionFilter (_exception_code(), _exception_info())) {
//
// Nothing.
//
}
//
// Perform all typical checks for a thread that has just finished.
//
RtlCheckForOrphanedCriticalSections (NtCurrentThread());
AVrfpCheckThreadTermination ();
RtlFreeHeap (RtlProcessHeap(), 0, Info);
return Result;
}
VOID
AVrfpCheckThreadTermination (
VOID
)
{
//
// Nothing yet.
//
}