|
|
//
// Template Driver
// Copyright (c) Microsoft Corporation, 1999.
//
// Module: tdriver.c
// Author: Silviu Calinoiu (SilviuC)
// Created: 4/20/1999 2:39pm
//
// This module contains a template driver.
//
// --- History ---
//
// 4/20/1999 (SilviuC): initial version.
//
// 10/25/1999 (DMihai): Aded tests for:
// - paged pool size
// - non paged pool size
// - number of free system PTEs
//
#include <ntddk.h>
#include "active.h"
#include "mmtests.h"
#include "physmem.h"
#include "tdriver.h"
#if !MMTESTS_ACTIVE
//
// Dummy implementation if the module is inactive
//
VOID MmTestDisabled (VOID) { DbgPrint ("Buggy: mmtests module is disabled (check \\driver\\active.h header) \n"); }
VOID MmTestProbeLockForEverStress ( IN PVOID NotUsed ) { MmTestDisabled (); }
VOID MmTestNameToAddressStress ( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID MmTestEccBadStress ( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID TdSysPagedPoolMaxTest( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID TdSysPagedPoolTotalTest( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID TdNonPagedPoolMaxTest( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID TdNonPagedPoolTotalTest( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID TdFreeSystemPtesTest( IN PVOID IrpAddress ) { MmTestDisabled (); }
VOID StressPoolFlag ( PVOID NotUsed ) { MmTestDisabled (); }
VOID StressPoolTagTableExtension ( PVOID NotUsed ) { MmTestDisabled (); }
#else
//
// Real implementation if the module is active
//
ULONG BuggyPP = (96 * 1024 * 1024); PVOID BuggyOld; SIZE_T UserVaSize = (50 * 1024 * 1024); ULONG BuggyHold = 1;
ULONG OverrideStart; ULONG OverrideSize; ULONG OverrideCount;
#define VERBOSITY_PRINT 0x0001
#define VERBOSITY_BREAK 0x0002
ULONG Verbosity = 0x0003;
NTSYSCALLAPI NTSTATUS NTAPI ZwAllocateVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect );
NTSTATUS MmMarkPhysicalMemoryAsBad ( IN PPHYSICAL_ADDRESS StartAddress, IN OUT PLARGE_INTEGER NumberOfBytes );
NTSTATUS MmMarkPhysicalMemoryAsGood ( IN PPHYSICAL_ADDRESS StartAddress, IN OUT PLARGE_INTEGER NumberOfBytes );
VOID MmTestProbeLockForEverStress ( IN PVOID IrpAddress ) { PIRP Irp = (PIRP) IrpAddress; PIO_STACK_LOCATION IrpStack; ULONG InputBufferLength; ULONG OutputBufferLength; ULONG Ioctl; NTSTATUS Status; ULONG BufferSize; ULONG ReturnedSize;
IrpStack = IoGetCurrentIrpStackLocation (Irp);
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
{ SIZE_T RegionSize; PVOID UserVa; PMDL Mdl;
UserVa = NULL; RegionSize = UserVaSize;
Status = ZwAllocateVirtualMemory (NtCurrentProcess(), (PVOID *)&UserVa, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE); if (NT_SUCCESS(Status)) {
Mdl = IoAllocateMdl ( UserVa, (ULONG)RegionSize, FALSE, // not secondary buffer
FALSE, // do not charge quota
NULL); // no irp
if (Mdl != NULL) {
try { MmProbeAndLockPages (Mdl, KernelMode, IoReadAccess);
DbgPrint ("Buggy: locked pages in MDL %p\n", Mdl); DbgBreakPoint ();
//
// Don't exit now without unlocking !
//
while (BuggyHold != 0) { KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond); } MmUnlockPages (Mdl); IoFreeMdl (Mdl); } except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint ("Buggy: exception raised while locking %p\n", Mdl); DbgBreakPoint (); } } } }
DbgPrint ("Buggy: finish with probe-and-lock forever ioctl \n"); Status = STATUS_SUCCESS; }
VOID MmTestNameToAddressStress ( IN PVOID IrpAddress ) { PIRP Irp = (PIRP) IrpAddress; PIO_STACK_LOCATION IrpStack; ULONG InputBufferLength; ULONG OutputBufferLength; ULONG Ioctl; NTSTATUS Status; ULONG BufferSize; ULONG ReturnedSize;
IrpStack = IoGetCurrentIrpStackLocation (Irp);
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
{
#define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
const UNICODE_STRING RoutineA = CONSTANT_UNICODE_STRING( L"KfRaiseIrql" );
const UNICODE_STRING RoutineList[] = {
CONSTANT_UNICODE_STRING( L"KeBugCheckEx" ), CONSTANT_UNICODE_STRING( L"KiBugCheckData" ), CONSTANT_UNICODE_STRING( L"KeWaitForSingleObject" ), CONSTANT_UNICODE_STRING( L"KeWaitForMutexObject" ), CONSTANT_UNICODE_STRING( L"Junk1" ), CONSTANT_UNICODE_STRING( L"CcCanIWrite" ), CONSTANT_UNICODE_STRING( L"Junk" ),
};
PVOID Addr; ULONG i;
Addr = MmGetSystemRoutineAddress ((PUNICODE_STRING)&RoutineA);
DbgPrint ("Addr is %p\n", Addr);
for (i = 0; i < sizeof (RoutineList) / sizeof (UNICODE_STRING); i += 1) {
Addr = MmGetSystemRoutineAddress ((PUNICODE_STRING)&RoutineList[i]);
DbgPrint ("Addr0 is %p\n", Addr); } } }
VOID MmTestEccBadStress ( IN PVOID IrpAddress ) { PIRP Irp = (PIRP) IrpAddress; PIO_STACK_LOCATION IrpStack; ULONG InputBufferLength; ULONG OutputBufferLength; ULONG Ioctl; NTSTATUS Status; ULONG BufferSize; ULONG ReturnedSize;
IrpStack = IoGetCurrentIrpStackLocation (Irp);
InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;
DbgPrint ("Buggy: mark physical memory ECC bad ioctl \n");
{ ULONG i; PPHYSICAL_MEMORY_RANGE Ranges; PPHYSICAL_MEMORY_RANGE p;
PHYSICAL_ADDRESS StartAddress; LARGE_INTEGER NumberOfBytes;
PHYSICAL_ADDRESS InputAddress; LARGE_INTEGER InputBytes;
Ranges = MmGetPhysicalMemoryRanges (); if (Ranges == NULL) { DbgPrint ("Buggy: MmRemovePhysicalMemory cannot get ranges\n"); Status = STATUS_INSUFFICIENT_RESOURCES; return; }
i = 0; DbgPrint("StartAddress @ %p, OverrideSize @ %p, OverrideCount @ %p\n", &OverrideStart, &OverrideSize, &OverrideCount); DbgBreakPoint();
p = Ranges; while (p->BaseAddress.QuadPart != 0 && p->NumberOfBytes.QuadPart != 0) { StartAddress.QuadPart = p->BaseAddress.QuadPart; NumberOfBytes.QuadPart = p->NumberOfBytes.QuadPart;
if (OverrideStart != 0) { StartAddress.LowPart = OverrideStart; }
InputAddress.QuadPart = StartAddress.QuadPart; InputBytes.QuadPart = NumberOfBytes.QuadPart;
#ifdef BIG_REMOVES
if (InputBytes.QuadPart > (64 * 1024)) { InputBytes.QuadPart = (64 * 1024); } #else
if (InputBytes.QuadPart > (4 * 1024)) { InputBytes.QuadPart = (4 * 1024); } #endif
if (OverrideSize != 0) { InputBytes.LowPart = OverrideSize; }
while (InputAddress.QuadPart + InputBytes.QuadPart <= StartAddress.QuadPart + NumberOfBytes.QuadPart) {
if (OverrideCount != 0 && i > OverrideCount) { break; }
i += 1;
DbgPrint ("buggy: MmMarkPhysicalMemoryAsBad %x %x %x %x\n", InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart);
Status = MmMarkPhysicalMemoryAsBad (&InputAddress, &InputBytes);
DbgPrint ("buggy: MmMarkPhysicalMemoryAsBad %x %x %x %x %x\n\n", Status, InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart);
KeDelayExecutionThread (KernelMode, FALSE, &BuggyOneSecond);
if (NT_SUCCESS(Status)) {
DbgPrint ("buggy: MmMarkPhysicalMemoryAsGood %x %x %x %x\n", InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart);
Status = MmMarkPhysicalMemoryAsGood (&InputAddress, &InputBytes);
if (NT_SUCCESS(Status)) { DbgPrint ("\n\n***************\nbuggy: MmMarkPhysicalMemoryAsGood WORKED %x %x %x %x %x\n****************\n", Status, InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart); } else { DbgPrint ("buggy: MmMarkPhysicalMemoryAsGood FAILED %x %x %x %x %x\n\n", Status, InputAddress.HighPart, InputAddress.LowPart, InputBytes.HighPart, InputBytes.LowPart); DbgBreakPoint (); } }
if (InputAddress.QuadPart + InputBytes.QuadPart == StartAddress.QuadPart + NumberOfBytes.QuadPart) {
break; }
InputAddress.QuadPart += InputBytes.QuadPart;
if (InputAddress.QuadPart + InputBytes.QuadPart > StartAddress.QuadPart + NumberOfBytes.QuadPart) {
InputBytes.QuadPart = StartAddress.QuadPart + NumberOfBytes.QuadPart - InputAddress.QuadPart; } }
if (OverrideCount != 0 && i > OverrideCount) { break; }
p += 1; } ExFreePool (Ranges); DbgPrint ("Buggy: MmMarkPhysicalMemory Ecc BAD test finished\n"); } }
////////////////////////////////////////////////////////////////////////////
typedef struct { LIST_ENTRY List; PVOID ChunkPointers[ ( 63 * 1024 ) / sizeof( PVOID ) ]; } ALLOCATION_TABLE, *PALLOCATION_TABLE;
LIST_ENTRY PagedPoolAllocationListHead; LIST_ENTRY NonPagedPoolAllocationListHead; LIST_ENTRY SessionPoolAllocationListHead;
const SIZE_T PoolChunkSize = 64 * 1024 - 32;
//
//
//
VOID TdpWriteSignature( PVOID Allocation, SIZE_T CurrentSize ) { PSIZE_T CrtSignature; SIZE_T CrtSignatureValue;
CrtSignature = (PSIZE_T)Allocation; CrtSignatureValue = ( (SIZE_T)Allocation ) ^ CurrentSize;
if( CurrentSize > 100 * 1024 * 1024 ) { DbgPrint( "Buggy: Writing signature %p from address %p, size %p\n", CrtSignatureValue, CrtSignature, CurrentSize ); }
while( 100 * PAGE_SIZE <= CurrentSize ) { *CrtSignature = CrtSignatureValue;
CrtSignatureValue +=1;
CrtSignature = (PSIZE_T)( (PCHAR)CrtSignature + 100 * PAGE_SIZE ); CurrentSize -= 100 * PAGE_SIZE; } }
//
//
//
VOID TdpVerifySignature( PVOID Allocation, SIZE_T CurrentSize ) { PSIZE_T CrtSignature; SIZE_T CrtSignatureValue;
CrtSignature = (PSIZE_T)Allocation; CrtSignatureValue = ( (SIZE_T)Allocation ) ^ CurrentSize;
if( CurrentSize > 100 * 1024 * 1024 ) { DbgPrint( "Buggy: Verifying signature %p from address %p, size %p\n", CrtSignatureValue, CrtSignature, CurrentSize ); }
while( 100 * PAGE_SIZE <= CurrentSize ) { if( *CrtSignature != CrtSignatureValue ) { DbgPrint ("Buggy: Signature at %p is incorrect, expected %p, base allocation %p\n", CrtSignature, CrtSignatureValue, Allocation );
DbgBreakPoint (); }
CrtSignatureValue +=1; CrtSignature = (PSIZE_T)( (PCHAR)CrtSignature + 100 * PAGE_SIZE ); CurrentSize -= 100 * PAGE_SIZE; } }
//
//
//
VOID TdpCleanupPoolAllocationTable( PLIST_ENTRY ListHead, SIZE_T Allocations ) { PLIST_ENTRY NextEntry; PALLOCATION_TABLE AllocationTable; SIZE_T ChunksPerAllocationEntry; SIZE_T CrtChunksIndex;
ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationTable->ChunkPointers );
NextEntry = ListHead->Flink;
while( NextEntry != ListHead ) { RemoveEntryList( NextEntry );
AllocationTable = CONTAINING_RECORD( NextEntry, ALLOCATION_TABLE, List );
DbgPrint( "Buggy: Current allocation table = %p\n", AllocationTable );
for( CrtChunksIndex = 0; CrtChunksIndex < ChunksPerAllocationEntry; CrtChunksIndex++ ) { if( 0 == Allocations ) { //
// Freed them all
//
break; } else { Allocations -= 1;
if( 0 == Allocations % 0x100 ) { //
// Let the user know that we are still working on something
//
DbgPrint( "Buggy: cleaning up allocation index %p\n", Allocations ); }
/*
DbgPrint( "Buggy: Verify and free chunk index %p (from the end) at address %p\n", Allocations, AllocationTable->ChunkPointers[ CrtChunksIndex ] ); */
TdpVerifySignature( AllocationTable->ChunkPointers[ CrtChunksIndex ], PoolChunkSize );
ExFreePoolWithTag( AllocationTable->ChunkPointers[ CrtChunksIndex ], TD_POOL_TAG ); } }
//
// Free the table as well
//
ExFreePoolWithTag( AllocationTable, TD_POOL_TAG );
//
// Go to the next allocations table
//
NextEntry = ListHead->Flink; }
//
// At this point, Allocations should be zero and the
// list should be empty
//
if( 0 != Allocations ) { DbgPrint ("Buggy: Emptied the allocation table list but still have %p allocations - this is a bug\n", Allocations );
DbgBreakPoint(); }
if( ! IsListEmpty( ListHead ) ) { DbgPrint ("Buggy: No allocations left but the list at %p is not empty yet - this is a bug\n", ListHead );
DbgBreakPoint(); } }
//
// Delay execution for a few seconds so we can get a chance to use
// !poolused, poolmon.exe, etc.
//
VOID TdpSleep( ULONG Seconds ) { LARGE_INTEGER Interval = {(ULONG)(-1000 * 1000 * 10), -1}; // One second.
DbgPrint( "Buggy: Sleeping for %u seconds\n", Seconds );
Interval.QuadPart *= Seconds;
KeDelayExecutionThread( KernelMode, FALSE, &Interval ); }
//
// Determine the maximum size of a block of paged pool currently available
//
VOID TdSysPagedPoolMaxTest( IN PVOID IrpAddress ) { SIZE_T CurrentSize; SIZE_T SizeIncrement; ULONG Increment; PVOID Allocation;
#ifdef _WIN64
CurrentSize = 0xFFFFFFFF00000000;
#else
CurrentSize = 0xFFFFFFFF;
#endif //#ifdef _WIN64
do { DbgPrint ("Buggy: Trying to allocate %p bytes paged pool\n", CurrentSize );
Allocation = ExAllocatePoolWithTag( PagedPool, CurrentSize, TD_POOL_TAG );
if( NULL != Allocation ) { DbgPrint ("Buggy: allocated %p bytes paged pool at %p\n", CurrentSize, Allocation);
TdpWriteSignature( Allocation, CurrentSize );
TdpVerifySignature( Allocation, CurrentSize );
ExFreePoolWithTag( Allocation, TD_POOL_TAG ); } else { CurrentSize /= 2; } } while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
if( NULL != Allocation ) { //
// Try to find an even bigger size in 10% increments
//
SizeIncrement = CurrentSize / 10;
if( PAGE_SIZE <= SizeIncrement ) { for( Increment = 0; Increment < 10; Increment += 1 ) { CurrentSize += SizeIncrement;
DbgPrint ("Buggy: Trying to allocate %p bytes paged pool\n", CurrentSize );
Allocation = ExAllocatePoolWithTag( PagedPool, CurrentSize, TD_POOL_TAG );
if( NULL != Allocation ) { DbgPrint ("Buggy: Better result of the test: allocated %p bytes paged pool at %p\n", CurrentSize, Allocation);
TdpSleep( 15 );
TdpWriteSignature( Allocation, CurrentSize ); TdpVerifySignature( Allocation, CurrentSize );
ExFreePoolWithTag( Allocation, TD_POOL_TAG ); } else { DbgPrint ("Buggy: could not allocate %p bytes paged pool - done\n", CurrentSize );
break; } } } } }
//
// Determine the total size of the paged pool currently available (64 Kb - 32 bytes blocks)
//
VOID TdSysPagedPoolTotalTest( IN PVOID IrpAddress ) { SIZE_T CurrentChunkIndex; SIZE_T ChunksPerAllocationEntry; SIZE_T TotalBytes; PALLOCATION_TABLE AllocationListEntry; PVOID Allocation;
//
// No allocations yet
//
InitializeListHead( &PagedPoolAllocationListHead );
//
// We want to allocate 64 k chunks but leave space for the pool block header
//
ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
CurrentChunkIndex = 0;
do { if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// Need a new allocation entry structure
//
AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag( PagedPool, sizeof( ALLOCATION_TABLE ), TD_POOL_TAG );
if( NULL == AllocationListEntry ) { DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" ); break; }
RtlZeroMemory( AllocationListEntry, sizeof( ALLOCATION_TABLE ) );
DbgPrint( "Buggy: New allocation table = %p\n", AllocationListEntry ); } //
// Try to allocate a new chunk
//
Allocation = ExAllocatePoolWithTag( PagedPool, PoolChunkSize, TD_POOL_TAG );
if( NULL == Allocation ) { DbgPrint ("Buggy: could not allocate paged pool chunk index %p - done\n", CurrentChunkIndex );
if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// We are using a new list entry - free it now because
// we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
//
ExFreePoolWithTag( AllocationListEntry, TD_POOL_TAG ); } } else { if( 0 == CurrentChunkIndex % 0x100 ) { //
// Let the user know that we are still working on something
//
DbgPrint( "Buggy: Allocated pool chunk index = %p\n", CurrentChunkIndex ); }
if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// We are using a new list entry - add it to our list only now because
// we don't want to have empty tables in the list so we didn't insert it yet
//
InsertTailList( &PagedPoolAllocationListHead, &AllocationListEntry->List ); }
AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
TdpWriteSignature( Allocation, PoolChunkSize );
/*
DbgPrint( "Buggy: Written signature to chunk index %p at address %p\n", CurrentChunkIndex, Allocation ); */
CurrentChunkIndex += 1; } } while( NULL != Allocation );
TotalBytes = CurrentChunkIndex * 64 * 1024;
DbgPrint ("Buggy: Result of the test: approx. %p total bytes of paged pool allocated\n", TotalBytes );
//
// Clean-up what we have allocated
//
TdpCleanupPoolAllocationTable( &PagedPoolAllocationListHead, CurrentChunkIndex ); }
VOID TdNonPagedPoolMaxTest( IN PVOID IrpAddress ) { SIZE_T CurrentSize; SIZE_T SizeIncrement; ULONG Increment; PVOID Allocation;
#ifdef _WIN64
CurrentSize = 0xFFFFFFFF00000000;
#else
CurrentSize = 0xFFFFFFFF;
#endif //#ifdef _WIN64
do { DbgPrint ("Buggy: Trying to allocate %p bytes non-paged pool\n", CurrentSize );
Allocation = ExAllocatePoolWithTag( NonPagedPool, CurrentSize, TD_POOL_TAG );
if( NULL != Allocation ) { DbgPrint ("Buggy: allocated %p bytes non-paged pool at %p\n", CurrentSize, Allocation);
TdpWriteSignature( Allocation, CurrentSize );
ExFreePoolWithTag( Allocation, TD_POOL_TAG ); } else { CurrentSize /= 2; } } while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
if( NULL != Allocation ) { //
// Try to find an even bigger size in 10% increments
//
SizeIncrement = CurrentSize / 10;
if( PAGE_SIZE <= SizeIncrement ) { for( Increment = 0; Increment < 10; Increment += 1 ) { CurrentSize += SizeIncrement;
DbgPrint ("Buggy: Trying to allocate %p bytes non-paged pool\n", CurrentSize );
Allocation = ExAllocatePoolWithTag( NonPagedPool, CurrentSize, TD_POOL_TAG );
if( NULL != Allocation ) { DbgPrint ("Buggy: Better result of the test: allocated %p bytes non-paged pool at %p\n", CurrentSize, Allocation);
TdpSleep( 15 );
TdpWriteSignature( Allocation, CurrentSize );
TdpVerifySignature( Allocation, CurrentSize );
ExFreePoolWithTag( Allocation, TD_POOL_TAG ); } else { DbgPrint ("Buggy: could not allocate %p bytes non-paged pool - done\n", CurrentSize );
break; } } } } }
//
// Determine the total size of the non-paged pool currently available (64 Kb - 32 bytes blocks)
//
VOID TdNonPagedPoolTotalTest( IN PVOID IrpAddress ) { SIZE_T CurrentChunkIndex; SIZE_T ChunksPerAllocationEntry; SIZE_T TotalBytes; PALLOCATION_TABLE AllocationListEntry; PVOID Allocation;
//
// No allocations yet
//
InitializeListHead( &NonPagedPoolAllocationListHead );
//
// We want to allocate 64 k chunks but leave space for the pool block header
//
ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
CurrentChunkIndex = 0;
do { if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// Need a new allocation entry structure
//
AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag( PagedPool, sizeof( ALLOCATION_TABLE ), TD_POOL_TAG );
if( NULL == AllocationListEntry ) { DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" ); break; } } //
// Try to allocate a new chunk
//
Allocation = ExAllocatePoolWithTag( NonPagedPool, PoolChunkSize, TD_POOL_TAG );
if( NULL == Allocation ) { DbgPrint ("Buggy: could not allocate non-paged pool chunk index %p - done\n", CurrentChunkIndex );
if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// We are using a new list entry - free it now because
// we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
//
ExFreePoolWithTag( AllocationListEntry, TD_POOL_TAG ); } } else { if( 0 == CurrentChunkIndex % 0x100 ) { //
// Let the user know that we are still working on something
//
DbgPrint( "Buggy: Allocated pool chunk index = %p\n", CurrentChunkIndex ); }
if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// We are using a new list entry - add it to our list only now because
// we don't want to have empty tables in the list so we didn't insert it yet
//
InsertTailList( &NonPagedPoolAllocationListHead, &AllocationListEntry->List ); }
AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
TdpWriteSignature( Allocation, PoolChunkSize );
CurrentChunkIndex += 1; } } while( NULL != Allocation );
TotalBytes = CurrentChunkIndex * 64 * 1024;
DbgPrint ("Buggy: Result of the test: approx. %p total bytes of non-paged pool allocated\n", TotalBytes );
//
// Clean-up what we have allocated
//
TdpCleanupPoolAllocationTable( &NonPagedPoolAllocationListHead, CurrentChunkIndex ); }
/////////////////////////////////////////////////////////////////////////////////////
typedef struct { LIST_ENTRY List; PMDL Mappings[ ( 63 * 1024 ) / sizeof( PMDL ) ]; } MAPPING_TABLE_ENTRY, *PMAPPING_TABLE_ENTRY;
LIST_ENTRY IoMappingsListHead;
ULONG BytesPerIoMapping = 1024 * 1024;
//
//
//
VOID TdpCleanupMappingsAllocationTable( PLIST_ENTRY ListHead, SIZE_T Mappings ) { PLIST_ENTRY NextEntry; PMAPPING_TABLE_ENTRY MappingTableEntry; SIZE_T MappingsPerMappingTableEntry; SIZE_T CrtMappingIndex;
MappingsPerMappingTableEntry = ARRAY_LENGTH( MappingTableEntry->Mappings );
NextEntry = ListHead->Flink;
while( NextEntry != ListHead ) { RemoveEntryList( NextEntry );
MappingTableEntry = CONTAINING_RECORD( NextEntry, MAPPING_TABLE_ENTRY, List );
for( CrtMappingIndex = 0; CrtMappingIndex < MappingsPerMappingTableEntry; CrtMappingIndex++ ) { if( 0 == Mappings ) { //
// Freed them all
//
break; } else { Mappings -= 1;
if( 0 == Mappings % 0x100 ) { //
// Let the user know that we are still working on something
//
DbgPrint( "Buggy: cleaning up mapping index %p\n", Mappings ); }
//
// Unmap
//
MmUnmapIoSpace( MappingTableEntry->Mappings[ CrtMappingIndex ], BytesPerIoMapping ); } }
//
// Free the table as well
//
ExFreePoolWithTag( MappingTableEntry, TD_POOL_TAG );
//
// Go to the next allocations table
//
NextEntry = ListHead->Flink; }
//
// At this point, Mappings should be zero and the
// list should be empty
//
if( 0 != Mappings ) { DbgPrint ("Buggy: Emptied the mappings table list but still have %p allocations - this is a bug\n", Mappings );
DbgBreakPoint(); }
if( ! IsListEmpty( ListHead ) ) { DbgPrint ("Buggy: No mappings left but the list at %p is not empty yet - this is a bug\n", ListHead );
DbgBreakPoint(); } }
//
// Determine the total amount of memory that can be mapped using system PTEs (1 Mb chunks)
//
VOID TdFreeSystemPtesTest( IN PVOID IrpAddress ) { ULONG MemType; PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS MyPhysicalAddress; SIZE_T CurrentMappingIndex; SIZE_T MappingsPerMappingTableEntry; SIZE_T TotalBytes; PVOID NewMapping; PMAPPING_TABLE_ENTRY MappingTableEntry; PMDL NewMdl; NTSTATUS Status;
//
// Use some joystick port address
//
MemType = 1; // IO space
PortAddress.LowPart = 0x200; PortAddress.HighPart = 0;
HalTranslateBusAddress( Isa, 0, PortAddress, &MemType, &MyPhysicalAddress);
//
// No Mappings allocated yet
//
InitializeListHead( &IoMappingsListHead );
//
// Map a ~64 Kb chunk over and over again to consume system PTEs
//
MappingsPerMappingTableEntry = ARRAY_LENGTH( MappingTableEntry->Mappings );
CurrentMappingIndex = 0;
do { if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry ) { //
// Need a new allocation entry structure
//
MappingTableEntry = (PMAPPING_TABLE_ENTRY) ExAllocatePoolWithTag( PagedPool, sizeof( MAPPING_TABLE_ENTRY ), TD_POOL_TAG );
if( NULL == MappingTableEntry ) { DbgPrint ("Buggy: could not allocate new MAPPING_TABLE_ENTRY - aborting test here\n" ); break; } }
NewMapping = MmMapIoSpace( MyPhysicalAddress, BytesPerIoMapping, MmNonCached );
if( NULL == NewMapping ) { DbgPrint ("Buggy: could not create mapping index %p\n", CurrentMappingIndex );
if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry ) { //
// We are using a new list entry - free it now because
// we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
//
ExFreePoolWithTag( MappingTableEntry, TD_POOL_TAG ); } } else { //DbgPrint ("Buggy: created Mapping index %p at address %p\n",
// CurrentMappingIndex,
// NewMapping );
if( 0 == CurrentMappingIndex % 0x100 ) { //
// Let the user know that we are still working on something
//
DbgPrint( "Buggy: mapped chunk index = %p\n", CurrentMappingIndex ); }
if( 0 == CurrentMappingIndex % MappingsPerMappingTableEntry ) { //
// We are using a new list entry - add it to our list only now because
// we don't want to have empty tables in the list so we didn't insert it yet
//
InsertTailList( &IoMappingsListHead, &MappingTableEntry->List ); }
MappingTableEntry->Mappings[ CurrentMappingIndex % MappingsPerMappingTableEntry ] = NewMapping;
CurrentMappingIndex += 1; } } while( NULL != NewMapping );
TotalBytes = CurrentMappingIndex * BytesPerIoMapping;
DbgPrint( "Buggy: Result of the test: %p total bytes mapped\n", TotalBytes );
//
// Clean-up what we have allocated and locked
//
TdpCleanupMappingsAllocationTable( &IoMappingsListHead, CurrentMappingIndex ); }
//
// Function:
//
// GetTag
//
// Description:
//
// This function transforms an integer into a four letter
// string. This is useful for the pool tag dynamic table
// in order to populate it with many different tags.
//
ULONG GetTag ( ULONG Index ) { UCHAR Value[4];
Value[0] = (UCHAR)(((Index & 0x000F) >> 0 )) + 'A'; Value[1] = (UCHAR)(((Index & 0x00F0) >> 4 )) + 'A'; Value[2] = (UCHAR)(((Index & 0x0F00) >> 8 )) + 'A'; Value[3] = (UCHAR)(((Index & 0xF000) >> 12)) + 'A';
return *((PULONG)Value); }
VOID StressPoolFlag ( PVOID NotUsed ) /*++
Routine Description:
This function iterates through all the pool types, pool flags and pool sizes (1 .. 8 * PAGE_SIZE).
Arguments:
None.
Return Value:
None.
Environment:
Kernel mode.
--*/
{ POOL_TYPE PoolType; SIZE_T NumberOfBytes; EX_POOL_PRIORITY Priority; PVOID Va; ULONG i;
for (PoolType = NonPagedPool; PoolType < 0xff; PoolType += 1) { for (Priority = LowPoolPriority; Priority < LowPoolPriority + 2; Priority += 1) { for (i = 1; i < 8 * PAGE_SIZE; i += 1) {
NumberOfBytes = i;
if (PoolType & 0x40) { break; }
if ((NumberOfBytes > PAGE_SIZE) && (PoolType & 0x2)) { break; }
try { Va = ExAllocatePoolWithTagPriority ( PoolType, NumberOfBytes, 'ZXCV', Priority); } except (EXCEPTION_EXECUTE_HANDLER) {
if (Verbosity & VERBOSITY_PRINT) { DbgPrint( "buggy: ExAllocatePool exceptioned %x %x %x\n", PoolType, NumberOfBytes, Priority); }
if (Verbosity & VERBOSITY_BREAK) { DbgBreakPoint (); }
Va = NULL; }
if (Va) { ExFreePool (Va); } else { if (Verbosity & VERBOSITY_PRINT) { DbgPrint( "buggy: ExAllocatePool failed %x %x %x\n", PoolType, NumberOfBytes, Priority); } if (Verbosity & VERBOSITY_BREAK) { DbgBreakPoint (); } } } } }
DbgPrint ("Buggy: ExAllocatePoolFlag test finished\n"); }
VOID StressPoolTagTableExtension ( PVOID NotUsed ) /*++
Routine Description:
This function stresses the pool tag table dynamic extension.
Arguments:
None.
Return Value:
None.
Environment:
Kernel mode.
--*/
{ PVOID * Blocks; ULONG Index;
Blocks = ExAllocatePoolWithTag ( NonPagedPool, 16384 * sizeof(PVOID), 'tguB');
if (Blocks == NULL) { DbgPrint ("Buggy: cannot allocate pool buffer\n"); } else {
//
// Loop with 8 byte size.
//
for (Index = 0; Index < 10000; Index++) {
if (Index && Index % 100 == 0) { DbgPrint ("Index(a): %u \n", Index); }
Blocks[Index] = ExAllocatePoolWithTag ( NonPagedPool, 8, GetTag(Index)); }
for (Index = 0; Index < 10000; Index++) {
if (Index && Index % 100 == 0) { DbgPrint ("Index(f): %u \n", Index); }
if (Blocks[Index]) { ExFreePool (Blocks[Index]); } }
//
// Loop with PAGE_SIZE byte size.
//
for (Index = 0; Index < 4000; Index++) {
if (Index && Index % 100 == 0) { DbgPrint ("Index(A): %u \n", Index); }
Blocks[Index] = ExAllocatePoolWithTag ( NonPagedPool, PAGE_SIZE, GetTag(Index + 16384)); }
for (Index = 0; Index < 4000; Index++) {
if (Index && Index % 100 == 0) { DbgPrint ("Index(F): %u \n", Index); }
if (Blocks[Index]) { ExFreePool (Blocks[Index]); } }
//
// Free block info.
//
ExFreePool (Blocks); } }
//
// Determine the maximum size of a block of session pool currently available
//
VOID TdSessionPoolMaxTest( IN PVOID IrpAddress ) { SIZE_T CurrentSize; SIZE_T SizeIncrement; ULONG Increment; PVOID Allocation;
#ifdef _WIN64
CurrentSize = 0xFFFFFFFF00000000;
#else
CurrentSize = 0xFFFFFFFF;
#endif //#ifdef _WIN64
do { DbgPrint ("Buggy: Trying to allocate %p bytes session pool\n", CurrentSize );
Allocation = ExAllocatePoolWithTag( PagedPool | SESSION_POOL_MASK, CurrentSize, TD_POOL_TAG );
if( NULL != Allocation ) { DbgPrint ("Buggy: allocated %p bytes session pool at %p\n", CurrentSize, Allocation);
TdpWriteSignature( Allocation, CurrentSize );
ExFreePoolWithTag( Allocation, TD_POOL_TAG ); } else { CurrentSize /= 2; } } while( NULL == Allocation && PAGE_SIZE <= CurrentSize );
if( NULL != Allocation ) { //
// Try to find an even bigger size in 10% increments
//
SizeIncrement = CurrentSize / 10;
if( PAGE_SIZE <= SizeIncrement ) { for( Increment = 0; Increment < 10; Increment += 1 ) { CurrentSize += SizeIncrement;
DbgPrint ("Buggy: Trying to allocate %p bytes session pool\n", CurrentSize );
Allocation = ExAllocatePoolWithTag( PagedPool | SESSION_POOL_MASK, CurrentSize, TD_POOL_TAG );
if( NULL != Allocation ) { DbgPrint ("Buggy: Better result of the test: allocated %p bytes sesssion pool at %p\n", CurrentSize, Allocation);
TdpSleep( 15 );
TdpWriteSignature( Allocation, CurrentSize ); TdpVerifySignature( Allocation, CurrentSize );
ExFreePoolWithTag( Allocation, TD_POOL_TAG ); } else { DbgPrint ("Buggy: could not allocate %p bytes session pool - done\n", CurrentSize );
break; } } } } }
//
// Determine the total size of the session pool currently available (64 Kb - 32 bytes blocks)
//
VOID TdSessionPoolTotalTest( IN PVOID IrpAddress ) { SIZE_T CurrentChunkIndex; SIZE_T ChunksPerAllocationEntry; SIZE_T TotalBytes; PALLOCATION_TABLE AllocationListEntry; PVOID Allocation;
//
// No allocations yet
//
InitializeListHead( &SessionPoolAllocationListHead );
//
// We want to allocate 64 k chunks but leave space for the pool block header
//
ChunksPerAllocationEntry = ARRAY_LENGTH( AllocationListEntry->ChunkPointers );
CurrentChunkIndex = 0;
do { if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// Need a new allocation entry structure
//
AllocationListEntry = (PALLOCATION_TABLE) ExAllocatePoolWithTag( PagedPool | SESSION_POOL_MASK, sizeof( ALLOCATION_TABLE ), TD_POOL_TAG );
if( NULL == AllocationListEntry ) { DbgPrint ("Buggy: could not allocate new ALLOCATION_TABLE - aborting test here\n" ); break; }
RtlZeroMemory( AllocationListEntry, sizeof( ALLOCATION_TABLE ) );
DbgPrint( "Buggy: New allocation table = %p\n", AllocationListEntry ); } //
// Try to allocate a new chunk
//
Allocation = ExAllocatePoolWithTag( PagedPool | SESSION_POOL_MASK, PoolChunkSize, TD_POOL_TAG );
if( NULL == Allocation ) { DbgPrint ("Buggy: could not allocate session pool chunk index %p - done\n", CurrentChunkIndex );
if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// We are using a new list entry - free it now because
// we don't want to have empty tables in the list so we didn't insert it yet so we didn't insert it yet
//
ExFreePoolWithTag( AllocationListEntry, TD_POOL_TAG ); } } else { if( 0 == CurrentChunkIndex % 0x100 ) { //
// Let the user know that we are still working on something
//
DbgPrint( "Buggy: Allocated pool chunk index = %p\n", CurrentChunkIndex ); }
if( 0 == CurrentChunkIndex % ChunksPerAllocationEntry ) { //
// We are using a new list entry - add it to our list only now because
// we don't want to have empty tables in the list so we didn't insert it yet
//
InsertTailList( &SessionPoolAllocationListHead, &AllocationListEntry->List ); }
AllocationListEntry->ChunkPointers[ CurrentChunkIndex % ChunksPerAllocationEntry ] = Allocation;
TdpWriteSignature( Allocation, PoolChunkSize );
/*
DbgPrint( "Buggy: Written signature to chunk index %p at address %p\n", CurrentChunkIndex, Allocation ); */
CurrentChunkIndex += 1; } } while( NULL != Allocation );
TotalBytes = CurrentChunkIndex * 64 * 1024;
DbgPrint ("Buggy: Result of the test: approx. %p total bytes of session pool allocated\n", TotalBytes );
//
// Clean-up what we have allocated
//
TdpCleanupPoolAllocationTable( &SessionPoolAllocationListHead, CurrentChunkIndex ); }
//
//
//
#define BUGGY_PAGE_DIRECTORY_BOUNDARY ((PVOID)0x40000000)
#define BUGGY_VAD_GRANULARITY (64 * 1024)
#if defined( _IA64_ )
#define BUGGY_PDE_GRANULARITY (8 * 1024 * 1024)
#elif defined( _AMD64_ )
#define BUGGY_PDE_GRANULARITY (2 * 1024 * 1024)
#else
#define BUGGY_PDE_GRANULARITY (4 * 1024 * 1024)
#endif
typedef struct _BUGGY_PAGEDPOOLMDLTEST {
PVOID RequestedUserVa; PMDL Mdl; PVOID MappedAddress; ULONG NumberOfPages;
} BUGGY_PAGEDPOOLMDLTEST, *PBUGGY_PAGEDPOOLMDLTEST;
BUGGY_PAGEDPOOLMDLTEST PagedPoolMdlTestArray [] = { {BUGGY_PAGE_DIRECTORY_BOUNDARY, NULL, NULL, 3}, {(PCHAR)BUGGY_PAGE_DIRECTORY_BOUNDARY + BUGGY_VAD_GRANULARITY, NULL, NULL, 3}, {(PCHAR)BUGGY_PAGE_DIRECTORY_BOUNDARY - BUGGY_VAD_GRANULARITY, NULL, NULL, 3}, {(PCHAR)BUGGY_PAGE_DIRECTORY_BOUNDARY + BUGGY_PDE_GRANULARITY - BUGGY_VAD_GRANULARITY, NULL, NULL, (2 * BUGGY_VAD_GRANULARITY) / PAGE_SIZE} };
VOID TdNonPagedPoolMdlTestMap( IN PVOID IrpAddress ) { PVOID VirtualAddress; ULONG MapIndex; ULONG SizeToMap;
#if defined( _IA64_ )
//
// IA64
//
// 0xe0000168`02000000 maps NonCached 0x800 pages starting with PFN 0x78000 on dmihai-ita.
//
VirtualAddress = (PVOID)0xe000016802000000; #elif defined( _AMD64_ )
//
// AMD64
//
// 0xfffffadf`f0a91000 maps WriteCombined 0x100 pages starting with PFN 0xd0200 on dmihai-amd64.
//
//VirtualAddress = (PVOID)0xffffffffffd00000;
VirtualAddress = (PVOID)0xfffffadff0a91000; #else
//
// X86
//
// f1000000 maps NonChached 0x800 pages starting with PFN f5000 on dmihai-amd.
//
VirtualAddress = (PVOID)0xf1000000; #endif
for (MapIndex = 0 ; MapIndex < ARRAY_LENGTH (PagedPoolMdlTestArray); MapIndex += 1) { //
//
//
SizeToMap = PAGE_SIZE * PagedPoolMdlTestArray [MapIndex].NumberOfPages;
PagedPoolMdlTestArray [MapIndex].Mdl = IoAllocateMdl (VirtualAddress, SizeToMap, FALSE, FALSE, NULL);
if (PagedPoolMdlTestArray [MapIndex].Mdl == NULL) { DbgPrint ("IoAllocateMdl failed\n"); return; }
DbgPrint ("Mdl %p allocated\n", PagedPoolMdlTestArray [MapIndex].Mdl);
//
//
//
MmBuildMdlForNonPagedPool (PagedPoolMdlTestArray [MapIndex].Mdl);
//
//
//
/*
UserVANonPagedPoolMdlTest = MmMapLockedPages (MdlNonPagedPoolMdlTest, UserMode); */
PagedPoolMdlTestArray [MapIndex].MappedAddress = MmMapLockedPagesSpecifyCache ( PagedPoolMdlTestArray [MapIndex].Mdl, UserMode, MmNonCached, PagedPoolMdlTestArray [MapIndex].RequestedUserVa, FALSE, HighPagePriority);
DbgPrint ("Mapped %p bytes at address %p\n", SizeToMap, PagedPoolMdlTestArray [MapIndex].MappedAddress); }
//DbgBreakPoint ();
}
VOID TdNonPagedPoolMdlTestUnMap( IN PVOID IrpAddress ) { ULONG MapIndex;
for (MapIndex = 0 ; MapIndex < ARRAY_LENGTH (PagedPoolMdlTestArray); MapIndex += 1) { if (PagedPoolMdlTestArray [MapIndex].MappedAddress != NULL) { //
// Unmap
//
MmUnmapLockedPages (PagedPoolMdlTestArray [MapIndex].MappedAddress, PagedPoolMdlTestArray [MapIndex].Mdl);
PagedPoolMdlTestArray [MapIndex].MappedAddress = NULL; }
if (PagedPoolMdlTestArray [MapIndex].Mdl != NULL) { //
// Free Mdl
//
IoFreeMdl (PagedPoolMdlTestArray [MapIndex].Mdl);
PagedPoolMdlTestArray [MapIndex].Mdl = NULL; } } }
#endif // #if !MMTESTS_ACTIVE
//
// End of file
//
|