Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

verifier.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 verifier.c 00008 00009 Abstract: 00010 00011 This module contains the routines to verify system drivers. 00012 00013 Author: 00014 00015 Landy Wang (landyw) 3-Sep-1998 00016 00017 Revision History: 00018 00019 --*/ 00020 #include "mi.h" 00021 00022 #define THUNKED_API 00023 00024 THUNKED_API 00025 PVOID 00026 VerifierAllocatePool( 00027 IN POOL_TYPE PoolType, 00028 IN SIZE_T NumberOfBytes 00029 ); 00030 00031 THUNKED_API 00032 PVOID 00033 VerifierAllocatePoolWithTag( 00034 IN POOL_TYPE PoolType, 00035 IN SIZE_T NumberOfBytes, 00036 IN ULONG Tag 00037 ); 00038 00039 THUNKED_API 00040 PVOID 00041 VerifierAllocatePoolWithQuotaTag( 00042 IN POOL_TYPE PoolType, 00043 IN SIZE_T NumberOfBytes, 00044 IN ULONG Tag 00045 ); 00046 00047 THUNKED_API 00048 PVOID 00049 VerifierAllocatePoolWithTagPriority( 00050 IN POOL_TYPE PoolType, 00051 IN SIZE_T NumberOfBytes, 00052 IN ULONG Tag, 00053 IN EX_POOL_PRIORITY Priority 00054 ); 00055 00056 PVOID 00057 VeAllocatePoolWithTagPriority( 00058 IN POOL_TYPE PoolType, 00059 IN SIZE_T NumberOfBytes, 00060 IN ULONG Tag, 00061 IN EX_POOL_PRIORITY Priority, 00062 IN PVOID CallingAddress 00063 ); 00064 00065 VOID 00066 VerifierFreePool( 00067 IN PVOID P 00068 ); 00069 00070 THUNKED_API 00071 VOID 00072 VerifierFreePoolWithTag( 00073 IN PVOID P, 00074 IN ULONG TagToFree 00075 ); 00076 00077 THUNKED_API 00078 LONG 00079 VerifierSetEvent( 00080 IN PRKEVENT Event, 00081 IN KPRIORITY Increment, 00082 IN BOOLEAN Wait 00083 ); 00084 00085 THUNKED_API 00086 KIRQL 00087 FASTCALL 00088 VerifierKfRaiseIrql ( 00089 IN KIRQL NewIrql 00090 ); 00091 00092 THUNKED_API 00093 VOID 00094 FASTCALL 00095 VerifierKfLowerIrql ( 00096 IN KIRQL NewIrql 00097 ); 00098 00099 THUNKED_API 00100 VOID 00101 VerifierKeRaiseIrql ( 00102 IN KIRQL NewIrql, 00103 OUT PKIRQL OldIrql 00104 ); 00105 00106 THUNKED_API 00107 VOID 00108 VerifierKeLowerIrql ( 00109 IN KIRQL NewIrql 00110 ); 00111 00112 THUNKED_API 00113 VOID 00114 VerifierKeAcquireSpinLock ( 00115 IN PKSPIN_LOCK SpinLock, 00116 OUT PKIRQL OldIrql 00117 ); 00118 00119 THUNKED_API 00120 VOID 00121 VerifierKeReleaseSpinLock ( 00122 IN PKSPIN_LOCK SpinLock, 00123 IN KIRQL NewIrql 00124 ); 00125 00126 THUNKED_API 00127 KIRQL 00128 FASTCALL 00129 VerifierKfAcquireSpinLock ( 00130 IN PKSPIN_LOCK SpinLock 00131 ); 00132 00133 THUNKED_API 00134 VOID 00135 FASTCALL 00136 VerifierKfReleaseSpinLock ( 00137 IN PKSPIN_LOCK SpinLock, 00138 IN KIRQL NewIrql 00139 ); 00140 00141 THUNKED_API 00142 VOID 00143 VerifierKeInitializeTimerEx( 00144 IN PKTIMER Timer, 00145 IN TIMER_TYPE Type 00146 ); 00147 00148 THUNKED_API 00149 VOID 00150 VerifierKeInitializeTimer( 00151 IN PKTIMER Timer 00152 ); 00153 00154 THUNKED_API 00155 BOOLEAN 00156 FASTCALL 00157 VerifierExTryToAcquireFastMutex ( 00158 IN PFAST_MUTEX FastMutex 00159 ); 00160 00161 THUNKED_API 00162 VOID 00163 FASTCALL 00164 VerifierExAcquireFastMutex ( 00165 IN PFAST_MUTEX FastMutex 00166 ); 00167 00168 THUNKED_API 00169 VOID 00170 FASTCALL 00171 VerifierExReleaseFastMutex ( 00172 IN PFAST_MUTEX FastMutex 00173 ); 00174 00175 THUNKED_API 00176 VOID 00177 FASTCALL 00178 VerifierExAcquireFastMutexUnsafe ( 00179 IN PFAST_MUTEX FastMutex 00180 ); 00181 00182 THUNKED_API 00183 VOID 00184 FASTCALL 00185 VerifierExReleaseFastMutexUnsafe ( 00186 IN PFAST_MUTEX FastMutex 00187 ); 00188 00189 THUNKED_API 00190 BOOLEAN 00191 VerifierExAcquireResourceExclusive( 00192 IN PERESOURCE Resource, 00193 IN BOOLEAN Wait 00194 ); 00195 00196 THUNKED_API 00197 VOID 00198 FASTCALL 00199 VerifierExReleaseResource( 00200 IN PERESOURCE Resource 00201 ); 00202 00203 THUNKED_API 00204 KIRQL 00205 FASTCALL 00206 VerifierKeAcquireQueuedSpinLock ( 00207 IN KSPIN_LOCK_QUEUE_NUMBER Number 00208 ); 00209 00210 THUNKED_API 00211 VOID 00212 FASTCALL 00213 VerifierKeReleaseQueuedSpinLock ( 00214 IN KSPIN_LOCK_QUEUE_NUMBER Number, 00215 IN KIRQL OldIrql 00216 ); 00217 00218 THUNKED_API 00219 BOOLEAN 00220 VerifierSynchronizeExecution ( 00221 IN PKINTERRUPT Interrupt, 00222 IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, 00223 IN PVOID SynchronizeContext 00224 ); 00225 00226 THUNKED_API 00227 VOID 00228 VerifierProbeAndLockPages ( 00229 IN OUT PMDL MemoryDescriptorList, 00230 IN KPROCESSOR_MODE AccessMode, 00231 IN LOCK_OPERATION Operation 00232 ); 00233 00234 THUNKED_API 00235 VOID 00236 VerifierProbeAndLockProcessPages ( 00237 IN OUT PMDL MemoryDescriptorList, 00238 IN PEPROCESS Process, 00239 IN KPROCESSOR_MODE AccessMode, 00240 IN LOCK_OPERATION Operation 00241 ); 00242 00243 THUNKED_API 00244 VOID 00245 VerifierProbeAndLockSelectedPages ( 00246 IN OUT PMDL MemoryDescriptorList, 00247 IN PFILE_SEGMENT_ELEMENT SegmentArray, 00248 IN KPROCESSOR_MODE AccessMode, 00249 IN LOCK_OPERATION Operation 00250 ); 00251 00252 VOID 00253 VerifierUnlockPages ( 00254 IN OUT PMDL MemoryDescriptorList 00255 ); 00256 00257 VOID 00258 VerifierUnmapLockedPages ( 00259 IN PVOID BaseAddress, 00260 IN PMDL MemoryDescriptorList 00261 ); 00262 00263 VOID 00264 VerifierUnmapIoSpace ( 00265 IN PVOID BaseAddress, 00266 IN SIZE_T NumberOfBytes 00267 ); 00268 00269 THUNKED_API 00270 PVOID 00271 VerifierMapIoSpace ( 00272 IN PHYSICAL_ADDRESS PhysicalAddress, 00273 IN SIZE_T NumberOfBytes, 00274 IN MEMORY_CACHING_TYPE CacheType 00275 ); 00276 00277 THUNKED_API 00278 PVOID 00279 VerifierMapLockedPages ( 00280 IN PMDL MemoryDescriptorList, 00281 IN KPROCESSOR_MODE AccessMode 00282 ); 00283 00284 THUNKED_API 00285 PVOID 00286 VerifierMapLockedPagesSpecifyCache ( 00287 IN PMDL MemoryDescriptorList, 00288 IN KPROCESSOR_MODE AccessMode, 00289 IN MEMORY_CACHING_TYPE CacheType, 00290 IN PVOID RequestedAddress, 00291 IN ULONG BugCheckOnFailure, 00292 IN MM_PAGE_PRIORITY Priority 00293 ); 00294 00295 VOID 00296 VerifierFreeTrackedPool( 00297 IN PVOID VirtualAddress, 00298 IN SIZE_T ChargedBytes, 00299 IN LOGICAL CheckType, 00300 IN LOGICAL SpecialPool 00301 ); 00302 00303 VOID 00304 ViPrintString ( 00305 IN PUNICODE_STRING DriverName 00306 ); 00307 00308 LOGICAL 00309 ViInjectResourceFailure ( 00310 VOID 00311 ); 00312 00313 VOID 00314 ViTrimAllSystemPagableMemory ( 00315 VOID 00316 ); 00317 00318 VOID 00319 ViInitializeEntry ( 00320 IN PMI_VERIFIER_DRIVER_ENTRY Verifier, 00321 IN LOGICAL FirstLoad 00322 ); 00323 00324 LOGICAL 00325 ViReservePoolAllocation ( 00326 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 00327 ); 00328 00329 ULONG_PTR 00330 ViInsertPoolAllocation ( 00331 IN PMI_VERIFIER_DRIVER_ENTRY Verifier, 00332 IN PVOID VirtualAddress, 00333 IN PVOID CallingAddress, 00334 IN SIZE_T NumberOfBytes, 00335 IN ULONG Tag 00336 ); 00337 00338 VOID 00339 ViCancelPoolAllocation ( 00340 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 00341 ); 00342 00343 VOID 00344 ViReleasePoolAllocation ( 00345 IN PMI_VERIFIER_DRIVER_ENTRY Verifier, 00346 IN PVOID VirtualAddress, 00347 IN ULONG_PTR ListIndex, 00348 IN SIZE_T ChargedBytes 00349 ); 00350 00351 VOID 00352 KfSanityCheckRaiseIrql ( 00353 IN KIRQL NewIrql 00354 ); 00355 00356 VOID 00357 KfSanityCheckLowerIrql ( 00358 IN KIRQL NewIrql 00359 ); 00360 00361 MM_DRIVER_VERIFIER_DATA MmVerifierData; 00362 00363 // 00364 // Any flags which can be modified on the fly without rebooting are set here. 00365 // 00366 00367 ULONG VerifierModifyableOptions; 00368 ULONG VerifierOptionChanges; 00369 00370 LIST_ENTRY MiSuspectDriverList; 00371 00372 LOGICAL MiVerifyAllDrivers; 00373 00374 WCHAR MiVerifyRandomDrivers; 00375 00376 ULONG MiActiveVerifies; 00377 00378 ULONG MiActiveVerifierThunks; 00379 00380 ULONG MiNoPageOnRaiseIrql; 00381 00382 ULONG MiVerifierStackProtectTime; 00383 00384 LOGICAL MmDontVerifyRandomDrivers = TRUE; 00385 00386 LOGICAL VerifierSystemSufficientlyBooted; 00387 00388 LARGE_INTEGER VerifierRequiredTimeSinceBoot = {(ULONG)(40 * 1000 * 1000 * 10), 1}; 00389 00390 LOGICAL VerifierIsTrackingPool = FALSE; 00391 00392 KSPIN_LOCK VerifierListLock; 00393 00394 KSPIN_LOCK VerifierPoolLock; 00395 00396 FAST_MUTEX VerifierPoolMutex; 00397 00398 PRTL_BITMAP VerifierLargePagedPoolMap; 00399 00400 LIST_ENTRY MiVerifierDriverAddedThunkListHead; 00401 00402 extern LOGICAL MmSpecialPoolCatchOverruns; 00403 00404 LOGICAL KernelVerifier = FALSE; 00405 00406 ULONG KernelVerifierTickPage = 0x7; 00407 00408 LOGICAL 00409 MiEnableVerifier ( 00410 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 00411 ); 00412 00413 VOID 00414 ViInsertVerifierEntry ( 00415 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 00416 ); 00417 00418 PVOID 00419 ViPostPoolAllocation ( 00420 IN PVOID VirtualAddress, 00421 IN SIZE_T NumberOfBytes, 00422 IN POOL_TYPE PoolType, 00423 IN ULONG Tag, 00424 IN PVOID CallingAddress 00425 ); 00426 00427 PMI_VERIFIER_DRIVER_ENTRY 00428 ViLocateVerifierEntry ( 00429 IN PVOID SystemAddress 00430 ); 00431 00432 VOID 00433 MiVerifierCheckThunks ( 00434 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 00435 ); 00436 00437 #ifdef ALLOC_PRAGMA 00438 #pragma alloc_text(INIT,MiInitializeDriverVerifierList) 00439 #if defined(_X86_) 00440 #pragma alloc_text(INIT,MiEnableKernelVerifier) 00441 #endif 00442 #pragma alloc_text(PAGE,MiApplyDriverVerifier) 00443 #pragma alloc_text(PAGE,MiEnableVerifier) 00444 #pragma alloc_text(PAGE,ViPrintString) 00445 #pragma alloc_text(PAGE,MmGetVerifierInformation) 00446 #pragma alloc_text(PAGE,MmSetVerifierInformation) 00447 #pragma alloc_text(PAGE,MmAddVerifierThunks) 00448 #pragma alloc_text(PAGELK,MiVerifierCheckThunks) 00449 #pragma alloc_text(PAGELK,MiVerifyingDriverUnloading) 00450 00451 #pragma alloc_text(PAGEVRFY,VerifierProbeAndLockPages) 00452 #pragma alloc_text(PAGEVRFY,VerifierProbeAndLockProcessPages) 00453 #pragma alloc_text(PAGEVRFY,VerifierProbeAndLockSelectedPages) 00454 #pragma alloc_text(PAGEVRFY,VerifierUnlockPages) 00455 #pragma alloc_text(PAGEVRFY,VerifierMapIoSpace) 00456 #pragma alloc_text(PAGEVRFY,VerifierMapLockedPages) 00457 #pragma alloc_text(PAGEVRFY,VerifierMapLockedPagesSpecifyCache) 00458 #pragma alloc_text(PAGEVRFY,VerifierUnmapLockedPages) 00459 #pragma alloc_text(PAGEVRFY,VerifierUnmapIoSpace) 00460 #pragma alloc_text(PAGEVRFY,VerifierAllocatePool) 00461 #pragma alloc_text(PAGEVRFY,VerifierAllocatePoolWithTag) 00462 #pragma alloc_text(PAGEVRFY,VerifierAllocatePoolWithTagPriority) 00463 #pragma alloc_text(PAGEVRFY,VerifierAllocatePoolWithQuotaTag) 00464 #pragma alloc_text(PAGEVRFY,VerifierFreePool) 00465 #pragma alloc_text(PAGEVRFY,VerifierFreePoolWithTag) 00466 #pragma alloc_text(PAGEVRFY,VerifierKfRaiseIrql) 00467 #pragma alloc_text(PAGEVRFY,VerifierKfLowerIrql) 00468 #pragma alloc_text(PAGEVRFY,VerifierKeRaiseIrql) 00469 #pragma alloc_text(PAGEVRFY,VerifierKeLowerIrql) 00470 #pragma alloc_text(PAGEVRFY,VerifierKeAcquireSpinLock) 00471 #pragma alloc_text(PAGEVRFY,VerifierKeReleaseSpinLock) 00472 #pragma alloc_text(PAGEVRFY,VerifierKfAcquireSpinLock) 00473 #pragma alloc_text(PAGEVRFY,VerifierKfReleaseSpinLock) 00474 #pragma alloc_text(PAGEVRFY,VerifierKeInitializeTimer) 00475 #pragma alloc_text(PAGEVRFY,VerifierKeInitializeTimerEx) 00476 #pragma alloc_text(PAGEVRFY,VerifierExTryToAcquireFastMutex) 00477 #pragma alloc_text(PAGEVRFY,VerifierExAcquireFastMutex) 00478 #pragma alloc_text(PAGEVRFY,VerifierExReleaseFastMutex) 00479 #pragma alloc_text(PAGEVRFY,VerifierExAcquireFastMutexUnsafe) 00480 #pragma alloc_text(PAGEVRFY,VerifierExReleaseFastMutexUnsafe) 00481 #pragma alloc_text(PAGEVRFY,VerifierExAcquireResourceExclusive) 00482 #pragma alloc_text(PAGEVRFY,VerifierExReleaseResource) 00483 #pragma alloc_text(PAGEVRFY,VerifierKeAcquireQueuedSpinLock) 00484 #pragma alloc_text(PAGEVRFY,VerifierKeReleaseQueuedSpinLock) 00485 #pragma alloc_text(PAGEVRFY,VerifierSynchronizeExecution) 00486 00487 #pragma alloc_text(PAGEVRFY,VerifierFreeTrackedPool) 00488 00489 #pragma alloc_text(PAGEVRFY,VeAllocatePoolWithTagPriority) 00490 #pragma alloc_text(PAGEVRFY,ViInsertVerifierEntry) 00491 #pragma alloc_text(PAGEVRFY,ViLocateVerifierEntry) 00492 #pragma alloc_text(PAGEVRFY,ViPostPoolAllocation) 00493 #pragma alloc_text(PAGEVRFY,ViInjectResourceFailure) 00494 #pragma alloc_text(PAGEVRFY,ViTrimAllSystemPagableMemory) 00495 #pragma alloc_text(PAGEVRFY,ViInitializeEntry) 00496 #pragma alloc_text(PAGEVRFY,ViReservePoolAllocation) 00497 #pragma alloc_text(PAGEVRFY,ViInsertPoolAllocation) 00498 #pragma alloc_text(PAGEVRFY,ViCancelPoolAllocation) 00499 #pragma alloc_text(PAGEVRFY,ViReleasePoolAllocation) 00500 #pragma alloc_text(PAGEVRFY,KfSanityCheckRaiseIrql) 00501 #pragma alloc_text(PAGEVRFY,KfSanityCheckLowerIrql) 00502 #endif 00503 00504 typedef struct _VERIFIER_THUNKS { 00505 PDRIVER_VERIFIER_THUNK_ROUTINE PristineRoutine; 00506 PDRIVER_VERIFIER_THUNK_ROUTINE NewRoutine; 00507 ULONG Flag; 00508 } VERIFIER_THUNKS, *PVERIFIER_THUNKS; 00509 00510 typedef struct _DRIVER_SPECIFIED_VERIFIER_THUNKS { 00511 LIST_ENTRY ListEntry; 00512 PLDR_DATA_TABLE_ENTRY DataTableEntry; 00513 ULONG NumberOfThunks; 00514 } DRIVER_SPECIFIED_VERIFIER_THUNKS, *PDRIVER_SPECIFIED_VERIFIER_THUNKS; 00515 00516 #if defined (_X86_) 00517 00518 #define VI_KE_RAISE_IRQL 0 00519 #define VI_KE_LOWER_IRQL 1 00520 #define VI_KE_ACQUIRE_SPINLOCK 2 00521 #define VI_KE_RELEASE_SPINLOCK 3 00522 #define VI_KF_RAISE_IRQL 4 00523 #define VI_KF_LOWER_IRQL 5 00524 #define VI_KF_ACQUIRE_SPINLOCK 6 00525 #define VI_KF_RELEASE_SPINLOCK 7 00526 #define VI_KE_ACQUIRE_QUEUED_SPINLOCK 8 00527 #define VI_KE_RELEASE_QUEUED_SPINLOCK 9 00528 00529 #define VI_HALMAX 10 00530 00531 PVOID MiKernelVerifierOriginalCalls[VI_HALMAX]; 00532 00533 #endif 00534 00535 THUNKED_API 00536 VOID 00537 VerifierProbeAndLockPages ( 00538 IN OUT PMDL MemoryDescriptorList, 00539 IN KPROCESSOR_MODE AccessMode, 00540 IN LOCK_OPERATION Operation 00541 ) 00542 { 00543 KIRQL CurrentIrql; 00544 00545 CurrentIrql = KeGetCurrentIrql(); 00546 if (CurrentIrql > DISPATCH_LEVEL) { 00547 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00548 0x70, 00549 CurrentIrql, 00550 (ULONG_PTR)MemoryDescriptorList, 00551 (ULONG_PTR)AccessMode); 00552 } 00553 00554 if (ViInjectResourceFailure () == TRUE) { 00555 ExRaiseStatus (STATUS_WORKING_SET_QUOTA); 00556 } 00557 00558 MmProbeAndLockPages (MemoryDescriptorList, AccessMode, Operation); 00559 } 00560 00561 THUNKED_API 00562 VOID 00563 VerifierProbeAndLockProcessPages ( 00564 IN OUT PMDL MemoryDescriptorList, 00565 IN PEPROCESS Process, 00566 IN KPROCESSOR_MODE AccessMode, 00567 IN LOCK_OPERATION Operation 00568 ) 00569 { 00570 KIRQL CurrentIrql; 00571 00572 CurrentIrql = KeGetCurrentIrql(); 00573 if (CurrentIrql > DISPATCH_LEVEL) { 00574 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00575 0x71, 00576 CurrentIrql, 00577 (ULONG_PTR)MemoryDescriptorList, 00578 (ULONG_PTR)Process); 00579 } 00580 00581 if (ViInjectResourceFailure () == TRUE) { 00582 ExRaiseStatus (STATUS_WORKING_SET_QUOTA); 00583 } 00584 00585 MmProbeAndLockProcessPages (MemoryDescriptorList, 00586 Process, 00587 AccessMode, 00588 Operation); 00589 } 00590 00591 THUNKED_API 00592 VOID 00593 VerifierProbeAndLockSelectedPages ( 00594 IN OUT PMDL MemoryDescriptorList, 00595 IN PFILE_SEGMENT_ELEMENT SegmentArray, 00596 IN KPROCESSOR_MODE AccessMode, 00597 IN LOCK_OPERATION Operation 00598 ) 00599 { 00600 KIRQL CurrentIrql; 00601 00602 CurrentIrql = KeGetCurrentIrql(); 00603 if (CurrentIrql > APC_LEVEL) { 00604 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00605 0x72, 00606 CurrentIrql, 00607 (ULONG_PTR)MemoryDescriptorList, 00608 (ULONG_PTR)AccessMode); 00609 } 00610 00611 if (ViInjectResourceFailure () == TRUE) { 00612 ExRaiseStatus (STATUS_WORKING_SET_QUOTA); 00613 } 00614 00615 MmProbeAndLockSelectedPages (MemoryDescriptorList, 00616 SegmentArray, 00617 AccessMode, 00618 Operation); 00619 } 00620 00621 // 00622 // It would be great to rip out the ViBadMapper code but some drivers will 00623 // never get fixed if this is done. 00624 // 00625 00626 #define VI_BAD_MAPPERS_MAX 100 00627 00628 KSPIN_LOCK ViBadMapperLock; 00629 PVOID ViBadMappers[VI_BAD_MAPPERS_MAX]; 00630 00631 LOGICAL 00632 ViAddBadMapper ( 00633 IN PVOID BadMapper 00634 ) 00635 { 00636 ULONG i; 00637 KIRQL OldIrql; 00638 LOGICAL Added; 00639 00640 Added = FALSE; 00641 ExAcquireSpinLock (&ViBadMapperLock, &OldIrql); 00642 00643 for (i = 0; i < VI_BAD_MAPPERS_MAX; i += 1) { 00644 if (ViBadMappers[i] == BadMapper) { 00645 break; 00646 } 00647 00648 if (ViBadMappers[i] == NULL) { 00649 ViBadMappers[i] = BadMapper; 00650 Added = TRUE; 00651 break; 00652 } 00653 } 00654 00655 ExReleaseSpinLock (&ViBadMapperLock, OldIrql); 00656 00657 return Added; 00658 } 00659 00660 THUNKED_API 00661 PVOID 00662 VerifierMapIoSpace ( 00663 IN PHYSICAL_ADDRESS PhysicalAddress, 00664 IN SIZE_T NumberOfBytes, 00665 IN MEMORY_CACHING_TYPE CacheType 00666 ) 00667 { 00668 KIRQL CurrentIrql; 00669 00670 CurrentIrql = KeGetCurrentIrql(); 00671 if (CurrentIrql > DISPATCH_LEVEL) { 00672 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00673 0x73, 00674 CurrentIrql, 00675 (ULONG_PTR)PhysicalAddress.LowPart, 00676 NumberOfBytes); 00677 } 00678 00679 if (ViInjectResourceFailure () == TRUE) { 00680 return NULL; 00681 } 00682 00683 return MmMapIoSpace (PhysicalAddress, NumberOfBytes, CacheType); 00684 } 00685 00686 THUNKED_API 00687 PVOID 00688 VerifierMapLockedPages ( 00689 IN PMDL MemoryDescriptorList, 00690 IN KPROCESSOR_MODE AccessMode 00691 ) 00692 { 00693 PVOID CallingAddress; 00694 PVOID CallersCaller; 00695 KIRQL CurrentIrql; 00696 00697 #if defined (_X86_) 00698 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 00699 #else 00700 CallingAddress = (PVOID)_ReturnAddress(); 00701 #endif 00702 00703 CurrentIrql = KeGetCurrentIrql(); 00704 00705 if (AccessMode == KernelMode) { 00706 if (CurrentIrql > DISPATCH_LEVEL) { 00707 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00708 0x74, 00709 CurrentIrql, 00710 (ULONG_PTR)MemoryDescriptorList, 00711 (ULONG_PTR)AccessMode); 00712 } 00713 } 00714 else { 00715 if (CurrentIrql > APC_LEVEL) { 00716 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00717 0x75, 00718 CurrentIrql, 00719 (ULONG_PTR)MemoryDescriptorList, 00720 (ULONG_PTR)AccessMode); 00721 } 00722 } 00723 00724 if ((MemoryDescriptorList->MdlFlags & MDL_MAPPING_CAN_FAIL) == 0) { 00725 00726 if (ViAddBadMapper (CallingAddress) == TRUE) { 00727 00728 // 00729 // All drivers must specify can fail. We'd really like to bugcheck 00730 // here to get drivers to convert but cut them some slack for now. 00731 // 00732 00733 DbgPrint ("*******************************************************************************\n"); 00734 DbgPrint ("* *\n"); 00735 00736 DbgPrint ("* The Driver Verifier has detected the driver at address %p\n", CallingAddress); 00737 DbgPrint ("* is calling MmMapLockedPages instead of MmMapLockedPagesSpecifyCache.\n"); 00738 DbgPrint ("* This can cause the system to needlessly bugcheck whenever system\n"); 00739 DbgPrint ("* resources are low. This driver needs to be fixed.\n"); 00740 00741 DbgPrint ("* *\n"); 00742 DbgPrint ("*******************************************************************************\n"); 00743 } 00744 } 00745 00746 return MmMapLockedPages (MemoryDescriptorList, AccessMode); 00747 } 00748 00749 THUNKED_API 00750 PVOID 00751 VerifierMapLockedPagesSpecifyCache ( 00752 IN PMDL MemoryDescriptorList, 00753 IN KPROCESSOR_MODE AccessMode, 00754 IN MEMORY_CACHING_TYPE CacheType, 00755 IN PVOID RequestedAddress, 00756 IN ULONG BugCheckOnFailure, 00757 IN MM_PAGE_PRIORITY Priority 00758 ) 00759 { 00760 PVOID CallingAddress; 00761 PVOID CallersCaller; 00762 KIRQL CurrentIrql; 00763 00764 #if defined (_X86_) 00765 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 00766 #else 00767 CallingAddress = (PVOID)_ReturnAddress(); 00768 #endif 00769 00770 CurrentIrql = KeGetCurrentIrql(); 00771 if (AccessMode == KernelMode) { 00772 if (CurrentIrql > DISPATCH_LEVEL) { 00773 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00774 0x76, 00775 CurrentIrql, 00776 (ULONG_PTR)MemoryDescriptorList, 00777 (ULONG_PTR)AccessMode); 00778 } 00779 } 00780 else { 00781 if (CurrentIrql > APC_LEVEL) { 00782 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00783 0x77, 00784 CurrentIrql, 00785 (ULONG_PTR)MemoryDescriptorList, 00786 (ULONG_PTR)AccessMode); 00787 } 00788 } 00789 00790 if ((MemoryDescriptorList->MdlFlags & MDL_MAPPING_CAN_FAIL) || 00791 (BugCheckOnFailure == 0)) { 00792 00793 if (ViInjectResourceFailure () == TRUE) { 00794 return NULL; 00795 } 00796 } 00797 else { 00798 00799 // 00800 // All drivers must specify can fail or don't bugcheck. We'd 00801 // really like to bugcheck here to get drivers to convert but 00802 // cut them some slack for now. 00803 // 00804 00805 if (ViAddBadMapper (CallingAddress) == TRUE) { 00806 00807 DbgPrint ("*******************************************************************************\n"); 00808 DbgPrint ("* *\n"); 00809 00810 DbgPrint ("* The Driver Verifier has detected the driver at address %p\n", CallingAddress); 00811 DbgPrint ("* is not calling the safe version of MmMapLockedPagesSpecifyCache.\n"); 00812 DbgPrint ("* This can cause the system to needlessly bugcheck whenever system\n"); 00813 DbgPrint ("* resources are low. This driver needs to be fixed.\n"); 00814 00815 DbgPrint ("* *\n"); 00816 DbgPrint ("*******************************************************************************\n"); 00817 } 00818 } 00819 00820 return MmMapLockedPagesSpecifyCache (MemoryDescriptorList, 00821 AccessMode, 00822 CacheType, 00823 RequestedAddress, 00824 BugCheckOnFailure, 00825 Priority); 00826 } 00827 00828 VOID 00829 VerifierUnlockPages ( 00830 IN OUT PMDL MemoryDescriptorList 00831 ) 00832 { 00833 KIRQL CurrentIrql; 00834 00835 CurrentIrql = KeGetCurrentIrql(); 00836 if (CurrentIrql > DISPATCH_LEVEL) { 00837 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00838 0x78, 00839 CurrentIrql, 00840 (ULONG_PTR)MemoryDescriptorList, 00841 0); 00842 } 00843 00844 if ((MemoryDescriptorList->MdlFlags & MDL_PAGES_LOCKED) == 0) { 00845 00846 // 00847 // The caller is trying to unlock an MDL that was never locked down. 00848 // 00849 00850 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00851 0x7C, 00852 (ULONG_PTR)MemoryDescriptorList, 00853 (ULONG_PTR)MemoryDescriptorList->MdlFlags, 00854 0); 00855 } 00856 00857 if (MemoryDescriptorList->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) { 00858 00859 // 00860 // Nonpaged pool should never be locked down. 00861 // 00862 00863 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00864 0x7D, 00865 (ULONG_PTR)MemoryDescriptorList, 00866 (ULONG_PTR)MemoryDescriptorList->MdlFlags, 00867 0); 00868 } 00869 00870 MmUnlockPages (MemoryDescriptorList); 00871 } 00872 00873 VOID 00874 VerifierUnmapLockedPages ( 00875 IN PVOID BaseAddress, 00876 IN PMDL MemoryDescriptorList 00877 ) 00878 { 00879 KIRQL CurrentIrql; 00880 00881 CurrentIrql = KeGetCurrentIrql(); 00882 00883 if (BaseAddress > MM_HIGHEST_USER_ADDRESS) { 00884 if (CurrentIrql > DISPATCH_LEVEL) { 00885 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00886 0x79, 00887 CurrentIrql, 00888 (ULONG_PTR)BaseAddress, 00889 (ULONG_PTR)MemoryDescriptorList); 00890 } 00891 } 00892 else { 00893 if (CurrentIrql > APC_LEVEL) { 00894 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00895 0x7A, 00896 CurrentIrql, 00897 (ULONG_PTR)BaseAddress, 00898 (ULONG_PTR)MemoryDescriptorList); 00899 } 00900 } 00901 00902 MmUnmapLockedPages (BaseAddress, MemoryDescriptorList); 00903 } 00904 00905 VOID 00906 VerifierUnmapIoSpace ( 00907 IN PVOID BaseAddress, 00908 IN SIZE_T NumberOfBytes 00909 ) 00910 { 00911 KIRQL CurrentIrql; 00912 00913 CurrentIrql = KeGetCurrentIrql(); 00914 if (CurrentIrql > DISPATCH_LEVEL) { 00915 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 00916 0x7B, 00917 CurrentIrql, 00918 (ULONG_PTR)BaseAddress, 00919 (ULONG_PTR)NumberOfBytes); 00920 } 00921 00922 MmUnmapIoSpace (BaseAddress, NumberOfBytes); 00923 } 00924 00925 THUNKED_API 00926 PVOID 00927 VerifierAllocatePool( 00928 IN POOL_TYPE PoolType, 00929 IN SIZE_T NumberOfBytes 00930 ) 00931 { 00932 PVOID CallingAddress; 00933 PVOID CallersCaller; 00934 PMI_VERIFIER_DRIVER_ENTRY Verifier; 00935 00936 #if defined (_X86_) 00937 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 00938 #else 00939 CallingAddress = (PVOID)_ReturnAddress(); 00940 #endif 00941 00942 if (KernelVerifier == TRUE) { 00943 00944 Verifier = ViLocateVerifierEntry (CallingAddress); 00945 00946 if ((Verifier == NULL) || 00947 ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) { 00948 00949 return ExAllocatePool (PoolType | POOL_DRIVER_MASK, NumberOfBytes); 00950 } 00951 PoolType |= POOL_DRIVER_MASK; 00952 } 00953 00954 MmVerifierData.AllocationsWithNoTag += 1; 00955 00956 return VeAllocatePoolWithTagPriority (PoolType, 00957 NumberOfBytes, 00958 'parW', 00959 HighPoolPriority, 00960 CallingAddress); 00961 } 00962 00963 THUNKED_API 00964 PVOID 00965 VerifierAllocatePoolWithTag( 00966 IN POOL_TYPE PoolType, 00967 IN SIZE_T NumberOfBytes, 00968 IN ULONG Tag 00969 ) 00970 { 00971 PVOID CallingAddress; 00972 PVOID CallersCaller; 00973 PMI_VERIFIER_DRIVER_ENTRY Verifier; 00974 00975 #if defined (_X86_) 00976 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 00977 #else 00978 CallingAddress = (PVOID)_ReturnAddress(); 00979 #endif 00980 00981 if (KernelVerifier == TRUE) { 00982 Verifier = ViLocateVerifierEntry (CallingAddress); 00983 00984 if ((Verifier == NULL) || 00985 ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) { 00986 00987 return ExAllocatePoolWithTag (PoolType | POOL_DRIVER_MASK, 00988 NumberOfBytes, 00989 Tag); 00990 } 00991 PoolType |= POOL_DRIVER_MASK; 00992 } 00993 00994 return VeAllocatePoolWithTagPriority (PoolType, 00995 NumberOfBytes, 00996 Tag, 00997 HighPoolPriority, 00998 CallingAddress); 00999 } 01000 01001 THUNKED_API 01002 PVOID 01003 VerifierAllocatePoolWithQuota( 01004 IN POOL_TYPE PoolType, 01005 IN SIZE_T NumberOfBytes 01006 ) 01007 { 01008 PVOID Va; 01009 LOGICAL RaiseOnQuotaFailure; 01010 PVOID CallingAddress; 01011 PVOID CallersCaller; 01012 PMI_VERIFIER_DRIVER_ENTRY Verifier; 01013 01014 #if defined (_X86_) 01015 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 01016 #else 01017 CallingAddress = (PVOID)_ReturnAddress(); 01018 #endif 01019 01020 if (KernelVerifier == TRUE) { 01021 Verifier = ViLocateVerifierEntry (CallingAddress); 01022 01023 if ((Verifier == NULL) || 01024 ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) { 01025 01026 return ExAllocatePoolWithQuota (PoolType | POOL_DRIVER_MASK, 01027 NumberOfBytes); 01028 } 01029 PoolType |= POOL_DRIVER_MASK; 01030 } 01031 01032 MmVerifierData.AllocationsWithNoTag += 1; 01033 01034 if (PoolType & POOL_QUOTA_FAIL_INSTEAD_OF_RAISE) { 01035 RaiseOnQuotaFailure = FALSE; 01036 PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE; 01037 } 01038 else { 01039 RaiseOnQuotaFailure = TRUE; 01040 } 01041 01042 Va = VeAllocatePoolWithTagPriority (PoolType, 01043 NumberOfBytes, 01044 'parW', 01045 HighPoolPriority, 01046 CallingAddress); 01047 01048 if (Va == NULL) { 01049 if (RaiseOnQuotaFailure == TRUE) { 01050 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 01051 } 01052 } 01053 01054 return Va; 01055 } 01056 01057 THUNKED_API 01058 PVOID 01059 VerifierAllocatePoolWithQuotaTag( 01060 IN POOL_TYPE PoolType, 01061 IN SIZE_T NumberOfBytes, 01062 IN ULONG Tag 01063 ) 01064 { 01065 PVOID Va; 01066 LOGICAL RaiseOnQuotaFailure; 01067 PVOID CallingAddress; 01068 PVOID CallersCaller; 01069 PMI_VERIFIER_DRIVER_ENTRY Verifier; 01070 01071 #if defined (_X86_) 01072 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 01073 #else 01074 CallingAddress = (PVOID)_ReturnAddress(); 01075 #endif 01076 01077 if (KernelVerifier == TRUE) { 01078 Verifier = ViLocateVerifierEntry (CallingAddress); 01079 01080 if ((Verifier == NULL) || 01081 ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) { 01082 01083 return ExAllocatePoolWithQuotaTag (PoolType | POOL_DRIVER_MASK, 01084 NumberOfBytes, 01085 Tag); 01086 } 01087 PoolType |= POOL_DRIVER_MASK; 01088 } 01089 01090 if (PoolType & POOL_QUOTA_FAIL_INSTEAD_OF_RAISE) { 01091 RaiseOnQuotaFailure = FALSE; 01092 PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE; 01093 } 01094 else { 01095 RaiseOnQuotaFailure = TRUE; 01096 } 01097 01098 Va = VeAllocatePoolWithTagPriority (PoolType, 01099 NumberOfBytes, 01100 Tag, 01101 HighPoolPriority, 01102 CallingAddress); 01103 01104 if (Va == NULL) { 01105 if (RaiseOnQuotaFailure == TRUE) { 01106 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 01107 } 01108 } 01109 01110 return Va; 01111 } 01112 01113 THUNKED_API 01114 PVOID 01115 VerifierAllocatePoolWithTagPriority( 01116 IN POOL_TYPE PoolType, 01117 IN SIZE_T NumberOfBytes, 01118 IN ULONG Tag, 01119 IN EX_POOL_PRIORITY Priority 01120 ) 01121 01122 /*++ 01123 01124 Routine Description: 01125 01126 This thunked-in function: 01127 01128 - Performs sanity checks on the caller. 01129 - Can optionally provide allocation failures to the caller. 01130 - Attempts to provide the allocation from special pool. 01131 - Tracks pool to ensure callers free everything they allocate. 01132 01133 --*/ 01134 01135 { 01136 PVOID CallingAddress; 01137 PVOID CallersCaller; 01138 PMI_VERIFIER_DRIVER_ENTRY Verifier; 01139 01140 #if defined (_X86_) 01141 RtlGetCallersAddress(&CallingAddress, &CallersCaller); 01142 #else 01143 CallingAddress = (PVOID)_ReturnAddress(); 01144 #endif 01145 01146 if (KernelVerifier == TRUE) { 01147 Verifier = ViLocateVerifierEntry (CallingAddress); 01148 01149 if ((Verifier == NULL) || 01150 ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) { 01151 01152 return ExAllocatePoolWithTagPriority (PoolType | POOL_DRIVER_MASK, 01153 NumberOfBytes, 01154 Tag, 01155 Priority); 01156 } 01157 PoolType |= POOL_DRIVER_MASK; 01158 } 01159 01160 return VeAllocatePoolWithTagPriority (PoolType, 01161 NumberOfBytes, 01162 Tag, 01163 Priority, 01164 CallingAddress); 01165 } 01166 01167 LOGICAL 01168 ViInjectResourceFailure ( 01169 VOID 01170 ) 01171 01172 /*++ 01173 01174 Routine Description: 01175 01176 This function determines whether a resource allocation should be 01177 deliberately failed. This may be a pool allocation, MDL creation, 01178 system PTE allocation, etc. 01179 01180 Arguments: 01181 01182 None. 01183 01184 Return Value: 01185 01186 TRUE if the allocation should be failed. FALSE otherwise. 01187 01188 Environment: 01189 01190 Kernel mode. DISPATCH_LEVEL or below. 01191 01192 --*/ 01193 01194 { 01195 LARGE_INTEGER CurrentTime; 01196 01197 if ((MmVerifierData.Level & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES) == 0) { 01198 return FALSE; 01199 } 01200 01201 // 01202 // Don't fail any requests in the first 7 or 8 minutes as we want to 01203 // give the system enough time to boot. 01204 // 01205 01206 if (VerifierSystemSufficientlyBooted == FALSE) { 01207 KeQuerySystemTime (&CurrentTime); 01208 if (CurrentTime.QuadPart > KeBootTime.QuadPart + VerifierRequiredTimeSinceBoot.QuadPart) { 01209 VerifierSystemSufficientlyBooted = TRUE; 01210 } 01211 } 01212 01213 if (VerifierSystemSufficientlyBooted == TRUE) { 01214 01215 KeQueryTickCount(&CurrentTime); 01216 01217 if ((CurrentTime.LowPart & 0xF) == 0) { 01218 01219 MmVerifierData.AllocationsFailedDeliberately += 1; 01220 01221 // 01222 // Deliberately fail this request. 01223 // 01224 01225 return TRUE; 01226 } 01227 } 01228 01229 return FALSE; 01230 } 01231 01232 LOGICAL 01233 ViReservePoolAllocation ( 01234 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 01235 ) 01236 { 01237 ULONG_PTR OldSize; 01238 ULONG_PTR NewSize; 01239 ULONG_PTR NewHashOffset; 01240 ULONG_PTR Increment; 01241 ULONG_PTR Entries; 01242 ULONG_PTR i; 01243 KIRQL OldIrql; 01244 PVOID NewHashTable; 01245 PVI_POOL_ENTRY HashEntry; 01246 PVI_POOL_ENTRY OldHashTable; 01247 01248 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 01249 01250 while (Verifier->PoolHashSize <= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved) { 01251 01252 // 01253 // More space is needed. Try for it now. 01254 // 01255 01256 #define VI_POOL_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(VI_POOL_ENTRY)) 01257 01258 OldSize = Verifier->PoolHashSize * sizeof(VI_POOL_ENTRY); 01259 01260 if (Verifier->PoolHashSize >= VI_POOL_ENTRIES_PER_PAGE) { 01261 Increment = PAGE_SIZE; 01262 } 01263 else { 01264 Increment = 16 * sizeof (VI_POOL_ENTRY); 01265 } 01266 01267 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01268 01269 NewSize = OldSize + Increment; 01270 01271 if (NewSize < OldSize) { 01272 return FALSE; 01273 } 01274 01275 // 01276 // Note POOL_DRIVER_MASK must be set to stop the recursion loop 01277 // when using the kernel verifier. 01278 // 01279 01280 NewHashTable = ExAllocatePoolWithTagPriority (NonPagedPool | POOL_DRIVER_MASK, 01281 NewSize, 01282 'ppeV', 01283 HighPoolPriority); 01284 01285 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 01286 01287 OldSize = Verifier->PoolHashSize * sizeof(VI_POOL_ENTRY); 01288 01289 if (NewHashTable == NULL) { 01290 if (Verifier->PoolHashSize <= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved) { 01291 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01292 return FALSE; 01293 } 01294 01295 // 01296 // Another thread got here before us and space is available. 01297 // 01298 01299 break; 01300 } 01301 01302 if (NewSize != OldSize + Increment) { 01303 01304 // 01305 // Another thread got here before us. 01306 // 01307 01308 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01309 ExFreePool (NewHashTable); 01310 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 01311 } 01312 else { 01313 01314 // 01315 // Rebuild the list into the new table. 01316 // 01317 01318 OldHashTable = Verifier->PoolHash; 01319 if (OldHashTable != NULL) { 01320 RtlCopyMemory (NewHashTable, OldHashTable, OldSize); 01321 } 01322 01323 // 01324 // Construct the freelist chaining it through any existing 01325 // list (any free entries must be already reserved). 01326 // 01327 01328 HashEntry = (PVI_POOL_ENTRY) ((PCHAR)NewHashTable + OldSize); 01329 Entries = Increment / sizeof (VI_POOL_ENTRY); 01330 NewHashOffset = HashEntry - (PVI_POOL_ENTRY)NewHashTable; 01331 01332 // 01333 // If list compaction becomes important then chaining it on the 01334 // end here will need to be revisited. 01335 // 01336 01337 for (i = 0; i < Entries; i += 1) { 01338 HashEntry->FreeListNext = NewHashOffset + i + 1; 01339 HashEntry += 1; 01340 } 01341 HashEntry -= 1; 01342 HashEntry->FreeListNext = Verifier->PoolHashFree; 01343 Verifier->PoolHashFree = NewHashOffset; 01344 Verifier->PoolHash = NewHashTable; 01345 Verifier->PoolHashSize += Entries; 01346 01347 // 01348 // Free the old table. 01349 // 01350 01351 if (OldHashTable != NULL) { 01352 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01353 ExFreePool (OldHashTable); 01354 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 01355 } 01356 } 01357 } 01358 01359 Verifier->PoolHashReserved += 1; 01360 01361 ASSERT (Verifier->PoolHashSize >= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved); 01362 01363 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01364 01365 return TRUE; 01366 } 01367 01368 ULONG_PTR 01369 ViInsertPoolAllocation ( 01370 IN PMI_VERIFIER_DRIVER_ENTRY Verifier, 01371 IN PVOID VirtualAddress, 01372 IN PVOID CallingAddress, 01373 IN SIZE_T NumberOfBytes, 01374 IN ULONG Tag 01375 ) 01376 01377 /*++ 01378 01379 Routine Description: 01380 01381 This function inserts the specified virtual address into the verifier 01382 list for this driver. 01383 01384 Arguments: 01385 01386 Verifier - Supplies the verifier entry to update. 01387 01388 VirtualAddress - Supplies the virtual address to insert. 01389 01390 CallingAddress - Supplies the caller's address. 01391 01392 NumberOfBytes - Supplies the number of bytes to allocate. 01393 01394 Tag - Supplies the tag for the pool being allocated. 01395 01396 Return Value: 01397 01398 The list index this virtual address was inserted at. 01399 01400 Environment: 01401 01402 Kernel mode, DISPATCH_LEVEL. The Verifier->VerifierPoolLock must be held. 01403 01404 --*/ 01405 01406 { 01407 ULONG_PTR Index; 01408 PVI_POOL_ENTRY HashEntry; 01409 01410 ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL); 01411 01412 // 01413 // The list entry must be reserved in advance. 01414 // 01415 01416 ASSERT (Verifier->PoolHashReserved != 0); 01417 01418 ASSERT (Verifier->PoolHashSize >= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved); 01419 01420 // 01421 // Use the next free list entry. 01422 // 01423 01424 Index = Verifier->PoolHashFree; 01425 ASSERT (Index != VI_POOL_FREELIST_END); 01426 01427 HashEntry = Verifier->PoolHash + Index; 01428 01429 Verifier->PoolHashFree = HashEntry->FreeListNext; 01430 01431 Verifier->PoolHashReserved -= 1; 01432 01433 ASSERT (((HashEntry->FreeListNext & MINLONG_PTR) == 0) || 01434 (HashEntry->FreeListNext == VI_POOL_FREELIST_END)); 01435 01436 HashEntry->InUse.VirtualAddress = VirtualAddress; 01437 HashEntry->InUse.CallingAddress = CallingAddress; 01438 HashEntry->InUse.NumberOfBytes = NumberOfBytes; 01439 HashEntry->InUse.Tag = Tag; 01440 01441 ASSERT ((HashEntry->FreeListNext & MINLONG_PTR) != 0); 01442 01443 return Index; 01444 } 01445 01446 VOID 01447 ViReleasePoolAllocation ( 01448 IN PMI_VERIFIER_DRIVER_ENTRY Verifier, 01449 IN PVOID VirtualAddress, 01450 IN ULONG_PTR ListIndex, 01451 IN SIZE_T ChargedBytes 01452 ) 01453 01454 /*++ 01455 01456 Routine Description: 01457 01458 This function removes the specified virtual address from the verifier 01459 list for this driver. 01460 01461 Arguments: 01462 01463 Verifier - Supplies the verifier entry to update. 01464 01465 VirtualAddress - Supplies the virtual address to release. 01466 01467 ListIndex - Supplies the verifier pool hash index for the address being 01468 released. 01469 01470 ChargedBytes - Supplies the bytes charged for this allocation. 01471 01472 Return Value: 01473 01474 None. 01475 01476 Environment: 01477 01478 Kernel mode, DISPATCH_LEVEL. The Verifier->VerifierPoolLock must be held. 01479 01480 --*/ 01481 01482 { 01483 PFN_NUMBER PageFrameIndex; 01484 PFN_NUMBER PageFrameIndex2; 01485 PVI_POOL_ENTRY HashEntry; 01486 PMMPTE PointerPte; 01487 01488 ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL); 01489 01490 if (Verifier->PoolHash == NULL) { 01491 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 01492 0x59, 01493 (ULONG_PTR)VirtualAddress, 01494 ListIndex, 01495 (ULONG_PTR)Verifier); 01496 } 01497 01498 // 01499 // Ensure that the list pointer has not been overrun and still 01500 // points at something decent. 01501 // 01502 01503 HashEntry = Verifier->PoolHash + ListIndex; 01504 01505 if (ListIndex >= Verifier->PoolHashSize) { 01506 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 01507 0x54, 01508 (ULONG_PTR)VirtualAddress, 01509 Verifier->PoolHashSize, 01510 ListIndex); 01511 } 01512 01513 if (HashEntry->InUse.VirtualAddress != VirtualAddress) { 01514 01515 PageFrameIndex = 0; 01516 PageFrameIndex2 = 1; 01517 01518 if ((!MI_IS_PHYSICAL_ADDRESS(VirtualAddress)) && 01519 (MI_IS_PHYSICAL_ADDRESS(HashEntry->InUse.VirtualAddress))) { 01520 01521 PointerPte = MiGetPteAddress(VirtualAddress); 01522 if (PointerPte->u.Hard.Valid == 1) { 01523 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 01524 01525 PageFrameIndex2 = MI_CONVERT_PHYSICAL_TO_PFN (HashEntry->InUse.VirtualAddress); 01526 } 01527 } 01528 01529 // 01530 // Caller overran and corrupted the virtual address - the linked 01531 // list cannot be counted on either. 01532 // 01533 01534 if (PageFrameIndex != PageFrameIndex2) { 01535 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 01536 0x52, 01537 (ULONG_PTR)VirtualAddress, 01538 (ULONG_PTR)HashEntry->InUse.VirtualAddress, 01539 ChargedBytes); 01540 } 01541 } 01542 01543 if (HashEntry->InUse.NumberOfBytes != ChargedBytes) { 01544 01545 // 01546 // Caller overran and corrupted the byte count - the linked 01547 // list cannot be counted on either. 01548 // 01549 01550 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 01551 0x51, 01552 (ULONG_PTR)VirtualAddress, 01553 (ULONG_PTR)HashEntry, 01554 ChargedBytes); 01555 } 01556 01557 // 01558 // Put this list entry into the freelist. 01559 // 01560 01561 HashEntry->FreeListNext = Verifier->PoolHashFree; 01562 Verifier->PoolHashFree = HashEntry - Verifier->PoolHash; 01563 } 01564 01565 VOID 01566 ViCancelPoolAllocation ( 01567 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 01568 ) 01569 01570 /*++ 01571 01572 Routine Description: 01573 01574 This function removes a reservation from the verifier list for this driver. 01575 All reservations must be made in advance. This routine is used when an 01576 earlier reservation is not going to be used (ie: the actual pool 01577 allocation failed so no reservation will be needed after all). 01578 01579 Arguments: 01580 01581 Verifier - Supplies the verifier entry to update. 01582 01583 Return Value: 01584 01585 None. 01586 01587 Environment: 01588 01589 Kernel mode, DISPATCH_LEVEL or below, no verifier mutexes held. 01590 01591 --*/ 01592 01593 { 01594 KIRQL OldIrql; 01595 01596 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 01597 01598 // 01599 // The hash entry reserved earlier is not going to be used after all. 01600 // 01601 01602 ASSERT (Verifier->PoolHashReserved != 0); 01603 01604 ASSERT (Verifier->PoolHashSize >= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved); 01605 01606 ASSERT (Verifier->PoolHashFree != VI_POOL_FREELIST_END); 01607 01608 Verifier->PoolHashReserved -= 1; 01609 01610 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01611 } 01612 01613 PVOID 01614 ViPostPoolAllocation ( 01615 IN PVOID VirtualAddress, 01616 IN SIZE_T NumberOfBytes, 01617 IN POOL_TYPE PoolType, 01618 IN ULONG Tag, 01619 IN PVOID CallingAddress 01620 ) 01621 01622 /*++ 01623 01624 Routine Description: 01625 01626 This function performs verifier book-keeping on the allocation attempt. 01627 01628 Arguments: 01629 01630 VirtualAddress - Supplies the virtual address that should be allocated. 01631 01632 NumberOfBytes - Supplies the number of bytes to allocate. 01633 01634 PoolType - Supplies the type of pool being allocated. 01635 01636 Tag - Supplies the tag for the pool being allocated. 01637 01638 CallingAddress - Supplies the caller's address. 01639 01640 Return Value: 01641 01642 The virtual address the caller should use. 01643 01644 Environment: 01645 01646 Kernel mode. DISPATCH_LEVEL or below. 01647 01648 --*/ 01649 01650 { 01651 KIRQL OldIrql; 01652 PMI_VERIFIER_POOL_HEADER Header; 01653 SIZE_T ChargedBytes; 01654 PMI_VERIFIER_DRIVER_ENTRY Verifier; 01655 ULONG_PTR InsertedIndex; 01656 LOGICAL SpecialPoolAllocation; 01657 PPOOL_HEADER PoolHeader; 01658 01659 InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsSucceeded); 01660 ChargedBytes = EX_REAL_POOL_USAGE(NumberOfBytes); 01661 SpecialPoolAllocation = FALSE; 01662 01663 if (VirtualAddress >= MmSpecialPoolStart && VirtualAddress < MmSpecialPoolEnd) { 01664 ChargedBytes = NumberOfBytes; 01665 InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsSucceededSpecialPool); 01666 SpecialPoolAllocation = TRUE; 01667 } 01668 else if (NumberOfBytes <= POOL_BUDDY_MAX) { 01669 ChargedBytes -= POOL_OVERHEAD; 01670 } 01671 else { 01672 01673 // 01674 // This isn't exactly true but it does give the user a way to see 01675 // if this machine is large enough to support special pool 100%. 01676 // 01677 01678 InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsSucceededSpecialPool); 01679 } 01680 01681 if ((PoolType & POOL_VERIFIER_MASK) == 0) { 01682 return VirtualAddress; 01683 } 01684 01685 if (NumberOfBytes > POOL_BUDDY_MAX) { 01686 ASSERT (BYTE_OFFSET(VirtualAddress) == 0); 01687 } 01688 01689 Verifier = ViLocateVerifierEntry (CallingAddress); 01690 ASSERT (Verifier != NULL); 01691 VerifierIsTrackingPool = TRUE; 01692 01693 if (SpecialPoolAllocation == TRUE) { 01694 01695 // 01696 // Carefully adjust the special pool page to move the verifier tracking 01697 // header to the front. This allows the allocation to remain butted 01698 // against the end of the page so overruns can be detected immediately. 01699 // 01700 01701 if (((ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1))) { 01702 PoolHeader = (PPOOL_HEADER)(PAGE_ALIGN (VirtualAddress)); 01703 Header = (PMI_VERIFIER_POOL_HEADER) (PoolHeader + 1); 01704 VirtualAddress = (PVOID) ((PCHAR)VirtualAddress + sizeof (MI_VERIFIER_POOL_HEADER)); 01705 } 01706 else { 01707 PoolHeader = (PPOOL_HEADER)((PCHAR)PAGE_ALIGN (VirtualAddress) + PAGE_SIZE - POOL_OVERHEAD); 01708 Header = (PMI_VERIFIER_POOL_HEADER) (PoolHeader - 1); 01709 } 01710 // ASSERT (PoolHeader->Ulong1 & MI_SPECIAL_POOL_VERIFIER); 01711 PoolHeader->Ulong1 -= sizeof (MI_VERIFIER_POOL_HEADER); 01712 ChargedBytes -= sizeof (MI_VERIFIER_POOL_HEADER); 01713 PoolHeader->Ulong1 |= MI_SPECIAL_POOL_VERIFIER; 01714 } 01715 else { 01716 Header = (PMI_VERIFIER_POOL_HEADER)((PCHAR)VirtualAddress + 01717 ChargedBytes - 01718 sizeof(MI_VERIFIER_POOL_HEADER)); 01719 } 01720 01721 ASSERT (((ULONG_PTR)Header & (sizeof(ULONG) - 1)) == 0); 01722 01723 01724 Header->Verifier = Verifier; 01725 01726 // 01727 // Enqueue the entry and update per-driver counters. 01728 // Note that paged pool allocations must be chained using nonpaged 01729 // pool to prevent deadlocks. 01730 // 01731 01732 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 01733 01734 InsertedIndex = ViInsertPoolAllocation (Verifier, 01735 VirtualAddress, 01736 CallingAddress, 01737 ChargedBytes, 01738 Tag); 01739 01740 if ((PoolType & BASE_POOL_TYPE_MASK) == PagedPool) { 01741 01742 Verifier->PagedBytes += ChargedBytes; 01743 if (Verifier->PagedBytes > Verifier->PeakPagedBytes) { 01744 Verifier->PeakPagedBytes = Verifier->PagedBytes; 01745 } 01746 01747 Verifier->CurrentPagedPoolAllocations += 1; 01748 if (Verifier->CurrentPagedPoolAllocations > Verifier->PeakPagedPoolAllocations) { 01749 Verifier->PeakPagedPoolAllocations = Verifier->CurrentPagedPoolAllocations; 01750 } 01751 } 01752 else { 01753 Verifier->NonPagedBytes += ChargedBytes; 01754 if (Verifier->NonPagedBytes > Verifier->PeakNonPagedBytes) { 01755 Verifier->PeakNonPagedBytes = Verifier->NonPagedBytes; 01756 } 01757 01758 Verifier->CurrentNonPagedPoolAllocations += 1; 01759 if (Verifier->CurrentNonPagedPoolAllocations > Verifier->PeakNonPagedPoolAllocations) { 01760 Verifier->PeakNonPagedPoolAllocations = Verifier->CurrentNonPagedPoolAllocations; 01761 } 01762 } 01763 01764 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 01765 01766 // 01767 // Since the header for paged pool is paged, don't initialize it until the 01768 // spinlock above is released. 01769 // 01770 01771 Header->ListIndex = InsertedIndex; 01772 01773 // 01774 // Update systemwide counters. 01775 // 01776 01777 if ((PoolType & BASE_POOL_TYPE_MASK) == PagedPool) { 01778 ExAcquireFastMutex (&VerifierPoolMutex); 01779 01780 MmVerifierData.PagedBytes += ChargedBytes; 01781 if (MmVerifierData.PagedBytes > MmVerifierData.PeakPagedBytes) { 01782 MmVerifierData.PeakPagedBytes = MmVerifierData.PagedBytes; 01783 } 01784 01785 MmVerifierData.CurrentPagedPoolAllocations += 1; 01786 if (MmVerifierData.CurrentPagedPoolAllocations > MmVerifierData.PeakPagedPoolAllocations) { 01787 MmVerifierData.PeakPagedPoolAllocations = MmVerifierData.CurrentPagedPoolAllocations; 01788 } 01789 01790 ExReleaseFastMutex (&VerifierPoolMutex); 01791 } 01792 else { 01793 ExAcquireSpinLock (&VerifierPoolLock, &OldIrql); 01794 01795 MmVerifierData.NonPagedBytes += ChargedBytes; 01796 if (MmVerifierData.NonPagedBytes > MmVerifierData.PeakNonPagedBytes) { 01797 MmVerifierData.PeakNonPagedBytes = MmVerifierData.NonPagedBytes; 01798 } 01799 01800 MmVerifierData.CurrentNonPagedPoolAllocations += 1; 01801 if (MmVerifierData.CurrentNonPagedPoolAllocations > MmVerifierData.PeakNonPagedPoolAllocations) { 01802 MmVerifierData.PeakNonPagedPoolAllocations = MmVerifierData.CurrentNonPagedPoolAllocations; 01803 } 01804 01805 ExReleaseSpinLock (&VerifierPoolLock, OldIrql); 01806 } 01807 01808 return VirtualAddress; 01809 } 01810 01811 PVOID 01812 VeAllocatePoolWithTagPriority( 01813 IN POOL_TYPE PoolType, 01814 IN SIZE_T NumberOfBytes, 01815 IN ULONG Tag, 01816 IN EX_POOL_PRIORITY Priority, 01817 IN PVOID CallingAddress 01818 ) 01819 01820 /*++ 01821 01822 Routine Description: 01823 01824 This routine is called both from ex\pool.c and directly within this module. 01825 01826 - Performs sanity checks on the caller. 01827 - Can optionally provide allocation failures to the caller. 01828 - Attempts to provide the allocation from special pool. 01829 - Tracks pool to ensure callers free everything they allocate. 01830 01831 --*/ 01832 01833 { 01834 PVOID VirtualAddress; 01835 EX_POOL_PRIORITY AllocationPriority; 01836 SIZE_T ChargedBytes; 01837 PMI_VERIFIER_DRIVER_ENTRY Verifier; 01838 LOGICAL ReservedHash; 01839 ULONG HeaderSize; 01840 01841 ExAllocatePoolSanityChecks (PoolType, NumberOfBytes); 01842 01843 InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsAttempted); 01844 01845 if ((PoolType & MUST_SUCCEED_POOL_TYPE_MASK) == 0) { 01846 01847 if (ViInjectResourceFailure () == TRUE) { 01848 01849 // 01850 // Caller requested an exception - throw it here. 01851 // 01852 01853 if ((PoolType & POOL_RAISE_IF_ALLOCATION_FAILURE) != 0) { 01854 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 01855 } 01856 01857 return NULL; 01858 } 01859 } 01860 01861 ASSERT ((PoolType & POOL_VERIFIER_MASK) == 0); 01862 01863 AllocationPriority = Priority; 01864 01865 if (MmVerifierData.Level & DRIVER_VERIFIER_SPECIAL_POOLING) { 01866 01867 // 01868 // Try for a special pool overrun allocation unless the caller has 01869 // explicitly specified otherwise. 01870 // 01871 01872 if ((AllocationPriority & (LowPoolPrioritySpecialPoolOverrun | LowPoolPrioritySpecialPoolUnderrun)) == 0) { 01873 if (MmSpecialPoolCatchOverruns == TRUE) { 01874 AllocationPriority |= LowPoolPrioritySpecialPoolOverrun; 01875 } 01876 else { 01877 AllocationPriority |= LowPoolPrioritySpecialPoolUnderrun; 01878 } 01879 } 01880 } 01881 01882 ReservedHash = FALSE; 01883 if (MmVerifierData.Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) { 01884 01885 if ((PoolType & SESSION_POOL_MASK) && (MiHydra == TRUE)) { 01886 01887 // 01888 // Session pool is directly tracked by default already. 01889 // 01890 01891 NOTHING; 01892 } 01893 else { 01894 HeaderSize = sizeof(MI_VERIFIER_POOL_HEADER); 01895 01896 ChargedBytes = MI_ROUND_TO_SIZE (NumberOfBytes, sizeof(ULONG)) + HeaderSize; 01897 Verifier = ViLocateVerifierEntry (CallingAddress); 01898 01899 if ((Verifier == NULL) || 01900 ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) { 01901 01902 // 01903 // This can happen for many reasons including no framing (which 01904 // can cause RtlGetCallersAddress to return the wrong address), 01905 // etc. 01906 // 01907 01908 MmVerifierData.UnTrackedPool += 1; 01909 } 01910 else if (ChargedBytes <= NumberOfBytes) { 01911 01912 // 01913 // Don't let the verifier header transform a bad caller into a 01914 // good caller. Fail via the fall through so an exception 01915 // can be thrown if asked for, etc. 01916 // 01917 01918 MmVerifierData.UnTrackedPool += 1; 01919 } 01920 else if (((PoolType & MUST_SUCCEED_POOL_TYPE_MASK) == 0) || 01921 (ChargedBytes <= PAGE_SIZE)) { 01922 01923 // 01924 // Any pool allocation that is allowed to fail or where the 01925 // total number of charged bytes fits in a page (nonpaged- 01926 // must-succeed requires this) is suitable for tracking. 01927 // Just ensure that the hash list has space for it. 01928 // 01929 01930 if (ViReservePoolAllocation (Verifier) == TRUE) { 01931 ReservedHash = TRUE; 01932 NumberOfBytes = ChargedBytes; 01933 PoolType |= POOL_VERIFIER_MASK; 01934 } 01935 } 01936 else { 01937 ASSERT ((PoolType & BASE_POOL_TYPE_MASK) == NonPagedPool); 01938 MmVerifierData.UnTrackedPool += 1; 01939 } 01940 } 01941 } 01942 01943 VirtualAddress = ExAllocatePoolWithTagPriority (PoolType, 01944 NumberOfBytes, 01945 Tag, 01946 AllocationPriority); 01947 01948 if (VirtualAddress == NULL) { 01949 MmVerifierData.AllocationsFailed += 1; 01950 01951 if (ReservedHash == TRUE) { 01952 01953 // 01954 // Release the hash table entry now as it's not needed. 01955 // 01956 01957 ViCancelPoolAllocation (Verifier); 01958 } 01959 01960 if ((PoolType & POOL_RAISE_IF_ALLOCATION_FAILURE) != 0) { 01961 ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); 01962 } 01963 return NULL; 01964 } 01965 01966 VirtualAddress = ViPostPoolAllocation (VirtualAddress, 01967 NumberOfBytes, 01968 PoolType, 01969 Tag, 01970 CallingAddress); 01971 01972 return VirtualAddress; 01973 } 01974 01975 VOID 01976 VerifierFreeTrackedPool( 01977 IN PVOID VirtualAddress, 01978 IN SIZE_T ChargedBytes, 01979 IN LOGICAL CheckType, 01980 IN LOGICAL SpecialPool 01981 ) 01982 01983 /*++ 01984 01985 Routine Description: 01986 01987 Called directly from the pool manager or the memory manager for verifier- 01988 tracked allocations. The call to ExFreePool is already in progress. 01989 01990 Arguments: 01991 01992 VirtualAddress - Supplies the virtual address being freed. 01993 01994 ChargedBytes - Supplies the number of bytes charged to this allocation. 01995 01996 CheckType - Supplies PagedPool or NonPagedPool. 01997 01998 SpecialPool - Supplies TRUE if the allocation is from special pool. 01999 02000 Return Value: 02001 02002 None. 02003 02004 Environment: 02005 02006 Kernel mode. 02007 02008 N.B. 02009 02010 Callers freeing small pool allocations hold no locks or mutexes on entry. 02011 02012 Callers freeing special pool hold no locks or mutexes on entry. 02013 02014 Callers freeing pool of PAGE_SIZE or larger hold the PFN lock (for nonpaged 02015 allocations) or the PagedPool mutex (for paged allocations) on entry. 02016 02017 --*/ 02018 02019 { 02020 KIRQL OldIrql; 02021 ULONG_PTR Index; 02022 PPOOL_HEADER PoolHeader; 02023 PMI_VERIFIER_POOL_HEADER Header; 02024 PMI_VERIFIER_DRIVER_ENTRY Verifier; 02025 02026 if (VerifierIsTrackingPool == FALSE) { 02027 02028 // 02029 // The verifier is not enabled so the only way this routine is being 02030 // called is because the pool header is mangled or the caller specified 02031 // a bad address. Either way it's a bugcheck. 02032 // 02033 02034 KeBugCheckEx (BAD_POOL_CALLER, 02035 0x99, 02036 (ULONG_PTR)VirtualAddress, 02037 0, 02038 0); 02039 } 02040 02041 if (SpecialPool == TRUE) { 02042 02043 // 02044 // Special pool allocation. 02045 // 02046 02047 if (((ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1))) { 02048 PoolHeader = PAGE_ALIGN (VirtualAddress); 02049 Header = (PMI_VERIFIER_POOL_HEADER)(PoolHeader + 1); 02050 } 02051 else { 02052 PoolHeader = (PPOOL_HEADER)((PCHAR)PAGE_ALIGN (VirtualAddress) + PAGE_SIZE - POOL_OVERHEAD); 02053 Header = (PMI_VERIFIER_POOL_HEADER)(PoolHeader - 1); 02054 } 02055 } 02056 else if (PAGE_ALIGNED(VirtualAddress)) { 02057 02058 // 02059 // Large page allocation. 02060 // 02061 02062 Header = (PMI_VERIFIER_POOL_HEADER) ((PCHAR)VirtualAddress + 02063 ChargedBytes - 02064 sizeof(MI_VERIFIER_POOL_HEADER)); 02065 } 02066 else { 02067 ChargedBytes -= POOL_OVERHEAD; 02068 Header = (PMI_VERIFIER_POOL_HEADER) ((PCHAR)VirtualAddress + 02069 ChargedBytes - 02070 sizeof(MI_VERIFIER_POOL_HEADER)); 02071 } 02072 02073 Verifier = Header->Verifier; 02074 02075 // 02076 // Check the pointer now so we can give a more friendly bugcheck 02077 // rather than crashing below on a bad reference. 02078 // 02079 02080 if ((((ULONG_PTR)Verifier & (sizeof(ULONG) - 1)) != 0) || 02081 (!MmIsAddressValid(&Verifier->Signature)) || 02082 (Verifier->Signature != MI_VERIFIER_ENTRY_SIGNATURE)) { 02083 02084 // 02085 // The caller corrupted the saved verifier field. 02086 // 02087 02088 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02089 0x53, 02090 (ULONG_PTR)VirtualAddress, 02091 (ULONG_PTR)Header, 02092 (ULONG_PTR)Verifier); 02093 } 02094 02095 Index = Header->ListIndex; 02096 02097 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 02098 02099 ViReleasePoolAllocation (Verifier, 02100 VirtualAddress, 02101 Index, 02102 ChargedBytes); 02103 02104 if (CheckType == PagedPool) { 02105 Verifier->PagedBytes -= ChargedBytes; 02106 Verifier->CurrentPagedPoolAllocations -= 1; 02107 02108 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 02109 02110 ExAcquireFastMutex (&VerifierPoolMutex); 02111 MmVerifierData.PagedBytes -= ChargedBytes; 02112 MmVerifierData.CurrentPagedPoolAllocations -= 1; 02113 ExReleaseFastMutex (&VerifierPoolMutex); 02114 } 02115 else { 02116 Verifier->NonPagedBytes -= ChargedBytes; 02117 Verifier->CurrentNonPagedPoolAllocations -= 1; 02118 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 02119 02120 ExAcquireSpinLock (&VerifierPoolLock, &OldIrql); 02121 MmVerifierData.NonPagedBytes -= ChargedBytes; 02122 MmVerifierData.CurrentNonPagedPoolAllocations -= 1; 02123 ExReleaseSpinLock (&VerifierPoolLock, OldIrql); 02124 } 02125 } 02126 02127 THUNKED_API 02128 VOID 02129 VerifierFreePool( 02130 IN PVOID P 02131 ) 02132 { 02133 if (KernelVerifier == TRUE) { 02134 ExFreePool (P); 02135 return; 02136 } 02137 02138 VerifierFreePoolWithTag (P, 0); 02139 } 02140 02141 THUNKED_API 02142 VOID 02143 VerifierFreePoolWithTag( 02144 IN PVOID P, 02145 IN ULONG TagToFree 02146 ) 02147 { 02148 if (KernelVerifier == TRUE) { 02149 ExFreePoolWithTag (P, TagToFree); 02150 return; 02151 } 02152 02153 ExFreePoolSanityChecks (P); 02154 02155 ExFreePoolWithTag (P, TagToFree); 02156 } 02157 02158 THUNKED_API 02159 LONG 02160 VerifierSetEvent ( 02161 IN PRKEVENT Event, 02162 IN KPRIORITY Increment, 02163 IN BOOLEAN Wait 02164 ) 02165 { 02166 KIRQL CurrentIrql; 02167 02168 CurrentIrql = KeGetCurrentIrql(); 02169 if (CurrentIrql > DISPATCH_LEVEL) { 02170 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02171 0x80, 02172 CurrentIrql, 02173 (ULONG_PTR)Event, 02174 (ULONG_PTR)0); 02175 } 02176 02177 return KeSetEvent (Event, Increment, Wait); 02178 } 02179 02180 THUNKED_API 02181 BOOLEAN 02182 VerifierExAcquireResourceExclusive( 02183 IN PERESOURCE Resource, 02184 IN BOOLEAN Wait 02185 ) 02186 { 02187 KIRQL CurrentIrql; 02188 02189 CurrentIrql = KeGetCurrentIrql (); 02190 02191 if ((CurrentIrql != APC_LEVEL) && 02192 (!IS_SYSTEM_THREAD(PsGetCurrentThread())) && 02193 (KeGetCurrentThread()->KernelApcDisable == 0)) { 02194 02195 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02196 0x37, 02197 CurrentIrql, 02198 (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable), 02199 (ULONG_PTR)Resource); 02200 } 02201 02202 return ExAcquireResourceExclusiveLite (Resource, Wait); 02203 } 02204 02205 THUNKED_API 02206 VOID 02207 FASTCALL 02208 VerifierExReleaseResource( 02209 IN PERESOURCE Resource 02210 ) 02211 { 02212 KIRQL CurrentIrql; 02213 02214 CurrentIrql = KeGetCurrentIrql (); 02215 02216 if ((CurrentIrql != APC_LEVEL) && 02217 (!IS_SYSTEM_THREAD(PsGetCurrentThread())) && 02218 (KeGetCurrentThread()->KernelApcDisable == 0)) { 02219 02220 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02221 0x38, 02222 CurrentIrql, 02223 (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable), 02224 (ULONG_PTR)Resource); 02225 } 02226 02227 ExReleaseResourceLite (Resource); 02228 } 02229 02230 int VerifierIrqlData[0x10]; 02231 02232 VOID 02233 KfSanityCheckRaiseIrql ( 02234 IN KIRQL NewIrql 02235 ) 02236 { 02237 KIRQL CurrentIrql; 02238 02239 // 02240 // Check for the caller inadvertently lowering. 02241 // 02242 02243 CurrentIrql = KeGetCurrentIrql (); 02244 02245 if (CurrentIrql == NewIrql) { 02246 VerifierIrqlData[0] += 1; 02247 if (CurrentIrql == APC_LEVEL) { 02248 VerifierIrqlData[1] += 1; 02249 } 02250 else if (CurrentIrql == DISPATCH_LEVEL) { 02251 VerifierIrqlData[2] += 1; 02252 } 02253 else { 02254 VerifierIrqlData[3] += 1; 02255 } 02256 } 02257 else { 02258 VerifierIrqlData[4] += 1; 02259 } 02260 02261 if (CurrentIrql > NewIrql) { 02262 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02263 0x30, 02264 CurrentIrql, 02265 NewIrql, 02266 0); 02267 } 02268 02269 // 02270 // Check for the caller using an uninitialized variable. 02271 // 02272 02273 if (NewIrql > HIGH_LEVEL) { 02274 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02275 0x30, 02276 CurrentIrql, 02277 NewIrql, 02278 0); 02279 } 02280 } 02281 02282 VOID 02283 KfSanityCheckLowerIrql ( 02284 IN KIRQL NewIrql 02285 ) 02286 { 02287 KIRQL CurrentIrql; 02288 02289 // 02290 // Check for the caller inadvertently lowering. 02291 // 02292 02293 CurrentIrql = KeGetCurrentIrql (); 02294 02295 if (CurrentIrql == NewIrql) { 02296 VerifierIrqlData[8] += 1; 02297 if (CurrentIrql == APC_LEVEL) { 02298 VerifierIrqlData[9] += 1; 02299 } 02300 else if (CurrentIrql == DISPATCH_LEVEL) { 02301 VerifierIrqlData[10] += 1; 02302 } 02303 else { 02304 VerifierIrqlData[11] += 1; 02305 } 02306 } 02307 else { 02308 VerifierIrqlData[12] += 1; 02309 } 02310 02311 if (CurrentIrql < NewIrql) { 02312 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02313 0x31, 02314 CurrentIrql, 02315 NewIrql, 02316 0); 02317 } 02318 02319 // 02320 // Check for the caller using an uninitialized variable. 02321 // 02322 02323 if (NewIrql > HIGH_LEVEL) { 02324 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02325 0x31, 02326 CurrentIrql, 02327 NewIrql, 02328 0); 02329 } 02330 } 02331 02332 VOID 02333 ViTrimAllSystemPagableMemory ( 02334 VOID 02335 ) 02336 { 02337 LARGE_INTEGER CurrentTime; 02338 LOGICAL PageOut; 02339 02340 PageOut = TRUE; 02341 if (KernelVerifier == TRUE) { 02342 KeQueryTickCount(&CurrentTime); 02343 if ((CurrentTime.LowPart & KernelVerifierTickPage) != 0) { 02344 PageOut = FALSE; 02345 } 02346 } 02347 02348 if ((PageOut == TRUE) && (MiNoPageOnRaiseIrql == 0)) { 02349 MmVerifierData.TrimRequests += 1; 02350 if (MmTrimAllSystemPagableMemory (FALSE) == TRUE) { 02351 MmVerifierData.Trims += 1; 02352 } 02353 } 02354 } 02355 02356 typedef 02357 VOID 02358 (*PKE_ACQUIRE_SPINLOCK) ( 02359 IN PKSPIN_LOCK SpinLock, 02360 OUT PKIRQL OldIrql 02361 ); 02362 02363 THUNKED_API 02364 VOID 02365 VerifierKeAcquireSpinLock ( 02366 IN PKSPIN_LOCK SpinLock, 02367 OUT PKIRQL OldIrql 02368 ) 02369 { 02370 KIRQL CurrentIrql; 02371 PKE_ACQUIRE_SPINLOCK HalRoutine; 02372 02373 CurrentIrql = KeGetCurrentIrql (); 02374 02375 KfSanityCheckRaiseIrql (DISPATCH_LEVEL); 02376 02377 MmVerifierData.AcquireSpinLocks += 1; 02378 02379 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 02380 if (CurrentIrql < DISPATCH_LEVEL) { 02381 ViTrimAllSystemPagableMemory (); 02382 } 02383 } 02384 02385 #if defined (_X86_) 02386 HalRoutine = (PKE_ACQUIRE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_ACQUIRE_SPINLOCK]; 02387 02388 if (HalRoutine) { 02389 (*HalRoutine)(SpinLock, OldIrql); 02390 return; 02391 } 02392 #endif 02393 02394 KeAcquireSpinLock (SpinLock, OldIrql); 02395 } 02396 02397 typedef 02398 VOID 02399 (*PKE_RELEASE_SPINLOCK) ( 02400 IN PKSPIN_LOCK SpinLock, 02401 IN KIRQL NewIrql 02402 ); 02403 02404 THUNKED_API 02405 VOID 02406 VerifierKeReleaseSpinLock ( 02407 IN PKSPIN_LOCK SpinLock, 02408 IN KIRQL NewIrql 02409 ) 02410 { 02411 KIRQL CurrentIrql; 02412 PKE_RELEASE_SPINLOCK HalRoutine; 02413 02414 CurrentIrql = KeGetCurrentIrql (); 02415 02416 // 02417 // Caller better still be at DISPATCH_LEVEL when releasing the spinlock 02418 // 02419 02420 if (CurrentIrql != DISPATCH_LEVEL) { 02421 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02422 0x32, 02423 CurrentIrql, 02424 (ULONG_PTR)SpinLock, 02425 0); 02426 } 02427 02428 KfSanityCheckLowerIrql (NewIrql); 02429 02430 #if defined (_X86_) 02431 HalRoutine = (PKE_RELEASE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_RELEASE_SPINLOCK]; 02432 02433 if (HalRoutine) { 02434 (*HalRoutine)(SpinLock, NewIrql); 02435 return; 02436 } 02437 #endif 02438 02439 KeReleaseSpinLock (SpinLock, NewIrql); 02440 } 02441 02442 #if defined (_X86_) 02443 02444 typedef 02445 KIRQL 02446 (FASTCALL *PKF_ACQUIRE_SPINLOCK) ( 02447 IN PKSPIN_LOCK SpinLock 02448 ); 02449 02450 THUNKED_API 02451 KIRQL 02452 FASTCALL 02453 VerifierKfAcquireSpinLock ( 02454 IN PKSPIN_LOCK SpinLock 02455 ) 02456 { 02457 KIRQL CurrentIrql; 02458 PKF_ACQUIRE_SPINLOCK HalRoutine; 02459 02460 CurrentIrql = KeGetCurrentIrql (); 02461 02462 KfSanityCheckRaiseIrql (DISPATCH_LEVEL); 02463 02464 MmVerifierData.AcquireSpinLocks += 1; 02465 02466 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 02467 if (CurrentIrql < DISPATCH_LEVEL) { 02468 ViTrimAllSystemPagableMemory (); 02469 } 02470 } 02471 02472 #if defined (_X86_) 02473 HalRoutine = (PKF_ACQUIRE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_ACQUIRE_SPINLOCK]; 02474 02475 if (HalRoutine) { 02476 return (*HalRoutine)(SpinLock); 02477 } 02478 #endif 02479 02480 CurrentIrql = KfAcquireSpinLock (SpinLock); 02481 02482 return CurrentIrql; 02483 } 02484 02485 typedef 02486 VOID 02487 (FASTCALL *PKF_RELEASE_SPINLOCK) ( 02488 IN PKSPIN_LOCK SpinLock, 02489 IN KIRQL NewIrql 02490 ); 02491 02492 THUNKED_API 02493 VOID 02494 FASTCALL 02495 VerifierKfReleaseSpinLock ( 02496 IN PKSPIN_LOCK SpinLock, 02497 IN KIRQL NewIrql 02498 ) 02499 { 02500 KIRQL CurrentIrql; 02501 PKF_RELEASE_SPINLOCK HalRoutine; 02502 02503 CurrentIrql = KeGetCurrentIrql (); 02504 02505 // 02506 // Caller better still be at DISPATCH_LEVEL when releasing the spinlock. 02507 // 02508 02509 if (KernelVerifier == TRUE) { 02510 if (CurrentIrql < DISPATCH_LEVEL) { 02511 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02512 0x35, 02513 CurrentIrql, 02514 (ULONG_PTR)SpinLock, 02515 NewIrql); 02516 } 02517 } 02518 else { 02519 if (CurrentIrql != DISPATCH_LEVEL) { 02520 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02521 0x32, 02522 CurrentIrql, 02523 (ULONG_PTR)SpinLock, 02524 NewIrql); 02525 } 02526 } 02527 02528 KfSanityCheckLowerIrql (NewIrql); 02529 02530 #if defined (_X86_) 02531 HalRoutine = (PKF_RELEASE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_RELEASE_SPINLOCK]; 02532 02533 if (HalRoutine) { 02534 (*HalRoutine)(SpinLock, NewIrql); 02535 return; 02536 } 02537 #endif 02538 02539 KfReleaseSpinLock (SpinLock, NewIrql); 02540 } 02541 02542 02543 #if !defined(NT_UP) 02544 02545 typedef 02546 KIRQL 02547 (FASTCALL *PKE_ACQUIRE_QUEUED_SPINLOCK) ( 02548 IN KSPIN_LOCK_QUEUE_NUMBER Number 02549 ); 02550 02551 THUNKED_API 02552 KIRQL 02553 FASTCALL 02554 VerifierKeAcquireQueuedSpinLock ( 02555 IN KSPIN_LOCK_QUEUE_NUMBER Number 02556 ) 02557 { 02558 KIRQL CurrentIrql; 02559 PKE_ACQUIRE_QUEUED_SPINLOCK HalRoutine; 02560 02561 CurrentIrql = KeGetCurrentIrql (); 02562 02563 KfSanityCheckRaiseIrql (DISPATCH_LEVEL); 02564 02565 MmVerifierData.AcquireSpinLocks += 1; 02566 02567 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 02568 if (CurrentIrql < DISPATCH_LEVEL) { 02569 ViTrimAllSystemPagableMemory (); 02570 } 02571 } 02572 02573 #if defined (_X86_) 02574 HalRoutine = (PKE_ACQUIRE_QUEUED_SPINLOCK) MiKernelVerifierOriginalCalls[VI_KE_ACQUIRE_QUEUED_SPINLOCK]; 02575 02576 if (HalRoutine) { 02577 return (*HalRoutine)(Number); 02578 } 02579 #endif 02580 02581 CurrentIrql = KeAcquireQueuedSpinLock (Number); 02582 02583 return CurrentIrql; 02584 } 02585 02586 typedef 02587 VOID 02588 (FASTCALL *PKE_RELEASE_QUEUED_SPINLOCK) ( 02589 IN KSPIN_LOCK_QUEUE_NUMBER Number, 02590 IN KIRQL OldIrql 02591 ); 02592 02593 THUNKED_API 02594 VOID 02595 FASTCALL 02596 VerifierKeReleaseQueuedSpinLock ( 02597 IN KSPIN_LOCK_QUEUE_NUMBER Number, 02598 IN KIRQL OldIrql 02599 ) 02600 { 02601 KIRQL CurrentIrql; 02602 PKE_RELEASE_QUEUED_SPINLOCK HalRoutine; 02603 02604 CurrentIrql = KeGetCurrentIrql (); 02605 02606 if (KernelVerifier == TRUE) { 02607 if (CurrentIrql < DISPATCH_LEVEL) { 02608 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02609 0x36, 02610 CurrentIrql, 02611 (ULONG_PTR)Number, 02612 (ULONG_PTR)OldIrql); 02613 } 02614 } 02615 02616 KfSanityCheckLowerIrql (OldIrql); 02617 02618 #if defined (_X86_) 02619 HalRoutine = (PKE_RELEASE_QUEUED_SPINLOCK) MiKernelVerifierOriginalCalls[VI_KE_RELEASE_QUEUED_SPINLOCK]; 02620 02621 if (HalRoutine) { 02622 (*HalRoutine)(Number, OldIrql); 02623 return; 02624 } 02625 #endif 02626 02627 KeReleaseQueuedSpinLock (Number, OldIrql); 02628 } 02629 #endif 02630 02631 typedef 02632 KIRQL 02633 (FASTCALL *PKF_RAISE_IRQL) ( 02634 IN KIRQL NewIrql 02635 ); 02636 02637 THUNKED_API 02638 KIRQL 02639 FASTCALL 02640 VerifierKfRaiseIrql ( 02641 IN KIRQL NewIrql 02642 ) 02643 { 02644 PKF_RAISE_IRQL HalRoutine; 02645 KIRQL CurrentIrql; 02646 02647 CurrentIrql = KeGetCurrentIrql (); 02648 02649 KfSanityCheckRaiseIrql (NewIrql); 02650 02651 MmVerifierData.RaiseIrqls += 1; 02652 02653 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 02654 if ((CurrentIrql < DISPATCH_LEVEL) && (NewIrql >= DISPATCH_LEVEL)) { 02655 ViTrimAllSystemPagableMemory (); 02656 } 02657 } 02658 02659 #if defined (_X86_) 02660 HalRoutine = (PKF_RAISE_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_RAISE_IRQL]; 02661 if (HalRoutine) { 02662 return (*HalRoutine)(NewIrql); 02663 } 02664 #endif 02665 02666 return KfRaiseIrql (NewIrql); 02667 } 02668 02669 typedef 02670 VOID 02671 (FASTCALL *PKF_LOWER_IRQL) ( 02672 IN KIRQL NewIrql 02673 ); 02674 02675 THUNKED_API 02676 VOID 02677 FASTCALL 02678 VerifierKfLowerIrql ( 02679 IN KIRQL NewIrql 02680 ) 02681 { 02682 PKF_LOWER_IRQL HalRoutine; 02683 02684 KfSanityCheckLowerIrql (NewIrql); 02685 02686 #if defined (_X86_) 02687 HalRoutine = (PKF_LOWER_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_LOWER_IRQL]; 02688 if (HalRoutine) { 02689 (*HalRoutine)(NewIrql); 02690 return; 02691 } 02692 #endif 02693 02694 KfLowerIrql (NewIrql); 02695 } 02696 02697 #endif 02698 02699 #if defined(_ALPHA_) 02700 THUNKED_API 02701 VOID 02702 VerifierKeAcquireSpinLockAtDpcLevel ( 02703 IN PKSPIN_LOCK SpinLock 02704 ) 02705 { 02706 KIRQL CurrentIrql; 02707 02708 CurrentIrql = KeGetCurrentIrql (); 02709 02710 // 02711 // Caller better be at DISPATCH_LEVEL. 02712 // 02713 02714 if (CurrentIrql != DISPATCH_LEVEL) { 02715 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02716 0x40, 02717 CurrentIrql, 02718 (ULONG_PTR)SpinLock, 02719 0); 02720 } 02721 02722 MmVerifierData.AcquireSpinLocks += 1; 02723 02724 KeAcquireSpinLockAtDpcLevel (SpinLock); 02725 } 02726 02727 THUNKED_API 02728 VOID 02729 VerifierKeReleaseSpinLockFromDpcLevel ( 02730 IN PKSPIN_LOCK SpinLock 02731 ) 02732 { 02733 KIRQL CurrentIrql; 02734 02735 CurrentIrql = KeGetCurrentIrql (); 02736 02737 // 02738 // Caller better be at DISPATCH_LEVEL. 02739 // 02740 02741 if (CurrentIrql != DISPATCH_LEVEL) { 02742 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02743 0x41, 02744 CurrentIrql, 02745 (ULONG_PTR)SpinLock, 02746 0); 02747 } 02748 02749 KeReleaseSpinLockFromDpcLevel (SpinLock); 02750 } 02751 02752 THUNKED_API 02753 KIRQL 02754 VerifierKeAcquireSpinLockRaiseToDpc ( 02755 IN PKSPIN_LOCK SpinLock 02756 ) 02757 { 02758 KIRQL CurrentIrql; 02759 02760 CurrentIrql = KeGetCurrentIrql (); 02761 02762 // 02763 // Caller better be at or below DISPATCH_LEVEL. 02764 // 02765 02766 if (CurrentIrql > DISPATCH_LEVEL) { 02767 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02768 0x42, 02769 CurrentIrql, 02770 (ULONG_PTR)SpinLock, 02771 0); 02772 } 02773 02774 MmVerifierData.AcquireSpinLocks += 1; 02775 02776 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 02777 if (CurrentIrql < DISPATCH_LEVEL) { 02778 ViTrimAllSystemPagableMemory (); 02779 } 02780 } 02781 02782 return KeAcquireSpinLockRaiseToDpc (SpinLock); 02783 } 02784 #endif 02785 02786 THUNKED_API 02787 BOOLEAN 02788 FASTCALL 02789 VerifierExTryToAcquireFastMutex ( 02790 IN PFAST_MUTEX FastMutex 02791 ) 02792 { 02793 KIRQL CurrentIrql; 02794 02795 CurrentIrql = KeGetCurrentIrql (); 02796 02797 // 02798 // Caller better be at or below APC_LEVEL or have APCs blocked. 02799 // 02800 02801 if (CurrentIrql > APC_LEVEL) { 02802 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02803 0x33, 02804 CurrentIrql, 02805 (ULONG_PTR)FastMutex, 02806 0); 02807 } 02808 02809 return ExTryToAcquireFastMutex (FastMutex); 02810 } 02811 02812 THUNKED_API 02813 VOID 02814 FASTCALL 02815 VerifierExAcquireFastMutex ( 02816 IN PFAST_MUTEX FastMutex 02817 ) 02818 { 02819 KIRQL CurrentIrql; 02820 02821 CurrentIrql = KeGetCurrentIrql (); 02822 02823 // 02824 // Caller better be at or below APC_LEVEL or have APCs blocked. 02825 // 02826 02827 if (CurrentIrql > APC_LEVEL) { 02828 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02829 0x33, 02830 CurrentIrql, 02831 (ULONG_PTR)FastMutex, 02832 0); 02833 } 02834 02835 ExAcquireFastMutex (FastMutex); 02836 } 02837 02838 THUNKED_API 02839 VOID 02840 FASTCALL 02841 VerifierExAcquireFastMutexUnsafe ( 02842 IN PFAST_MUTEX FastMutex 02843 ) 02844 { 02845 KIRQL CurrentIrql; 02846 02847 CurrentIrql = KeGetCurrentIrql (); 02848 02849 // 02850 // Caller better be at APC_LEVEL or have APCs blocked. 02851 // 02852 02853 if ((CurrentIrql != APC_LEVEL) && 02854 (!IS_SYSTEM_THREAD(PsGetCurrentThread())) && 02855 (KeGetCurrentThread()->KernelApcDisable == 0)) { 02856 02857 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02858 0x39, 02859 CurrentIrql, 02860 (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable), 02861 (ULONG_PTR)FastMutex); 02862 } 02863 02864 ExAcquireFastMutexUnsafe (FastMutex); 02865 } 02866 02867 THUNKED_API 02868 VOID 02869 FASTCALL 02870 VerifierExReleaseFastMutex ( 02871 IN PFAST_MUTEX FastMutex 02872 ) 02873 { 02874 KIRQL CurrentIrql; 02875 02876 CurrentIrql = KeGetCurrentIrql (); 02877 02878 // 02879 // Caller better be at APC_LEVEL or have APCs blocked. 02880 // 02881 02882 if ((CurrentIrql != APC_LEVEL) && 02883 (!IS_SYSTEM_THREAD(PsGetCurrentThread())) && 02884 (KeGetCurrentThread()->KernelApcDisable == 0)) { 02885 02886 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02887 0x34, 02888 CurrentIrql, 02889 (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable), 02890 (ULONG_PTR)FastMutex); 02891 } 02892 02893 ExReleaseFastMutex (FastMutex); 02894 } 02895 02896 THUNKED_API 02897 VOID 02898 FASTCALL 02899 VerifierExReleaseFastMutexUnsafe ( 02900 IN PFAST_MUTEX FastMutex 02901 ) 02902 { 02903 KIRQL CurrentIrql; 02904 02905 CurrentIrql = KeGetCurrentIrql (); 02906 02907 // 02908 // Caller better be at APC_LEVEL or have APCs blocked. 02909 // 02910 02911 if ((CurrentIrql != APC_LEVEL) && 02912 (!IS_SYSTEM_THREAD(PsGetCurrentThread())) && 02913 (KeGetCurrentThread()->KernelApcDisable == 0)) { 02914 02915 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 02916 0x3A, 02917 CurrentIrql, 02918 (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable), 02919 (ULONG_PTR)FastMutex); 02920 } 02921 02922 ExReleaseFastMutexUnsafe (FastMutex); 02923 } 02924 02925 typedef 02926 VOID 02927 (*PKE_RAISE_IRQL) ( 02928 IN KIRQL NewIrql, 02929 OUT PKIRQL OldIrql 02930 ); 02931 02932 THUNKED_API 02933 VOID 02934 VerifierKeRaiseIrql ( 02935 IN KIRQL NewIrql, 02936 OUT PKIRQL OldIrql 02937 ) 02938 { 02939 PKE_RAISE_IRQL HalRoutine; 02940 02941 *OldIrql = KeGetCurrentIrql (); 02942 02943 KfSanityCheckRaiseIrql (NewIrql); 02944 02945 MmVerifierData.RaiseIrqls += 1; 02946 02947 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 02948 if ((*OldIrql < DISPATCH_LEVEL) && (NewIrql >= DISPATCH_LEVEL)) { 02949 ViTrimAllSystemPagableMemory (); 02950 } 02951 } 02952 02953 #if defined (_X86_) 02954 HalRoutine = (PKE_RAISE_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_RAISE_IRQL]; 02955 if (HalRoutine) { 02956 (*HalRoutine)(NewIrql, OldIrql); 02957 return; 02958 } 02959 #endif 02960 02961 KeRaiseIrql (NewIrql, OldIrql); 02962 } 02963 02964 typedef 02965 VOID 02966 (*PKE_LOWER_IRQL) ( 02967 IN KIRQL NewIrql 02968 ); 02969 02970 THUNKED_API 02971 VOID 02972 VerifierKeLowerIrql ( 02973 IN KIRQL NewIrql 02974 ) 02975 { 02976 PKE_LOWER_IRQL HalRoutine; 02977 02978 KfSanityCheckLowerIrql (NewIrql); 02979 02980 #if defined (_X86_) 02981 HalRoutine = (PKE_LOWER_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_LOWER_IRQL]; 02982 if (HalRoutine) { 02983 (*HalRoutine)(NewIrql); 02984 return; 02985 } 02986 #endif 02987 02988 KeLowerIrql (NewIrql); 02989 } 02990 02991 THUNKED_API 02992 BOOLEAN 02993 VerifierSynchronizeExecution ( 02994 IN PKINTERRUPT Interrupt, 02995 IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, 02996 IN PVOID SynchronizeContext 02997 ) 02998 { 02999 KIRQL OldIrql; 03000 03001 OldIrql = KeGetCurrentIrql (); 03002 03003 KfSanityCheckRaiseIrql (Interrupt->SynchronizeIrql); 03004 03005 MmVerifierData.SynchronizeExecutions += 1; 03006 03007 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 03008 if ((OldIrql < DISPATCH_LEVEL) && (Interrupt->SynchronizeIrql >= DISPATCH_LEVEL)) { 03009 ViTrimAllSystemPagableMemory (); 03010 } 03011 } 03012 03013 return KeSynchronizeExecution (Interrupt, 03014 SynchronizeRoutine, 03015 SynchronizeContext); 03016 } 03017 03018 THUNKED_API 03019 VOID 03020 VerifierKeInitializeTimerEx( 03021 IN PKTIMER Timer, 03022 IN TIMER_TYPE Type 03023 ) 03024 { 03025 // 03026 // Check the object being initialized isn't already an 03027 // active timer. Make sure the timer table list is initialized. 03028 // 03029 03030 if (KiTimerTableListHead[0].Flink != NULL) { 03031 KeCheckForTimer(Timer, sizeof(KTIMER)); 03032 } 03033 03034 KeInitializeTimerEx(Timer, Type); 03035 } 03036 03037 THUNKED_API 03038 VOID 03039 VerifierKeInitializeTimer( 03040 IN PKTIMER Timer 03041 ) 03042 { 03043 VerifierKeInitializeTimerEx(Timer, NotificationTimer); 03044 } 03045 03046 VOID 03047 ViInitializeEntry ( 03048 IN PMI_VERIFIER_DRIVER_ENTRY Verifier, 03049 IN LOGICAL FirstLoad 03050 ) 03051 03052 /*++ 03053 03054 Routine Description: 03055 03056 Initialize various verifier fields as the driver is being (re)loaded now. 03057 03058 Arguments: 03059 03060 Verifier - Supplies the verifier entry to be initialized. 03061 03062 FirstLoad - Supplies TRUE if this is the first load of this driver. 03063 03064 Return Value: 03065 03066 None. 03067 03068 --*/ 03069 03070 { 03071 KIRQL OldIrql; 03072 03073 // 03074 // Only the BaseName field is initialized on entry. 03075 // 03076 03077 KeInitializeSpinLock (&Verifier->VerifierPoolLock); 03078 03079 Verifier->CurrentPagedPoolAllocations = 0; 03080 Verifier->CurrentNonPagedPoolAllocations = 0; 03081 Verifier->PeakPagedPoolAllocations = 0; 03082 Verifier->PeakNonPagedPoolAllocations = 0; 03083 03084 Verifier->PagedBytes = 0; 03085 Verifier->NonPagedBytes = 0; 03086 Verifier->PeakPagedBytes = 0; 03087 Verifier->PeakNonPagedBytes = 0; 03088 03089 Verifier->PoolHash = NULL; 03090 Verifier->PoolHashSize = 0; 03091 Verifier->PoolHashFree = VI_POOL_FREELIST_END; 03092 Verifier->PoolHashReserved = 0; 03093 03094 Verifier->Signature = MI_VERIFIER_ENTRY_SIGNATURE; 03095 03096 if (FirstLoad == TRUE) { 03097 Verifier->Flags = 0; 03098 Verifier->Loads = 0; 03099 Verifier->Unloads = 0; 03100 } 03101 03102 ExAcquireSpinLock (&VerifierListLock, &OldIrql); 03103 Verifier->StartAddress = NULL; 03104 Verifier->EndAddress = NULL; 03105 ExReleaseSpinLock (&VerifierListLock, OldIrql); 03106 } 03107 03108 #define UNICODE_TAB 0x0009 03109 #define UNICODE_LF 0x000A 03110 #define UNICODE_CR 0x000D 03111 #define UNICODE_SPACE 0x0020 03112 #define UNICODE_CJK_SPACE 0x3000 03113 03114 #define UNICODE_WHITESPACE(_ch) (((_ch) == UNICODE_TAB) || \ 03115 ((_ch) == UNICODE_LF) || \ 03116 ((_ch) == UNICODE_CR) || \ 03117 ((_ch) == UNICODE_SPACE) || \ 03118 ((_ch) == UNICODE_CJK_SPACE)) 03119 03120 LOGICAL 03121 MiInitializeDriverVerifierList ( 03122 IN PLOADER_PARAMETER_BLOCK LoaderBlock 03123 ) 03124 03125 /*++ 03126 03127 Routine Description: 03128 03129 Parse the registry setting and set up the list of driver names that will 03130 be put through the validation process. 03131 03132 Walk the loaded module list and thunk any drivers that need/deserve it. 03133 03134 Arguments: 03135 03136 None. 03137 03138 Return Value: 03139 03140 TRUE if successful, FALSE if not. 03141 03142 Environment: 03143 03144 Kernel mode, Phase 0 Initialization. 03145 03146 Nonpaged (but not paged) pool exists. 03147 03148 The PsLoadedModuleList has not been set up yet although the boot drivers 03149 have been relocated to their final resting places. 03150 03151 --*/ 03152 03153 { 03154 ULONG i; 03155 PLIST_ENTRY NextEntry; 03156 PLDR_DATA_TABLE_ENTRY DataTableEntry; 03157 PWCHAR Start; 03158 PWCHAR End; 03159 PWCHAR Walk; 03160 ULONG NameLength; 03161 PMI_VERIFIER_DRIVER_ENTRY Verifier; 03162 LARGE_INTEGER CurrentTime; 03163 UNICODE_STRING KernelString; 03164 UNICODE_STRING HalString; 03165 PMI_VERIFIER_DRIVER_ENTRY KernelEntry; 03166 PMI_VERIFIER_DRIVER_ENTRY HalEntry; 03167 03168 InitializeListHead (&MiSuspectDriverList); 03169 03170 if (MmVerifyDriverLevel != (ULONG)-1) { 03171 if (MmVerifyDriverLevel & DRIVER_VERIFIER_IO_CHECKING) { 03172 if (MmVerifyDriverBufferLength == (ULONG)-1) { 03173 MmVerifyDriverBufferLength = 0; // Mm will not page out verifier pages. 03174 } 03175 } 03176 } 03177 03178 if (MmVerifyDriverBufferLength == (ULONG)-1) { 03179 03180 if (MmDontVerifyRandomDrivers == TRUE) { 03181 return FALSE; 03182 } 03183 03184 MmVerifyDriverBufferLength = 0; 03185 03186 CurrentTime = KeQueryPerformanceCounter (NULL); 03187 CurrentTime.LowPart = (CurrentTime.LowPart % 26); 03188 03189 MiVerifyRandomDrivers = (WCHAR)'A' + (WCHAR)CurrentTime.LowPart; 03190 03191 if ((MiVerifyRandomDrivers == (WCHAR)'H') || 03192 (MiVerifyRandomDrivers == (WCHAR)'J') || 03193 (MiVerifyRandomDrivers == (WCHAR)'X') || 03194 (MiVerifyRandomDrivers == (WCHAR)'Y') || 03195 (MiVerifyRandomDrivers == (WCHAR)'Z')) { 03196 MiVerifyRandomDrivers = (WCHAR)'X'; 03197 } 03198 } 03199 03200 KeInitializeSpinLock (&ViBadMapperLock); 03201 KeInitializeSpinLock (&VerifierListLock); 03202 03203 KeInitializeSpinLock (&VerifierPoolLock); 03204 ExInitializeFastMutex (&VerifierPoolMutex); 03205 03206 InitializeListHead (&MiVerifierDriverAddedThunkListHead); 03207 03208 // 03209 // If no default is specified, then special pool, pagable code/data 03210 // flushing and pool leak detection are enabled. 03211 // 03212 03213 if (MmVerifyDriverLevel == (ULONG)-1) { 03214 MmVerifierData.Level = DRIVER_VERIFIER_SPECIAL_POOLING | 03215 DRIVER_VERIFIER_FORCE_IRQL_CHECKING | 03216 DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS; 03217 } 03218 else { 03219 MmVerifierData.Level = MmVerifyDriverLevel; 03220 } 03221 03222 VerifierModifyableOptions = (DRIVER_VERIFIER_SPECIAL_POOLING | 03223 DRIVER_VERIFIER_FORCE_IRQL_CHECKING | 03224 DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES); 03225 03226 IoVerifierInit (MmVerifierData.Level, IOVERIFIERINIT_PHASE0 | 03227 IOVERIFIERINIT_EVERYTHING_TRACKED | 03228 IOVERIFIERINIT_VERIFIER_DRIVER_LIST); 03229 03230 KernelEntry = NULL; 03231 HalEntry = NULL; 03232 03233 if (MiVerifyRandomDrivers == (WCHAR)0) { 03234 03235 RtlInitUnicodeString (&KernelString, L"ntoskrnl.exe"); 03236 RtlInitUnicodeString (&HalString, L"hal.dll"); 03237 03238 Start = MmVerifyDriverBuffer; 03239 End = MmVerifyDriverBuffer + (MmVerifyDriverBufferLength - sizeof(WCHAR)) / sizeof(WCHAR); 03240 03241 while (Start < End) { 03242 if (UNICODE_WHITESPACE(*Start)) { 03243 Start += 1; 03244 continue; 03245 } 03246 03247 if (*Start == (WCHAR)'*') { 03248 MiVerifyAllDrivers = TRUE; 03249 break; 03250 } 03251 03252 for (Walk = Start; Walk < End; Walk += 1) { 03253 if (UNICODE_WHITESPACE(*Walk)) { 03254 break; 03255 } 03256 } 03257 03258 // 03259 // Got a string. Save it. 03260 // 03261 03262 NameLength = (ULONG)(Walk - Start + 1) * sizeof (WCHAR); 03263 03264 Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag ( 03265 NonPagedPool, 03266 sizeof (MI_VERIFIER_DRIVER_ENTRY) + 03267 NameLength, 03268 'dLmM'); 03269 03270 if (Verifier == NULL) { 03271 break; 03272 } 03273 03274 Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier + 03275 sizeof (MI_VERIFIER_DRIVER_ENTRY)); 03276 Verifier->BaseName.Length = (USHORT)NameLength - sizeof (UNICODE_NULL); 03277 Verifier->BaseName.MaximumLength = (USHORT)NameLength; 03278 03279 RtlMoveMemory (Verifier->BaseName.Buffer, 03280 Start, 03281 NameLength - sizeof (UNICODE_NULL)); 03282 03283 ViInitializeEntry (Verifier, TRUE); 03284 03285 Verifier->Flags |= VI_VERIFYING_DIRECTLY; 03286 03287 ViInsertVerifierEntry (Verifier); 03288 03289 if (RtlEqualUnicodeString (&KernelString, 03290 &Verifier->BaseName, 03291 TRUE)) { 03292 03293 // 03294 // All driver pool allocation calls must be intercepted so 03295 // they are not mistaken for kernel pool allocations. 03296 // 03297 03298 MiVerifyAllDrivers = TRUE; 03299 03300 KernelVerifier = TRUE; 03301 KernelEntry = Verifier; 03302 03303 } 03304 else if (RtlEqualUnicodeString (&HalString, 03305 &Verifier->BaseName, 03306 TRUE)) { 03307 HalEntry = Verifier; 03308 } 03309 03310 Start = Walk + 1; 03311 } 03312 } 03313 03314 if (MiTriageAddDrivers (LoaderBlock) == TRUE) { 03315 03316 // 03317 // Disable random driver verification if triage has picked driver(s). 03318 // 03319 03320 MiVerifyRandomDrivers = (WCHAR)0; 03321 } 03322 03323 // 03324 // Process the boot-loaded drivers now. 03325 // 03326 03327 i = 0; 03328 NextEntry = LoaderBlock->LoadOrderListHead.Flink; 03329 03330 for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) { 03331 03332 DataTableEntry = CONTAINING_RECORD(NextEntry, 03333 LDR_DATA_TABLE_ENTRY, 03334 InLoadOrderLinks); 03335 03336 // 03337 // Process the kernel and HAL specially. 03338 // 03339 03340 if (i == 0) { 03341 if (KernelEntry != NULL) { 03342 MiApplyDriverVerifier (DataTableEntry, KernelEntry); 03343 } 03344 } 03345 else if (i == 1) { 03346 if (HalEntry != NULL) { 03347 MiApplyDriverVerifier (DataTableEntry, HalEntry); 03348 } 03349 } 03350 else { 03351 MiApplyDriverVerifier (DataTableEntry, NULL); 03352 } 03353 i += 1; 03354 } 03355 03356 return TRUE; 03357 } 03358 03359 VOID 03360 ViInsertVerifierEntry ( 03361 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 03362 ) 03363 03364 /*++ 03365 03366 Routine Description: 03367 03368 Nonpagable wrapper to insert a new verifier entry. 03369 03370 Note that the system load mutant or the verifier load spinlock is sufficient 03371 for readers to access the list. This is because the insertion path 03372 acquires both. 03373 03374 Lock synchronization is needed because pool allocators walk the 03375 verifier list at DISPATCH_LEVEL. 03376 03377 Arguments: 03378 03379 Verifier - Supplies a caller-initialized entry for the driver. 03380 03381 Return Value: 03382 03383 None. 03384 03385 --*/ 03386 03387 { 03388 KIRQL OldIrql; 03389 03390 ExAcquireSpinLock (&VerifierListLock, &OldIrql); 03391 InsertTailList (&MiSuspectDriverList, &Verifier->Links); 03392 ExReleaseSpinLock (&VerifierListLock, OldIrql); 03393 } 03394 03395 PMI_VERIFIER_DRIVER_ENTRY 03396 ViLocateVerifierEntry ( 03397 IN PVOID SystemAddress 03398 ) 03399 03400 /*++ 03401 03402 Routine Description: 03403 03404 Locate the Driver Verifier entry for the specified system address. 03405 03406 Arguments: 03407 03408 SystemAddress - Supplies a code or data address within a driver. 03409 03410 Return Value: 03411 03412 The Verifier entry corresponding to the driver or NULL. 03413 03414 Environment: 03415 03416 The caller may be at DISPATCH_LEVEL and does not hold the MmSystemLoadLock. 03417 03418 --*/ 03419 03420 { 03421 KIRQL OldIrql; 03422 PLIST_ENTRY NextEntry; 03423 PMI_VERIFIER_DRIVER_ENTRY Verifier; 03424 03425 ExAcquireSpinLock (&VerifierListLock, &OldIrql); 03426 03427 NextEntry = MiSuspectDriverList.Flink; 03428 while (NextEntry != &MiSuspectDriverList) { 03429 03430 Verifier = CONTAINING_RECORD(NextEntry, 03431 MI_VERIFIER_DRIVER_ENTRY, 03432 Links); 03433 03434 if ((SystemAddress >= Verifier->StartAddress) && 03435 (SystemAddress < Verifier->EndAddress)) { 03436 03437 ExReleaseSpinLock (&VerifierListLock, OldIrql); 03438 return Verifier; 03439 } 03440 NextEntry = NextEntry->Flink; 03441 } 03442 03443 ExReleaseSpinLock (&VerifierListLock, OldIrql); 03444 return NULL; 03445 } 03446 03447 LOGICAL 03448 MiApplyDriverVerifier ( 03449 IN PLDR_DATA_TABLE_ENTRY DataTableEntry, 03450 IN PMI_VERIFIER_DRIVER_ENTRY Verifier 03451 ) 03452 03453 /*++ 03454 03455 Routine Description: 03456 03457 This function is called as each module is loaded. If the module being 03458 loaded is in the suspect list, thunk it here. 03459 03460 Arguments: 03461 03462 DataTableEntry - Supplies the data table entry for the module. 03463 03464 Verifier - Non-NULL if verification must be applied. FALSE indicates 03465 that the driver name must match for verification to be 03466 applied. 03467 03468 Return Value: 03469 03470 TRUE if thunking was applied, FALSE if not. 03471 03472 Environment: 03473 03474 Kernel mode, Phase 0 Initialization and normal runtime. 03475 Non paged pool exists in Phase0, but paged pool does not. 03476 Post-Phase0 serialization is provided by the MmSystemLoadLock. 03477 03478 --*/ 03479 03480 { 03481 WCHAR FirstChar; 03482 LOGICAL Found; 03483 PLIST_ENTRY NextEntry; 03484 ULONG VerifierFlags; 03485 03486 if (Verifier != NULL) { 03487 Found = TRUE; 03488 } 03489 else { 03490 Found = FALSE; 03491 NextEntry = MiSuspectDriverList.Flink; 03492 while (NextEntry != &MiSuspectDriverList) { 03493 03494 Verifier = CONTAINING_RECORD(NextEntry, 03495 MI_VERIFIER_DRIVER_ENTRY, 03496 Links); 03497 03498 if (RtlEqualUnicodeString (&Verifier->BaseName, 03499 &DataTableEntry->BaseDllName, 03500 TRUE)) { 03501 03502 Found = TRUE; 03503 ViInitializeEntry (Verifier, FALSE); 03504 break; 03505 } 03506 NextEntry = NextEntry->Flink; 03507 } 03508 } 03509 03510 if (Found == FALSE) { 03511 VerifierFlags = VI_VERIFYING_DIRECTLY; 03512 if (MiVerifyAllDrivers == TRUE) { 03513 if (KernelVerifier == TRUE) { 03514 VerifierFlags = VI_VERIFYING_INVERSELY; 03515 } 03516 Found = TRUE; 03517 } 03518 else if (MiVerifyRandomDrivers != (WCHAR)0) { 03519 03520 // 03521 // Wildcard match drivers randomly. 03522 // 03523 03524 FirstChar = RtlUpcaseUnicodeChar(DataTableEntry->BaseDllName.Buffer[0]); 03525 03526 if (MiVerifyRandomDrivers == FirstChar) { 03527 Found = TRUE; 03528 } 03529 else if (MiVerifyRandomDrivers == (WCHAR)'X') { 03530 if ((FirstChar >= (WCHAR)'0') && (FirstChar <= (WCHAR)'9')) { 03531 Found = TRUE; 03532 } 03533 } 03534 } 03535 03536 if (Found == FALSE) { 03537 return FALSE; 03538 } 03539 03540 Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag ( 03541 NonPagedPool, 03542 sizeof (MI_VERIFIER_DRIVER_ENTRY) + 03543 DataTableEntry->BaseDllName.MaximumLength, 03544 'dLmM'); 03545 03546 if (Verifier == NULL) { 03547 return FALSE; 03548 } 03549 03550 Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier + 03551 sizeof (MI_VERIFIER_DRIVER_ENTRY)); 03552 Verifier->BaseName.Length = DataTableEntry->BaseDllName.Length; 03553 Verifier->BaseName.MaximumLength = DataTableEntry->BaseDllName.MaximumLength; 03554 03555 RtlMoveMemory (Verifier->BaseName.Buffer, 03556 DataTableEntry->BaseDllName.Buffer, 03557 DataTableEntry->BaseDllName.Length); 03558 03559 ViInitializeEntry (Verifier, TRUE); 03560 03561 Verifier->Flags = VerifierFlags; 03562 03563 ViInsertVerifierEntry (Verifier); 03564 } 03565 03566 Verifier->StartAddress = DataTableEntry->DllBase; 03567 Verifier->EndAddress = (PVOID)((ULONG_PTR)DataTableEntry->DllBase + DataTableEntry->SizeOfImage); 03568 03569 if (MiEnableVerifier (DataTableEntry) == TRUE) { 03570 03571 if (Verifier->Flags & VI_VERIFYING_DIRECTLY) { 03572 ViPrintString (&DataTableEntry->BaseDllName); 03573 } 03574 03575 MmVerifierData.Loads += 1; 03576 03577 Verifier->Loads += 1; 03578 03579 DataTableEntry->Flags |= LDRP_IMAGE_VERIFYING; 03580 MiActiveVerifies += 1; 03581 03582 if (MiActiveVerifies == 1) { 03583 03584 // 03585 // Up the retry mechanism for potential injection failures. 03586 // 03587 03588 MiIoRetryLevel = (ULONG)-1; 03589 MiFaultRetries = MiIoRetryLevel; 03590 MiUserIoRetryLevel = (ULONG)-1; 03591 MiUserFaultRetries = MiUserIoRetryLevel; 03592 03593 #ifndef NO_POOL_CHECKS 03594 03595 // 03596 // If a loaded driver(s) is undergoing validation, the default 03597 // special pool randomizer is disabled as the precious virtual 03598 // address space and physical memory is being put to specific 03599 // use. 03600 // 03601 03602 MiEnableRandomSpecialPool (FALSE); 03603 #endif 03604 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 03605 03606 // 03607 // Page out all thread stacks as soon as possible to 03608 // catch drivers using local events that do usermode waits. 03609 // 03610 03611 if (KernelVerifier == FALSE) { 03612 MiVerifierStackProtectTime = KiStackProtectTime; 03613 KiStackProtectTime = 0; 03614 } 03615 } 03616 } 03617 } 03618 03619 return Found; 03620 } 03621 03622 PUNICODE_STRING ViBadDriver; 03623 03624 VOID 03625 MiVerifyingDriverUnloading ( 03626 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 03627 ) 03628 03629 /*++ 03630 03631 Routine Description: 03632 03633 This function is called as a driver that was being verified is now being 03634 unloaded. 03635 03636 Arguments: 03637 03638 DataTableEntry - Supplies the data table entry for the driver. 03639 03640 Return Value: 03641 03642 TRUE if thunking was applied, FALSE if not. 03643 03644 Environment: 03645 03646 Kernel mode, Phase 0 Initialization and normal runtime. 03647 Non paged pool exists in Phase0, but paged pool does not. 03648 Post-Phase0 serialization is provided by the MmSystemLoadLock. 03649 03650 --*/ 03651 03652 { 03653 KIRQL OldIrql; 03654 LOGICAL Found; 03655 PLIST_ENTRY NextEntry; 03656 PMI_VERIFIER_DRIVER_ENTRY Verifier; 03657 PVI_POOL_ENTRY OldHashTable; 03658 03659 Found = FALSE; 03660 NextEntry = MiSuspectDriverList.Flink; 03661 while (NextEntry != &MiSuspectDriverList) { 03662 03663 Verifier = CONTAINING_RECORD(NextEntry, 03664 MI_VERIFIER_DRIVER_ENTRY, 03665 Links); 03666 03667 if (RtlEqualUnicodeString (&Verifier->BaseName, 03668 &DataTableEntry->BaseDllName, 03669 TRUE)) { 03670 03671 Found = TRUE; 03672 break; 03673 } 03674 NextEntry = NextEntry->Flink; 03675 } 03676 03677 ASSERT (Found == TRUE); 03678 03679 if (MmVerifierData.Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) { 03680 03681 // 03682 // Better not be any pool left that wasn't freed. Walk the pagable 03683 // allocations in an attempt to make them all resident for a 03684 // kernel debugger session. 03685 // 03686 03687 if (Verifier->PagedBytes) { 03688 03689 #if DBG 03690 DbgPrint ("Driver %wZ leaked %d paged pool allocations (0x%x bytes)\n", 03691 &DataTableEntry->FullDllName, 03692 Verifier->CurrentPagedPoolAllocations, 03693 Verifier->PagedBytes); 03694 #endif 03695 03696 // 03697 // It would be nice to fault in the driver's paged pool allocations 03698 // now to make debugging easier, but this cannot be easily done 03699 // in a deadlock free manner. 03700 // 03701 // At least disable the paging of pool on IRQL raising in attempt 03702 // to keep some of these allocations resident for debugging. 03703 // No need to undo the increment as we're about to bugcheck anyway. 03704 // 03705 03706 InterlockedIncrement ((PLONG)&MiNoPageOnRaiseIrql); 03707 } 03708 03709 #if DBG 03710 if (Verifier->NonPagedBytes) { 03711 DbgPrint ("Driver %wZ leaked %d nonpaged pool allocations (0x%x bytes)\n", 03712 &DataTableEntry->FullDllName, 03713 Verifier->CurrentNonPagedPoolAllocations, 03714 Verifier->NonPagedBytes); 03715 } 03716 #endif 03717 03718 if (Verifier->PagedBytes || Verifier->NonPagedBytes) { 03719 #if 0 03720 DbgBreakPoint (); 03721 InterlockedDecrement (&MiNoPageOnRaiseIrql); 03722 #else 03723 // 03724 // Snap this so the build/BVT lab can easily triage the culprit. 03725 // 03726 03727 ViBadDriver = &Verifier->BaseName; 03728 03729 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 03730 0x60, 03731 Verifier->PagedBytes, 03732 Verifier->NonPagedBytes, 03733 Verifier->CurrentPagedPoolAllocations + 03734 Verifier->CurrentNonPagedPoolAllocations); 03735 #endif 03736 } 03737 03738 ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql); 03739 03740 if (Verifier->PoolHashReserved != 0) { 03741 KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION, 03742 0x61, 03743 Verifier->PagedBytes, 03744 Verifier->NonPagedBytes, 03745 Verifier->CurrentPagedPoolAllocations + 03746 Verifier->CurrentNonPagedPoolAllocations); 03747 } 03748 03749 OldHashTable = Verifier->PoolHash; 03750 if (OldHashTable != NULL) { 03751 Verifier->PoolHashSize = 0; 03752 Verifier->PoolHashFree = VI_POOL_FREELIST_END; 03753 Verifier->PoolHash = NULL; 03754 } 03755 else { 03756 ASSERT (Verifier->PoolHashSize == 0); 03757 ASSERT (Verifier->PoolHashFree == VI_POOL_FREELIST_END); 03758 } 03759 03760 ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql); 03761 03762 if (OldHashTable != NULL) { 03763 ExFreePool (OldHashTable); 03764 } 03765 03766 // 03767 // Clear these fields so reuse of stale addresses don't trigger 03768 // erroneous bucket fills. 03769 // 03770 03771 ExAcquireSpinLock (&VerifierListLock, &OldIrql); 03772 Verifier->StartAddress = NULL; 03773 Verifier->EndAddress = NULL; 03774 ExReleaseSpinLock (&VerifierListLock, OldIrql); 03775 } 03776 03777 Verifier->Unloads += 1; 03778 MmVerifierData.Unloads += 1; 03779 MiActiveVerifies -= 1; 03780 03781 if (MiActiveVerifies == 0) { 03782 03783 if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) { 03784 03785 // 03786 // Return to normal thread stack protection. 03787 // 03788 03789 if (KernelVerifier == FALSE) { 03790 KiStackProtectTime = MiVerifierStackProtectTime; 03791 } 03792 } 03793 03794 #ifndef NO_POOL_CHECKS 03795 MiEnableRandomSpecialPool (TRUE); 03796 #endif 03797 } 03798 } 03799 03800 NTKERNELAPI 03801 LOGICAL 03802 MmIsDriverVerifying ( 03803 IN PDRIVER_OBJECT DriverObject 03804 ) 03805 03806 /*++ 03807 03808 Routine Description: 03809 03810 This function informs the caller if the argument driver is being verified. 03811 03812 Arguments: 03813 03814 DriverObject - Supplies the driver object. 03815 03816 Return Value: 03817 03818 TRUE if this driver is being verified, FALSE if not. 03819 03820 Environment: 03821 03822 Kernel mode, any IRQL, any needed synchronization must be provided by the 03823 caller. 03824 03825 --*/ 03826 03827 { 03828 PLDR_DATA_TABLE_ENTRY DataTableEntry; 03829 03830 DataTableEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection; 03831 03832 if (DataTableEntry == NULL) { 03833 return FALSE; 03834 } 03835 03836 if ((DataTableEntry->Flags & LDRP_IMAGE_VERIFYING) == 0) { 03837 return FALSE; 03838 } 03839 03840 return TRUE; 03841 } 03842 03843 #define MM_BOOT_IMAGE_SIZE (16 * 1024 * 1024) 03844 03845 NTSTATUS 03846 MmAddVerifierThunks ( 03847 IN PVOID ThunkBuffer, 03848 IN ULONG ThunkBufferSize 03849 ) 03850 03851 /*++ 03852 03853 Routine Description: 03854 03855 This routine adds another set of thunks to the verifier list. 03856 03857 Arguments: 03858 03859 ThunkBuffer - Supplies the buffer containing the thunk pairs. 03860 03861 ThunkBufferSize - Supplies the number of bytes in the thunk buffer. 03862 03863 Return Value: 03864 03865 Returns the status of the operation. 03866 03867 Environment: 03868 03869 Kernel mode. APC_LEVEL and below. 03870 03871 --*/ 03872 03873 { 03874 ULONG i; 03875 ULONG NumberOfThunkPairs; 03876 PDRIVER_VERIFIER_THUNK_PAIRS ThunkPairs; 03877 PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable; 03878 PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase; 03879 PLDR_DATA_TABLE_ENTRY DataTableEntry; 03880 PVOID DriverStartAddress; 03881 PVOID DriverEndAddress; 03882 03883 PAGED_CODE(); 03884 03885 if (MiVerifierDriverAddedThunkListHead.Flink == NULL) { 03886 return STATUS_NOT_SUPPORTED; 03887 } 03888 03889 ThunkPairs = (PDRIVER_VERIFIER_THUNK_PAIRS)ThunkBuffer; 03890 NumberOfThunkPairs = ThunkBufferSize / sizeof(DRIVER_VERIFIER_THUNK_PAIRS); 03891 03892 if (NumberOfThunkPairs == 0) { 03893 return STATUS_INVALID_PARAMETER_1; 03894 } 03895 03896 ThunkTableBase = (PDRIVER_SPECIFIED_VERIFIER_THUNKS) ExAllocatePoolWithTag ( 03897 PagedPool, 03898 sizeof (DRIVER_SPECIFIED_VERIFIER_THUNKS) + NumberOfThunkPairs * sizeof (DRIVER_VERIFIER_THUNK_PAIRS), 03899 'tVmM'); 03900 03901 if (ThunkTableBase == NULL) { 03902 return STATUS_INSUFFICIENT_RESOURCES; 03903 } 03904 03905 ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(ThunkTableBase + 1); 03906 03907 RtlCopyMemory (ThunkTable, 03908 ThunkPairs, 03909 NumberOfThunkPairs * sizeof(DRIVER_VERIFIER_THUNK_PAIRS)); 03910 03911 KeEnterCriticalRegion(); 03912 03913 KeWaitForSingleObject (&MmSystemLoadLock, 03914 WrVirtualMemory, 03915 KernelMode, 03916 FALSE, 03917 (PLARGE_INTEGER)NULL); 03918 03919 // 03920 // Find and validate the image that contains the routines to be thunked. 03921 // 03922 03923 DataTableEntry = MiLookupDataTableEntry (ThunkTable->PristineRoutine, 03924 TRUE); 03925 03926 if (DataTableEntry == NULL) { 03927 KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE); 03928 KeLeaveCriticalRegion(); 03929 ExFreePool (ThunkTableBase); 03930 return STATUS_INVALID_PARAMETER_2; 03931 } 03932 03933 DriverStartAddress = (PVOID)(DataTableEntry->DllBase); 03934 DriverEndAddress = (PVOID)((PCHAR)DataTableEntry->DllBase + DataTableEntry->SizeOfImage); 03935 03936 // 03937 // Don't let drivers hook calls to kernel or HAL routines. 03938 // 03939 03940 if (DriverStartAddress < (PVOID)(KSEG0_BASE + MM_BOOT_IMAGE_SIZE)) { 03941 KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE); 03942 KeLeaveCriticalRegion(); 03943 ExFreePool (ThunkTableBase); 03944 return STATUS_INVALID_PARAMETER_2; 03945 } 03946 03947 for (i = 0; i < NumberOfThunkPairs; i += 1) { 03948 03949 // 03950 // Ensure all the routines being thunked are in the same driver. 03951 // 03952 03953 if (((ULONG_PTR)ThunkTable->PristineRoutine < (ULONG_PTR)DriverStartAddress) || 03954 ((ULONG_PTR)ThunkTable->PristineRoutine >= (ULONG_PTR)DriverEndAddress)) { 03955 03956 KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE); 03957 KeLeaveCriticalRegion(); 03958 ExFreePool (ThunkTableBase); 03959 return STATUS_INVALID_PARAMETER_2; 03960 } 03961 ThunkTable += 1; 03962 } 03963 03964 // 03965 // Add the validated thunk table to the verifier's global list. 03966 // 03967 03968 ThunkTableBase->DataTableEntry = DataTableEntry; 03969 ThunkTableBase->NumberOfThunks = NumberOfThunkPairs; 03970 MiActiveVerifierThunks += 1; 03971 03972 InsertTailList (&MiVerifierDriverAddedThunkListHead, 03973 &ThunkTableBase->ListEntry); 03974 03975 KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE); 03976 KeLeaveCriticalRegion(); 03977 03978 return STATUS_SUCCESS; 03979 } 03980 03981 VOID 03982 MiVerifierCheckThunks ( 03983 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 03984 ) 03985 03986 /*++ 03987 03988 Routine Description: 03989 03990 This routine adds another set of thunks to the verifier list. 03991 03992 Arguments: 03993 03994 DataTableEntry - Supplies the data table entry for the driver. 03995 03996 Return Value: 03997 03998 None. 03999 04000 Environment: 04001 04002 Kernel mode. APC_LEVEL and below. 04003 The system load lock must be held by the caller. 04004 04005 --*/ 04006 04007 { 04008 PLIST_ENTRY NextEntry; 04009 PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase; 04010 04011 PAGED_CODE (); 04012 04013 // 04014 // N.B. The DataTableEntry can move (see MiInitializeLoadedModuleList), 04015 // but this only happens long before IoInitialize so this is safe. 04016 // 04017 04018 NextEntry = MiVerifierDriverAddedThunkListHead.Flink; 04019 while (NextEntry != &MiVerifierDriverAddedThunkListHead) { 04020 04021 ThunkTableBase = CONTAINING_RECORD(NextEntry, 04022 DRIVER_SPECIFIED_VERIFIER_THUNKS, 04023 ListEntry); 04024 04025 if (ThunkTableBase->DataTableEntry == DataTableEntry) { 04026 RemoveEntryList (NextEntry); 04027 NextEntry = NextEntry->Flink; 04028 ExFreePool (ThunkTableBase); 04029 MiActiveVerifierThunks -= 1; 04030 04031 // 04032 // Keep looking as the driver may have made multiple calls. 04033 // 04034 04035 continue; 04036 } 04037 04038 NextEntry = NextEntry->Flink; 04039 } 04040 } 04041 04042 #define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \ 04043 ((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L)))) 04044 04045 NTSTATUS 04046 MmGetVerifierInformation ( 04047 OUT PVOID SystemInformation, 04048 IN ULONG SystemInformationLength, 04049 OUT PULONG Length 04050 ) 04051 04052 /*++ 04053 04054 Routine Description: 04055 04056 This routine returns information about drivers undergoing verification. 04057 04058 Arguments: 04059 04060 SystemInformation - Returns the driver verification information. 04061 04062 SystemInformationLength - Supplies the length of the SystemInformation 04063 buffer. 04064 04065 Length - Returns the length of the driver verification file information 04066 placed in the buffer. 04067 04068 Return Value: 04069 04070 Returns the status of the operation. 04071 04072 Environment: 04073 04074 The SystemInformation buffer is in user space and our caller has wrapped 04075 a try-except around this entire routine. Capture any exceptions here and 04076 release resources accordingly. 04077 04078 --*/ 04079 04080 { 04081 PSYSTEM_VERIFIER_INFORMATION UserVerifyBuffer; 04082 ULONG NextEntryOffset; 04083 ULONG TotalSize; 04084 NTSTATUS Status; 04085 PLIST_ENTRY NextEntry; 04086 PMI_VERIFIER_DRIVER_ENTRY Verifier; 04087 UNICODE_STRING UserBufferDriverName; 04088 04089 PAGED_CODE(); 04090 04091 NextEntryOffset = 0; 04092 TotalSize = 0; 04093 04094 *Length = 0; 04095 UserVerifyBuffer = (PSYSTEM_VERIFIER_INFORMATION)SystemInformation; 04096 04097 // 04098 // Capture the number of verifying drivers and the relevant data while 04099 // synchronized. Then return it to our caller. 04100 // 04101 04102 Status = STATUS_SUCCESS; 04103 04104 KeEnterCriticalRegion(); 04105 04106 KeWaitForSingleObject (&MmSystemLoadLock, 04107 WrVirtualMemory, 04108 KernelMode, 04109 FALSE, 04110 (PLARGE_INTEGER)NULL); 04111 04112 try { 04113 04114 NextEntry = MiSuspectDriverList.Flink; 04115 while (NextEntry != &MiSuspectDriverList) { 04116 04117 Verifier = CONTAINING_RECORD(NextEntry, 04118 MI_VERIFIER_DRIVER_ENTRY, 04119 Links); 04120 04121 if ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0) { 04122 NextEntry = NextEntry->Flink; 04123 continue; 04124 } 04125 04126 UserVerifyBuffer = (PSYSTEM_VERIFIER_INFORMATION)( 04127 (PUCHAR)UserVerifyBuffer + NextEntryOffset); 04128 NextEntryOffset = sizeof(SYSTEM_VERIFIER_INFORMATION); 04129 TotalSize += sizeof(SYSTEM_VERIFIER_INFORMATION); 04130 04131 if (TotalSize > SystemInformationLength) { 04132 ExRaiseStatus (STATUS_INFO_LENGTH_MISMATCH); 04133 } 04134 04135 // 04136 // This data is cumulative for all drivers. 04137 // 04138 04139 UserVerifyBuffer->Level = MmVerifierData.Level; 04140 UserVerifyBuffer->RaiseIrqls = MmVerifierData.RaiseIrqls; 04141 UserVerifyBuffer->AcquireSpinLocks = MmVerifierData.AcquireSpinLocks; 04142 04143 UserVerifyBuffer->UnTrackedPool = MmVerifierData.UnTrackedPool; 04144 UserVerifyBuffer->SynchronizeExecutions = MmVerifierData.SynchronizeExecutions; 04145 04146 UserVerifyBuffer->AllocationsAttempted = MmVerifierData.AllocationsAttempted; 04147 UserVerifyBuffer->AllocationsSucceeded = MmVerifierData.AllocationsSucceeded; 04148 UserVerifyBuffer->AllocationsSucceededSpecialPool = MmVerifierData.AllocationsSucceededSpecialPool; 04149 UserVerifyBuffer->AllocationsWithNoTag = MmVerifierData.AllocationsWithNoTag; 04150 04151 UserVerifyBuffer->TrimRequests = MmVerifierData.TrimRequests; 04152 UserVerifyBuffer->Trims = MmVerifierData.Trims; 04153 UserVerifyBuffer->AllocationsFailed = MmVerifierData.AllocationsFailed; 04154 UserVerifyBuffer->AllocationsFailedDeliberately = MmVerifierData.AllocationsFailedDeliberately; 04155 04156 // 04157 // This data is kept on a per-driver basis. 04158 // 04159 04160 UserVerifyBuffer->CurrentPagedPoolAllocations = Verifier->CurrentPagedPoolAllocations; 04161 UserVerifyBuffer->CurrentNonPagedPoolAllocations = Verifier->CurrentNonPagedPoolAllocations; 04162 UserVerifyBuffer->PeakPagedPoolAllocations = Verifier->PeakPagedPoolAllocations; 04163 UserVerifyBuffer->PeakNonPagedPoolAllocations = Verifier->PeakNonPagedPoolAllocations; 04164 04165 UserVerifyBuffer->PagedPoolUsageInBytes = Verifier->PagedBytes; 04166 UserVerifyBuffer->NonPagedPoolUsageInBytes = Verifier->NonPagedBytes; 04167 UserVerifyBuffer->PeakPagedPoolUsageInBytes = Verifier->PeakPagedBytes; 04168 UserVerifyBuffer->PeakNonPagedPoolUsageInBytes = Verifier->PeakNonPagedBytes; 04169 04170 UserVerifyBuffer->Loads = Verifier->Loads; 04171 UserVerifyBuffer->Unloads = Verifier->Unloads; 04172 04173 // 04174 // The DriverName portion of the UserVerifyBuffer must be saved 04175 // locally to protect against a malicious thread changing the 04176 // contents. This is because we will reference the contents 04177 // ourselves when the actual string is copied out carefully below. 04178 // 04179 04180 UserBufferDriverName.Length = Verifier->BaseName.Length; 04181 UserBufferDriverName.MaximumLength = Verifier->BaseName.Length + sizeof (WCHAR); 04182 UserBufferDriverName.Buffer = (PWCHAR)(UserVerifyBuffer + 1); 04183 04184 UserVerifyBuffer->DriverName = UserBufferDriverName; 04185 04186 TotalSize += ROUND_UP (UserBufferDriverName.MaximumLength, 04187 sizeof(ULONG)); 04188 NextEntryOffset += ROUND_UP (UserBufferDriverName.MaximumLength, 04189 sizeof(ULONG)); 04190 04191 if (TotalSize > SystemInformationLength) { 04192 ExRaiseStatus (STATUS_INFO_LENGTH_MISMATCH); 04193 } 04194 04195 // 04196 // Carefully reference the UserVerifyBuffer here. 04197 // 04198 04199 RtlMoveMemory(UserBufferDriverName.Buffer, 04200 Verifier->BaseName.Buffer, 04201 Verifier->BaseName.Length); 04202 04203 UserBufferDriverName.Buffer[ 04204 Verifier->BaseName.Length/sizeof(WCHAR)] = UNICODE_NULL; 04205 UserVerifyBuffer->NextEntryOffset = NextEntryOffset; 04206 04207 NextEntry = NextEntry->Flink; 04208 } 04209 } except (EXCEPTION_EXECUTE_HANDLER) { 04210 Status = GetExceptionCode(); 04211 } 04212 04213 KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE); 04214 04215 KeLeaveCriticalRegion(); 04216 04217 if (Status != STATUS_INFO_LENGTH_MISMATCH) { 04218 UserVerifyBuffer->NextEntryOffset = 0; 04219 *Length = TotalSize; 04220 } 04221 04222 return Status; 04223 } 04224 04225 NTSTATUS 04226 MmSetVerifierInformation ( 04227 IN OUT PVOID SystemInformation, 04228 IN ULONG SystemInformationLength 04229 ) 04230 04231 /*++ 04232 04233 Routine Description: 04234 04235 This routine sets any driver verifier flags that can be done without 04236 rebooting. 04237 04238 Arguments: 04239 04240 SystemInformation - Gets and returns the driver verification flags. 04241 04242 SystemInformationLength - Supplies the length of the SystemInformation 04243 buffer. 04244 04245 Return Value: 04246 04247 Returns the status of the operation. 04248 04249 Environment: 04250 04251 The SystemInformation buffer is in user space and our caller has wrapped 04252 a try-except around this entire routine. Capture any exceptions here and 04253 release resources accordingly. 04254 04255 --*/ 04256 04257 { 04258 ULONG UserFlags; 04259 ULONG NewFlags; 04260 ULONG NewFlagsOn; 04261 ULONG NewFlagsOff; 04262 NTSTATUS Status; 04263 PULONG UserVerifyBuffer; 04264 04265 PAGED_CODE(); 04266 04267 if (SystemInformationLength < sizeof (ULONG)) { 04268 ExRaiseStatus (STATUS_INFO_LENGTH_MISMATCH); 04269 } 04270 04271 UserVerifyBuffer = (PULONG)SystemInformation; 04272 04273 // 04274 // Synchronize all changes to the flags here. 04275 // 04276 04277 Status = STATUS_SUCCESS; 04278 04279 KeEnterCriticalRegion(); 04280 04281 KeWaitForSingleObject (&MmSystemLoadLock, 04282 WrVirtualMemory, 04283 KernelMode, 04284 FALSE, 04285 (PLARGE_INTEGER)NULL); 04286 04287 try { 04288 04289 UserFlags = *UserVerifyBuffer; 04290 04291 // 04292 // Ensure nothing is being set or cleared that isn't supported. 04293 // 04294 // 04295 04296 NewFlagsOn = UserFlags & VerifierModifyableOptions; 04297 04298 NewFlags = MmVerifierData.Level | NewFlagsOn; 04299 04300 // 04301 // Any bits set in NewFlagsOff must be zeroed in the NewFlags. 04302 // 04303 04304 NewFlagsOff = ((~UserFlags) & VerifierModifyableOptions); 04305 04306 NewFlags &= ~NewFlagsOff; 04307 04308 if (NewFlags != MmVerifierData.Level) { 04309 VerifierOptionChanges += 1; 04310 MmVerifierData.Level = NewFlags; 04311 *UserVerifyBuffer = NewFlags; 04312 } 04313 04314 } except (EXCEPTION_EXECUTE_HANDLER) { 04315 Status = GetExceptionCode(); 04316 } 04317 04318 KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE); 04319 04320 KeLeaveCriticalRegion(); 04321 04322 return Status; 04323 } 04324 04325 typedef struct _VERIFIER_STRING_INFO { 04326 ULONG BuildNumber; 04327 ULONG DriverVerifierLevel; 04328 ULONG Flags; 04329 ULONG Check; 04330 } VERIFIER_STRING_INFO, *PVERIFIER_STRING_INFO; 04331 04332 static WCHAR Printable[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 04333 static ULONG PrintableChars = sizeof (Printable) / sizeof (Printable[0]) - 1; 04334 04335 VOID 04336 ViPrintString ( 04337 IN PUNICODE_STRING DriverName 04338 ) 04339 04340 /*++ 04341 04342 Routine Description: 04343 04344 This routine does a really bad hash of build number, verifier level and 04345 flags by using the driver name as a stream of bytes to XOR into the flags, 04346 etc. 04347 04348 This is a Neill Clift special. 04349 04350 Arguments: 04351 04352 DriverName - Supplies the name of the driver. 04353 04354 Return Value: 04355 04356 None. 04357 04358 --*/ 04359 04360 { 04361 VERIFIER_STRING_INFO Bld; 04362 PUCHAR BufPtr; 04363 PWCHAR DriverPtr; 04364 ULONG BufLen; 04365 ULONG i; 04366 ULONG j; 04367 ULONG DriverChars; 04368 ULONG MaxChars; 04369 WCHAR OutBuf[sizeof (VERIFIER_STRING_INFO) * 2 + 1]; 04370 UNICODE_STRING OutBufU; 04371 ULONG Rem; 04372 ULONG LastRem; 04373 LOGICAL Done; 04374 04375 Bld.BuildNumber = NtBuildNumber; 04376 Bld.DriverVerifierLevel = MmVerifierData.Level; 04377 04378 // 04379 // Unloads and other actions could be encoded in the Flags field here. 04380 // 04381 04382 Bld.Flags = 0; 04383 04384 // 04385 // Make the last ULONG a weird function of the others. 04386 // 04387 04388 Bld.Check = ((Bld.Flags + 1) * Bld.BuildNumber * (Bld.DriverVerifierLevel + 1)) * 123456789; 04389 04390 BufPtr = (PUCHAR) &Bld; 04391 BufLen = sizeof (Bld); 04392 04393 DriverChars = DriverName->Length / sizeof (DriverName->Buffer[0]); 04394 DriverPtr = DriverName->Buffer; 04395 MaxChars = DriverChars; 04396 04397 if (DriverChars < sizeof (VERIFIER_STRING_INFO)) { 04398 MaxChars = sizeof (VERIFIER_STRING_INFO); 04399 } 04400 04401 // 04402 // Xor each character in the driver name into the buffer. 04403 // 04404 04405 for (i = 0; i < MaxChars; i += 1) { 04406 BufPtr[i % BufLen] ^= (UCHAR) RtlUpcaseUnicodeChar(DriverPtr[i % DriverChars]); 04407 } 04408 04409 // 04410 // Produce a base N decoding of the binary buffer using the printable 04411 // characters defines. Treat the binary as a byte array and do the 04412 // division for each, tracking the carry. 04413 // 04414 04415 j = 0; 04416 do { 04417 Done = TRUE; 04418 04419 for (i = 0, LastRem = 0; i < sizeof (VERIFIER_STRING_INFO); i += 1) { 04420 Rem = BufPtr[i] + 256 * LastRem; 04421 BufPtr[i] = (UCHAR) (Rem / PrintableChars); 04422 LastRem = Rem % PrintableChars; 04423 if (BufPtr[i]) { 04424 Done = FALSE; 04425 } 04426 } 04427 OutBuf[j++] = Printable[LastRem]; 04428 04429 if (j >= sizeof (OutBuf) / sizeof (OutBuf[0])) { 04430 04431 // 04432 // The stack buffer isn't big enough. 04433 // 04434 04435 return; 04436 } 04437 04438 } while (Done == FALSE); 04439 04440 OutBuf[j] = L'\0'; 04441 04442 OutBufU.Length = OutBufU.MaximumLength = (USHORT) j * sizeof (WCHAR); 04443 OutBufU.Buffer = OutBuf; 04444 04445 DbgPrint ("*******************************************************************************\n"); 04446 DbgPrint ("* *\n"); 04447 04448 DbgPrint ("* This is the string to paste into your build mail\n"); 04449 04450 DbgPrint ("* Driver Verifier: Enabled for %Z on Build %ld %wZ\n", 04451 DriverName, NtBuildNumber & 0xFFFFFFF, &OutBufU); 04452 04453 DbgPrint ("* *\n"); 04454 DbgPrint ("*******************************************************************************\n"); 04455 04456 return; 04457 } 04458 04459 // 04460 // BEWARE: Various kernel macros are undefined here so we can pull in the 04461 // real routines. This is needed because the real routines are exported for 04462 // driver compatibility. This module has been carefully laid out so these 04463 // macros are not referenced from this point down and references go to the 04464 // real routines. 04465 // 04466 04467 04468 04469 04470 #undef KeRaiseIrql 04471 #undef KeLowerIrql 04472 #undef KeAcquireSpinLock 04473 #undef KeReleaseSpinLock 04474 #undef ExAcquireResourceExclusive 04475 04476 VOID 04477 KeRaiseIrql ( 04478 IN KIRQL NewIrql, 04479 OUT PKIRQL OldIrql 04480 ); 04481 04482 VOID 04483 KeLowerIrql ( 04484 IN KIRQL NewIrql 04485 ); 04486 04487 VOID 04488 KeAcquireSpinLock ( 04489 IN PKSPIN_LOCK SpinLock, 04490 OUT PKIRQL OldIrql 04491 ); 04492 04493 VOID 04494 KeReleaseSpinLock ( 04495 IN PKSPIN_LOCK SpinLock, 04496 IN KIRQL NewIrql 04497 ); 04498 04499 BOOLEAN 04500 ExAcquireResourceExclusive ( 04501 IN PERESOURCE Resource, 04502 IN BOOLEAN Wait 04503 ); 04504 04505 #if defined(_X86_) 04506 #define X86_HAL_ROUTINE 1 04507 #else 04508 #define X86_HAL_ROUTINE 0 04509 #endif 04510 04511 #define POOL_ROUTINE 2 04512 04513 #define VERIFIER_THUNK_IN_HAL(Flag) (Flag & X86_HAL_ROUTINE) 04514 #define VERIFIER_POOL_ROUTINE(Flag) (Flag & POOL_ROUTINE) 04515 04516 VERIFIER_THUNKS MiVerifierThunks[] = { 04517 04518 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAllocatePool, 04519 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePool, 04520 POOL_ROUTINE, 04521 04522 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAllocatePoolWithQuota, 04523 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithQuota, 04524 POOL_ROUTINE, 04525 04526 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAllocatePoolWithQuotaTag, 04527 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithQuotaTag, 04528 POOL_ROUTINE, 04529 04530 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAllocatePoolWithTag, 04531 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithTag, 04532 POOL_ROUTINE, 04533 04534 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAllocatePoolWithTagPriority, 04535 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithTagPriority, 04536 POOL_ROUTINE, 04537 04538 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExFreePool, 04539 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierFreePool, 04540 POOL_ROUTINE, 04541 04542 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExFreePoolWithTag, 04543 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierFreePoolWithTag, 04544 POOL_ROUTINE, 04545 04546 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeSetEvent, 04547 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierSetEvent, 04548 0, 04549 04550 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAcquireFastMutexUnsafe, 04551 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireFastMutexUnsafe, 04552 0, 04553 04554 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExReleaseFastMutexUnsafe, 04555 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExReleaseFastMutexUnsafe, 04556 0, 04557 04558 #if 0 04559 // 04560 // This API is re-routed through the stale ddkresrc.c. 04561 // 04562 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAcquireResourceExclusive, 04563 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireResourceExclusive, 04564 0, 04565 #endif 04566 04567 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAcquireResourceExclusiveLite, 04568 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireResourceExclusive, 04569 0, 04570 04571 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExReleaseResourceLite, 04572 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExReleaseResource, 04573 0, 04574 04575 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmProbeAndLockPages, 04576 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierProbeAndLockPages, 04577 0, 04578 04579 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmProbeAndLockProcessPages, 04580 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierProbeAndLockProcessPages, 04581 0, 04582 04583 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmMapIoSpace, 04584 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierMapIoSpace, 04585 0, 04586 04587 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmMapLockedPages, 04588 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierMapLockedPages, 04589 0, 04590 04591 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmMapLockedPagesSpecifyCache, 04592 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierMapLockedPagesSpecifyCache, 04593 0, 04594 04595 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmUnlockPages, 04596 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierUnlockPages, 04597 0, 04598 04599 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmUnmapLockedPages, 04600 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierUnmapLockedPages, 04601 0, 04602 04603 (PDRIVER_VERIFIER_THUNK_ROUTINE)MmUnmapIoSpace, 04604 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierUnmapIoSpace, 04605 0, 04606 04607 // 04608 // These routines cannot be referenced as data on x86 because they 04609 // reside in the HAL. So their addresses must be checked as a pointer. 04610 // 04611 04612 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExAcquireFastMutex, 04613 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireFastMutex, 04614 X86_HAL_ROUTINE, 04615 04616 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExTryToAcquireFastMutex, 04617 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExTryToAcquireFastMutex, 04618 X86_HAL_ROUTINE, 04619 04620 (PDRIVER_VERIFIER_THUNK_ROUTINE)ExReleaseFastMutex, 04621 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExReleaseFastMutex, 04622 X86_HAL_ROUTINE, 04623 04624 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeRaiseIrql, 04625 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeRaiseIrql, 04626 X86_HAL_ROUTINE, 04627 04628 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeLowerIrql, 04629 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeLowerIrql, 04630 X86_HAL_ROUTINE, 04631 04632 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireSpinLock, 04633 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLock, 04634 X86_HAL_ROUTINE, 04635 04636 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeReleaseSpinLock, 04637 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLock, 04638 X86_HAL_ROUTINE, 04639 04640 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeSynchronizeExecution, 04641 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierSynchronizeExecution, 04642 0, 04643 04644 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeInitializeTimerEx, 04645 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeInitializeTimerEx, 04646 0, 04647 04648 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeInitializeTimer, 04649 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeInitializeTimer, 04650 0, 04651 04652 #if defined(_X86_) 04653 04654 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfRaiseIrql, 04655 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfRaiseIrql, 04656 X86_HAL_ROUTINE, 04657 04658 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfLowerIrql, 04659 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfLowerIrql, 04660 X86_HAL_ROUTINE, 04661 04662 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfAcquireSpinLock, 04663 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfAcquireSpinLock, 04664 X86_HAL_ROUTINE, 04665 04666 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfReleaseSpinLock, 04667 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfReleaseSpinLock, 04668 X86_HAL_ROUTINE, 04669 04670 #endif 04671 04672 #if defined(_ALPHA_) 04673 04674 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireSpinLockAtDpcLevel, 04675 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLockAtDpcLevel, 04676 0, 04677 04678 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeReleaseSpinLockFromDpcLevel, 04679 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLockFromDpcLevel, 04680 0, 04681 04682 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireSpinLockRaiseToDpc, 04683 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLockRaiseToDpc, 04684 0, 04685 04686 #endif 04687 04688 (PDRIVER_VERIFIER_THUNK_ROUTINE)IoFreeIrp, 04689 (PDRIVER_VERIFIER_THUNK_ROUTINE)IovFreeIrp, 04690 0, 04691 04692 (PDRIVER_VERIFIER_THUNK_ROUTINE)IofCallDriver, 04693 (PDRIVER_VERIFIER_THUNK_ROUTINE)IovCallDriver, 04694 0, 04695 (PDRIVER_VERIFIER_THUNK_ROUTINE)IofCompleteRequest, 04696 (PDRIVER_VERIFIER_THUNK_ROUTINE)IovCompleteRequest, 04697 0, 04698 (PDRIVER_VERIFIER_THUNK_ROUTINE)IoBuildDeviceIoControlRequest, 04699 (PDRIVER_VERIFIER_THUNK_ROUTINE)IovBuildDeviceIoControlRequest, 04700 0, 04701 04702 (PDRIVER_VERIFIER_THUNK_ROUTINE)IoBuildAsynchronousFsdRequest, 04703 (PDRIVER_VERIFIER_THUNK_ROUTINE)IovBuildAsynchronousFsdRequest, 04704 0, 04705 04706 (PDRIVER_VERIFIER_THUNK_ROUTINE)IoInitializeTimer, 04707 (PDRIVER_VERIFIER_THUNK_ROUTINE)IovInitializeTimer, 04708 0 04709 }; 04710 04711 LOGICAL 04712 MiEnableVerifier ( 04713 IN PLDR_DATA_TABLE_ENTRY DataTableEntry 04714 ) 04715 04716 /*++ 04717 04718 Routine Description: 04719 04720 This function enables the verifier for the argument driver by thunking 04721 relevant system APIs in the argument driver import table. 04722 04723 Arguments: 04724 04725 DataTableEntry - Supplies the data table entry for the driver. 04726 04727 Return Value: 04728 04729 TRUE if thunking was applied, FALSE if not. 04730 04731 Environment: 04732 04733 Kernel mode, Phase 0 Initialization and normal runtime. 04734 Non paged pool exists in Phase0, but paged pool does not. 04735 04736 --*/ 04737 04738 { 04739 ULONG i; 04740 ULONG j; 04741 PULONG_PTR ImportThunk; 04742 ULONG ImportSize; 04743 PVERIFIER_THUNKS VerifierThunk; 04744 ULONG ThunkCount; 04745 LOGICAL Found; 04746 ULONG_PTR RealRoutine; 04747 PULONG_PTR PointerRealRoutine; 04748 PLIST_ENTRY NextEntry; 04749 PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable; 04750 PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase; 04751 04752 ImportThunk = (PULONG_PTR)RtlImageDirectoryEntryToData( 04753 DataTableEntry->DllBase, 04754 TRUE, 04755 IMAGE_DIRECTORY_ENTRY_IAT, 04756 &ImportSize); 04757 04758 if (ImportThunk == NULL) { 04759 return FALSE; 04760 } 04761 04762 ImportSize /= sizeof(PULONG_PTR); 04763 04764 for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) { 04765 04766 Found = FALSE; 04767 04768 VerifierThunk = MiVerifierThunks; 04769 04770 for (ThunkCount = 0; ThunkCount < sizeof (MiVerifierThunks) / sizeof (VERIFIER_THUNKS); ThunkCount += 1) { 04771 04772 if (KernelVerifier == TRUE) { 04773 if (VERIFIER_POOL_ROUTINE (VerifierThunk->Flag) == 0) { 04774 VerifierThunk += 1; 04775 continue; 04776 } 04777 } 04778 04779 if (VERIFIER_THUNK_IN_HAL (VerifierThunk->Flag) == 0) { 04780 RealRoutine = (ULONG_PTR)VerifierThunk->PristineRoutine; 04781 } 04782 else { 04783 04784 // 04785 // Only the x86 has/needs this oddity - take the kernel address, 04786 // knowing that it points at a 2 byte jmp opcode followed by 04787 // a 4-byte indirect pointer to a destination address. 04788 // 04789 04790 PointerRealRoutine = (PULONG_PTR)*((PULONG_PTR)((PCHAR)VerifierThunk->PristineRoutine + 2)); 04791 RealRoutine = *PointerRealRoutine; 04792 } 04793 04794 if (*ImportThunk == RealRoutine) { 04795 *ImportThunk = (ULONG_PTR)(VerifierThunk->NewRoutine); 04796 Found = TRUE; 04797 break; 04798 } 04799 VerifierThunk += 1; 04800 } 04801 04802 if (Found == FALSE) { 04803 04804 NextEntry = MiVerifierDriverAddedThunkListHead.Flink; 04805 while (NextEntry != &MiVerifierDriverAddedThunkListHead) { 04806 04807 ThunkTableBase = CONTAINING_RECORD(NextEntry, 04808 DRIVER_SPECIFIED_VERIFIER_THUNKS, 04809 ListEntry); 04810 04811 ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(ThunkTableBase + 1); 04812 04813 for (j = 0; j < ThunkTableBase->NumberOfThunks; j += 1) { 04814 04815 if (*ImportThunk == (ULONG_PTR)ThunkTable->PristineRoutine) { 04816 *ImportThunk = (ULONG_PTR)(ThunkTable->NewRoutine); 04817 Found = TRUE; 04818 break; 04819 } 04820 ThunkTable += 1; 04821 } 04822 04823 if (Found == TRUE) { 04824 break; 04825 } 04826 04827 NextEntry = NextEntry->Flink; 04828 } 04829 } 04830 } 04831 return TRUE; 04832 } 04833 04834 #if defined(_X86_) 04835 04836 DRIVER_VERIFIER_THUNK_PAIRS MiKernelVerifierThunks[] = { 04837 04838 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeRaiseIrql, 04839 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeRaiseIrql, 04840 04841 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeLowerIrql, 04842 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeLowerIrql, 04843 04844 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireSpinLock, 04845 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLock, 04846 04847 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeReleaseSpinLock, 04848 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLock, 04849 04850 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfRaiseIrql, 04851 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfRaiseIrql, 04852 04853 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfLowerIrql, 04854 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfLowerIrql, 04855 04856 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfAcquireSpinLock, 04857 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfAcquireSpinLock, 04858 04859 (PDRIVER_VERIFIER_THUNK_ROUTINE)KfReleaseSpinLock, 04860 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfReleaseSpinLock, 04861 04862 #if !defined(NT_UP) 04863 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireQueuedSpinLock, 04864 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireQueuedSpinLock, 04865 04866 (PDRIVER_VERIFIER_THUNK_ROUTINE)KeReleaseQueuedSpinLock, 04867 (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseQueuedSpinLock, 04868 #endif 04869 }; 04870 04871 VOID 04872 MiEnableKernelVerifier ( 04873 VOID 04874 ) 04875 04876 /*++ 04877 04878 Routine Description: 04879 04880 This function enables the verifier for the kernel by thunking 04881 relevant HAL APIs in the kernel's import table. 04882 04883 Arguments: 04884 04885 None. 04886 04887 Return Value: 04888 04889 None. 04890 04891 Environment: 04892 04893 Kernel mode, Phase 1 Initialization. 04894 04895 --*/ 04896 04897 { 04898 ULONG i; 04899 PULONG_PTR ImportThunk; 04900 ULONG ImportSize; 04901 PDRIVER_VERIFIER_THUNK_PAIRS VerifierThunk; 04902 ULONG ThunkCount; 04903 ULONG_PTR RealRoutine; 04904 PULONG_PTR PointerRealRoutine; 04905 04906 if (KernelVerifier == FALSE) { 04907 return; 04908 } 04909 04910 ImportThunk = (PULONG_PTR)RtlImageDirectoryEntryToData( 04911 PsNtosImageBase, 04912 TRUE, 04913 IMAGE_DIRECTORY_ENTRY_IAT, 04914 &ImportSize); 04915 04916 if (ImportThunk == NULL) { 04917 return; 04918 } 04919 04920 ImportSize /= sizeof(PULONG_PTR); 04921 04922 for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) { 04923 04924 VerifierThunk = MiKernelVerifierThunks; 04925 04926 for (ThunkCount = 0; ThunkCount < sizeof (MiKernelVerifierThunks) / sizeof (DRIVER_VERIFIER_THUNK_PAIRS); ThunkCount += 1) { 04927 04928 // 04929 // Only the x86 has/needs this oddity - take the kernel address, 04930 // knowing that it points at a 2 byte jmp opcode followed by 04931 // a 4-byte indirect pointer to a destination address. 04932 // 04933 04934 PointerRealRoutine = (PULONG_PTR)*((PULONG_PTR)((PCHAR)VerifierThunk->PristineRoutine + 2)); 04935 RealRoutine = *PointerRealRoutine; 04936 04937 if (*ImportThunk == RealRoutine) { 04938 04939 // 04940 // Order is important here. 04941 // 04942 04943 if (MiKernelVerifierOriginalCalls[ThunkCount] == NULL) { 04944 MiKernelVerifierOriginalCalls[ThunkCount] = (PVOID)RealRoutine; 04945 } 04946 04947 *ImportThunk = (ULONG_PTR)(VerifierThunk->NewRoutine); 04948 04949 break; 04950 } 04951 VerifierThunk += 1; 04952 } 04953 } 04954 return; 04955 } 04956 #endif 04957 04958 // 04959 // BEWARE: Various kernel macros were undefined above so we can pull in the 04960 // real routines. This is needed because the real routines are exported for 04961 // driver compatibility. This module has been carefully laid out so these 04962 // macros are not referenced from that point to here and references go to the 04963 // real routines. 04964 // 04965 // BE EXTREMELY CAREFUL IF YOU DECIDE TO ADD ROUTINES BELOW THIS POINT ! 04966 //

Generated on Sat May 15 19:42:23 2004 for test by doxygen 1.3.7