Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7079 lines
182 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. verifier.c
  5. Abstract:
  6. This module contains the routines to verify the system kernel, HAL and
  7. drivers.
  8. Author:
  9. Landy Wang (landyw) 3-Sep-1998
  10. Revision History:
  11. --*/
  12. #include "mi.h"
  13. #define THUNKED_API
  14. THUNKED_API
  15. PVOID
  16. VerifierAllocatePool (
  17. IN POOL_TYPE PoolType,
  18. IN SIZE_T NumberOfBytes
  19. );
  20. THUNKED_API
  21. PVOID
  22. VerifierAllocatePoolWithTag (
  23. IN POOL_TYPE PoolType,
  24. IN SIZE_T NumberOfBytes,
  25. IN ULONG Tag
  26. );
  27. THUNKED_API
  28. PVOID
  29. VerifierAllocatePoolWithQuotaTag (
  30. IN POOL_TYPE PoolType,
  31. IN SIZE_T NumberOfBytes,
  32. IN ULONG Tag
  33. );
  34. THUNKED_API
  35. PVOID
  36. VerifierAllocatePoolWithTagPriority (
  37. IN POOL_TYPE PoolType,
  38. IN SIZE_T NumberOfBytes,
  39. IN ULONG Tag,
  40. IN EX_POOL_PRIORITY Priority
  41. );
  42. PVOID
  43. VeAllocatePoolWithTagPriority (
  44. IN POOL_TYPE PoolType,
  45. IN SIZE_T NumberOfBytes,
  46. IN ULONG Tag,
  47. IN EX_POOL_PRIORITY Priority,
  48. IN PVOID CallingAddress
  49. );
  50. VOID
  51. VerifierFreePool (
  52. IN PVOID P
  53. );
  54. THUNKED_API
  55. VOID
  56. VerifierFreePoolWithTag (
  57. IN PVOID P,
  58. IN ULONG TagToFree
  59. );
  60. THUNKED_API
  61. LONG
  62. VerifierSetEvent (
  63. IN PRKEVENT Event,
  64. IN KPRIORITY Increment,
  65. IN BOOLEAN Wait
  66. );
  67. THUNKED_API
  68. KIRQL
  69. FASTCALL
  70. VerifierKfRaiseIrql (
  71. IN KIRQL NewIrql
  72. );
  73. THUNKED_API
  74. KIRQL
  75. VerifierKeRaiseIrqlToDpcLevel (
  76. VOID
  77. );
  78. THUNKED_API
  79. VOID
  80. FASTCALL
  81. VerifierKfLowerIrql (
  82. IN KIRQL NewIrql
  83. );
  84. THUNKED_API
  85. VOID
  86. VerifierKeRaiseIrql (
  87. IN KIRQL NewIrql,
  88. OUT PKIRQL OldIrql
  89. );
  90. THUNKED_API
  91. VOID
  92. VerifierKeLowerIrql (
  93. IN KIRQL NewIrql
  94. );
  95. THUNKED_API
  96. VOID
  97. VerifierKeAcquireSpinLock (
  98. IN PKSPIN_LOCK SpinLock,
  99. OUT PKIRQL OldIrql
  100. );
  101. THUNKED_API
  102. VOID
  103. VerifierKeReleaseSpinLock (
  104. IN PKSPIN_LOCK SpinLock,
  105. IN KIRQL NewIrql
  106. );
  107. THUNKED_API
  108. VOID
  109. #if defined(_X86_)
  110. FASTCALL
  111. #endif
  112. VerifierKeAcquireSpinLockAtDpcLevel (
  113. IN PKSPIN_LOCK SpinLock
  114. );
  115. THUNKED_API
  116. VOID
  117. #if defined(_X86_)
  118. FASTCALL
  119. #endif
  120. VerifierKeReleaseSpinLockFromDpcLevel (
  121. IN PKSPIN_LOCK SpinLock
  122. );
  123. THUNKED_API
  124. KIRQL
  125. FASTCALL
  126. VerifierKfAcquireSpinLock (
  127. IN PKSPIN_LOCK SpinLock
  128. );
  129. THUNKED_API
  130. VOID
  131. FASTCALL
  132. VerifierKfReleaseSpinLock (
  133. IN PKSPIN_LOCK SpinLock,
  134. IN KIRQL NewIrql
  135. );
  136. #if !defined(_X86_)
  137. THUNKED_API
  138. KIRQL
  139. VerifierKeAcquireSpinLockRaiseToDpc (
  140. IN PKSPIN_LOCK SpinLock
  141. );
  142. #endif
  143. THUNKED_API
  144. VOID
  145. VerifierKeInitializeTimerEx (
  146. IN PKTIMER Timer,
  147. IN TIMER_TYPE Type
  148. );
  149. THUNKED_API
  150. VOID
  151. VerifierKeInitializeTimer (
  152. IN PKTIMER Timer
  153. );
  154. THUNKED_API
  155. BOOLEAN
  156. FASTCALL
  157. VerifierExTryToAcquireFastMutex (
  158. IN PFAST_MUTEX FastMutex
  159. );
  160. THUNKED_API
  161. VOID
  162. FASTCALL
  163. VerifierExAcquireFastMutex (
  164. IN PFAST_MUTEX FastMutex
  165. );
  166. THUNKED_API
  167. VOID
  168. FASTCALL
  169. VerifierExReleaseFastMutex (
  170. IN PFAST_MUTEX FastMutex
  171. );
  172. THUNKED_API
  173. VOID
  174. FASTCALL
  175. VerifierExAcquireFastMutexUnsafe (
  176. IN PFAST_MUTEX FastMutex
  177. );
  178. THUNKED_API
  179. VOID
  180. FASTCALL
  181. VerifierExReleaseFastMutexUnsafe (
  182. IN PFAST_MUTEX FastMutex
  183. );
  184. THUNKED_API
  185. BOOLEAN
  186. VerifierExAcquireResourceExclusiveLite (
  187. IN PERESOURCE Resource,
  188. IN BOOLEAN Wait
  189. );
  190. THUNKED_API
  191. VOID
  192. FASTCALL
  193. VerifierExReleaseResourceLite (
  194. IN PERESOURCE Resource
  195. );
  196. THUNKED_API
  197. KIRQL
  198. FASTCALL
  199. VerifierKeAcquireQueuedSpinLock (
  200. IN KSPIN_LOCK_QUEUE_NUMBER Number
  201. );
  202. THUNKED_API
  203. VOID
  204. FASTCALL
  205. VerifierKeReleaseQueuedSpinLock (
  206. IN KSPIN_LOCK_QUEUE_NUMBER Number,
  207. IN KIRQL OldIrql
  208. );
  209. THUNKED_API
  210. BOOLEAN
  211. VerifierSynchronizeExecution (
  212. IN PKINTERRUPT Interrupt,
  213. IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  214. IN PVOID SynchronizeContext
  215. );
  216. THUNKED_API
  217. VOID
  218. VerifierProbeAndLockPages (
  219. IN OUT PMDL MemoryDescriptorList,
  220. IN KPROCESSOR_MODE AccessMode,
  221. IN LOCK_OPERATION Operation
  222. );
  223. THUNKED_API
  224. VOID
  225. VerifierProbeAndLockProcessPages (
  226. IN OUT PMDL MemoryDescriptorList,
  227. IN PEPROCESS Process,
  228. IN KPROCESSOR_MODE AccessMode,
  229. IN LOCK_OPERATION Operation
  230. );
  231. THUNKED_API
  232. VOID
  233. VerifierProbeAndLockSelectedPages (
  234. IN OUT PMDL MemoryDescriptorList,
  235. IN PFILE_SEGMENT_ELEMENT SegmentArray,
  236. IN KPROCESSOR_MODE AccessMode,
  237. IN LOCK_OPERATION Operation
  238. );
  239. VOID
  240. VerifierUnlockPages (
  241. IN OUT PMDL MemoryDescriptorList
  242. );
  243. VOID
  244. VerifierUnmapLockedPages (
  245. IN PVOID BaseAddress,
  246. IN PMDL MemoryDescriptorList
  247. );
  248. VOID
  249. VerifierUnmapIoSpace (
  250. IN PVOID BaseAddress,
  251. IN SIZE_T NumberOfBytes
  252. );
  253. THUNKED_API
  254. PVOID
  255. VerifierMapIoSpace (
  256. IN PHYSICAL_ADDRESS PhysicalAddress,
  257. IN SIZE_T NumberOfBytes,
  258. IN MEMORY_CACHING_TYPE CacheType
  259. );
  260. THUNKED_API
  261. PVOID
  262. VerifierMapLockedPages (
  263. IN PMDL MemoryDescriptorList,
  264. IN KPROCESSOR_MODE AccessMode
  265. );
  266. THUNKED_API
  267. PVOID
  268. VerifierMapLockedPagesSpecifyCache (
  269. IN PMDL MemoryDescriptorList,
  270. IN KPROCESSOR_MODE AccessMode,
  271. IN MEMORY_CACHING_TYPE CacheType,
  272. IN PVOID RequestedAddress,
  273. IN ULONG BugCheckOnFailure,
  274. IN MM_PAGE_PRIORITY Priority
  275. );
  276. THUNKED_API
  277. NTSTATUS
  278. VerifierKeWaitForSingleObject (
  279. IN PVOID Object,
  280. IN KWAIT_REASON WaitReason,
  281. IN KPROCESSOR_MODE WaitMode,
  282. IN BOOLEAN Alertable,
  283. IN PLARGE_INTEGER Timeout OPTIONAL
  284. );
  285. THUNKED_API
  286. LONG
  287. VerifierKeReleaseMutex (
  288. IN PRKMUTEX Mutex,
  289. IN BOOLEAN Wait
  290. );
  291. THUNKED_API
  292. VOID
  293. VerifierKeInitializeMutex (
  294. IN PRKMUTEX Mutex,
  295. IN ULONG Level
  296. );
  297. THUNKED_API
  298. LONG
  299. VerifierKeReleaseMutant(
  300. IN PRKMUTANT Mutant,
  301. IN KPRIORITY Increment,
  302. IN BOOLEAN Abandoned,
  303. IN BOOLEAN Wait
  304. );
  305. THUNKED_API
  306. VOID
  307. VerifierKeInitializeMutant(
  308. IN PRKMUTANT Mutant,
  309. IN BOOLEAN InitialOwner
  310. );
  311. THUNKED_API
  312. VOID
  313. VerifierKeInitializeSpinLock (
  314. IN PKSPIN_LOCK SpinLock
  315. );
  316. VOID
  317. ViCheckMdlPages (
  318. IN PMDL MemoryDescriptorList,
  319. IN MEMORY_CACHING_TYPE CacheType
  320. );
  321. VOID
  322. ViFreeTrackedPool (
  323. IN PVOID VirtualAddress,
  324. IN SIZE_T ChargedBytes,
  325. IN LOGICAL CheckType,
  326. IN LOGICAL SpecialPool
  327. );
  328. VOID
  329. VerifierFreeTrackedPool (
  330. IN PVOID VirtualAddress,
  331. IN SIZE_T ChargedBytes,
  332. IN LOGICAL CheckType,
  333. IN LOGICAL SpecialPool
  334. );
  335. VOID
  336. ViPrintString (
  337. IN PUNICODE_STRING DriverName
  338. );
  339. LOGICAL
  340. ViInjectResourceFailure (
  341. VOID
  342. );
  343. VOID
  344. ViTrimAllSystemPagableMemory (
  345. VOID
  346. );
  347. VOID
  348. ViInitializeEntry (
  349. IN PMI_VERIFIER_DRIVER_ENTRY Verifier,
  350. IN LOGICAL FirstLoad
  351. );
  352. LOGICAL
  353. ViReservePoolAllocation (
  354. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  355. );
  356. ULONG_PTR
  357. ViInsertPoolAllocation (
  358. IN PMI_VERIFIER_DRIVER_ENTRY Verifier,
  359. IN PVOID VirtualAddress,
  360. IN PVOID CallingAddress,
  361. IN SIZE_T NumberOfBytes,
  362. IN ULONG Tag
  363. );
  364. VOID
  365. ViCancelPoolAllocation (
  366. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  367. );
  368. VOID
  369. ViReleasePoolAllocation (
  370. IN PMI_VERIFIER_DRIVER_ENTRY Verifier,
  371. IN PVOID VirtualAddress,
  372. IN ULONG_PTR ListIndex,
  373. IN SIZE_T ChargedBytes
  374. );
  375. VOID
  376. KfSanityCheckRaiseIrql (
  377. IN KIRQL NewIrql
  378. );
  379. VOID
  380. KfSanityCheckLowerIrql (
  381. IN KIRQL NewIrql
  382. );
  383. NTSTATUS
  384. VerifierReferenceObjectByHandle (
  385. IN HANDLE Handle,
  386. IN ACCESS_MASK DesiredAccess,
  387. IN POBJECT_TYPE ObjectType OPTIONAL,
  388. IN KPROCESSOR_MODE AccessMode,
  389. OUT PVOID *Object,
  390. OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
  391. );
  392. MM_DRIVER_VERIFIER_DATA MmVerifierData;
  393. //
  394. // Any flags which can be modified on the fly without rebooting are set here.
  395. //
  396. ULONG VerifierModifyableOptions;
  397. ULONG VerifierOptionChanges;
  398. LIST_ENTRY MiSuspectDriverList;
  399. LOGICAL MiVerifyAllDrivers;
  400. WCHAR MiVerifyRandomDrivers;
  401. ULONG MiActiveVerifies;
  402. ULONG MiActiveVerifierThunks;
  403. ULONG MiNoPageOnRaiseIrql;
  404. ULONG MiVerifierStackProtectTime;
  405. LOGICAL MmDontVerifyRandomDrivers = TRUE;
  406. LOGICAL VerifierSystemSufficientlyBooted;
  407. LARGE_INTEGER VerifierRequiredTimeSinceBoot = {(ULONG)(40 * 1000 * 1000 * 10), 1};
  408. LOGICAL VerifierIsTrackingPool = FALSE;
  409. KSPIN_LOCK VerifierListLock;
  410. KSPIN_LOCK VerifierPoolLock;
  411. FAST_MUTEX VerifierPoolMutex;
  412. PRTL_BITMAP VerifierLargePagedPoolMap;
  413. LIST_ENTRY MiVerifierDriverAddedThunkListHead;
  414. extern LOGICAL MmSpecialPoolCatchOverruns;
  415. LOGICAL KernelVerifier = FALSE;
  416. ULONG KernelVerifierTickPage = 0x7;
  417. ULONG MiVerifierThunksAdded;
  418. PDRIVER_VERIFIER_THUNK_ROUTINE
  419. MiResolveVerifierExports (
  420. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  421. IN PCHAR PristineName
  422. );
  423. LOGICAL
  424. MiEnableVerifier (
  425. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  426. );
  427. LOGICAL
  428. MiReEnableVerifier (
  429. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  430. );
  431. VOID
  432. ViInsertVerifierEntry (
  433. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  434. );
  435. PVOID
  436. ViPostPoolAllocation (
  437. IN PVOID VirtualAddress,
  438. IN SIZE_T NumberOfBytes,
  439. IN POOL_TYPE PoolType,
  440. IN ULONG Tag,
  441. IN PVOID CallingAddress
  442. );
  443. PMI_VERIFIER_DRIVER_ENTRY
  444. ViLocateVerifierEntry (
  445. IN PVOID SystemAddress
  446. );
  447. VOID
  448. MiVerifierCheckThunks (
  449. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  450. );
  451. //
  452. // Track irqls functions
  453. //
  454. VOID
  455. ViTrackIrqlInitialize (
  456. );
  457. VOID
  458. ViTrackIrqlLog (
  459. IN KIRQL CurrentIrql,
  460. IN KIRQL NewIrql
  461. );
  462. //
  463. // Fault injection stack trace log
  464. //
  465. #if defined(_X86_)
  466. VOID
  467. ViFaultTracesInitialize (
  468. );
  469. VOID
  470. ViFaultTracesLog (
  471. );
  472. #endif
  473. #ifdef ALLOC_PRAGMA
  474. #pragma alloc_text(INIT,MiInitializeDriverVerifierList)
  475. #pragma alloc_text(INIT,MiInitializeVerifyingComponents)
  476. #pragma alloc_text(INIT,ViTrackIrqlInitialize)
  477. #pragma alloc_text(INIT,MiResolveVerifierExports)
  478. #if defined(_X86_)
  479. #pragma alloc_text(INIT,MiEnableKernelVerifier)
  480. #pragma alloc_text(INIT,ViFaultTracesInitialize)
  481. #endif
  482. #pragma alloc_text(PAGE,MiApplyDriverVerifier)
  483. #pragma alloc_text(PAGE,MiEnableVerifier)
  484. #pragma alloc_text(INIT,MiReEnableVerifier)
  485. #pragma alloc_text(PAGE,ViPrintString)
  486. #pragma alloc_text(PAGE,MmGetVerifierInformation)
  487. #pragma alloc_text(PAGE,MmSetVerifierInformation)
  488. #pragma alloc_text(PAGE,MmAddVerifierThunks)
  489. #pragma alloc_text(PAGE,MmIsVerifierEnabled)
  490. #pragma alloc_text(PAGE,MiVerifierCheckThunks)
  491. #pragma alloc_text(PAGEVRFY,MiVerifyingDriverUnloading)
  492. #pragma alloc_text(PAGE,MmAddVerifierEntry)
  493. #pragma alloc_text(PAGE,MmRemoveVerifierEntry)
  494. #pragma alloc_text(INIT,MiReApplyVerifierToLoadedModules)
  495. #pragma alloc_text(PAGEVRFY,VerifierProbeAndLockPages)
  496. #pragma alloc_text(PAGEVRFY,VerifierProbeAndLockProcessPages)
  497. #pragma alloc_text(PAGEVRFY,VerifierProbeAndLockSelectedPages)
  498. #pragma alloc_text(PAGEVRFY,VerifierUnlockPages)
  499. #pragma alloc_text(PAGEVRFY,VerifierMapIoSpace)
  500. #pragma alloc_text(PAGEVRFY,VerifierMapLockedPages)
  501. #pragma alloc_text(PAGEVRFY,VerifierMapLockedPagesSpecifyCache)
  502. #pragma alloc_text(PAGEVRFY,VerifierUnmapLockedPages)
  503. #pragma alloc_text(PAGEVRFY,VerifierUnmapIoSpace)
  504. #pragma alloc_text(PAGEVRFY,VerifierAllocatePool)
  505. #pragma alloc_text(PAGEVRFY,VerifierAllocatePoolWithTag)
  506. #pragma alloc_text(PAGEVRFY,VerifierAllocatePoolWithTagPriority)
  507. #pragma alloc_text(PAGEVRFY,VerifierAllocatePoolWithQuotaTag)
  508. #pragma alloc_text(PAGEVRFY,VerifierFreePool)
  509. #pragma alloc_text(PAGEVRFY,VerifierFreePoolWithTag)
  510. #pragma alloc_text(PAGEVRFY,VerifierKeWaitForSingleObject)
  511. #pragma alloc_text(PAGEVRFY,VerifierKfRaiseIrql)
  512. #pragma alloc_text(PAGEVRFY,VerifierKeRaiseIrqlToDpcLevel)
  513. #pragma alloc_text(PAGEVRFY,VerifierKfLowerIrql)
  514. #pragma alloc_text(PAGEVRFY,VerifierKeRaiseIrql)
  515. #pragma alloc_text(PAGEVRFY,VerifierKeLowerIrql)
  516. #pragma alloc_text(PAGEVRFY,VerifierKeAcquireSpinLock)
  517. #pragma alloc_text(PAGEVRFY,VerifierKeReleaseSpinLock)
  518. #pragma alloc_text(PAGEVRFY,VerifierKeAcquireSpinLockAtDpcLevel)
  519. #pragma alloc_text(PAGEVRFY,VerifierKeReleaseSpinLockFromDpcLevel)
  520. #pragma alloc_text(PAGEVRFY,VerifierKfAcquireSpinLock)
  521. #pragma alloc_text(PAGEVRFY,VerifierKfReleaseSpinLock)
  522. #pragma alloc_text(PAGEVRFY,VerifierKeInitializeTimer)
  523. #pragma alloc_text(PAGEVRFY,VerifierKeInitializeTimerEx)
  524. #pragma alloc_text(PAGEVRFY,VerifierExTryToAcquireFastMutex)
  525. #pragma alloc_text(PAGEVRFY,VerifierExAcquireFastMutex)
  526. #pragma alloc_text(PAGEVRFY,VerifierExReleaseFastMutex)
  527. #pragma alloc_text(PAGEVRFY,VerifierExAcquireFastMutexUnsafe)
  528. #pragma alloc_text(PAGEVRFY,VerifierExReleaseFastMutexUnsafe)
  529. #pragma alloc_text(PAGEVRFY,VerifierExAcquireResourceExclusiveLite)
  530. #pragma alloc_text(PAGEVRFY,VerifierExReleaseResourceLite)
  531. #pragma alloc_text(PAGEVRFY,VerifierKeAcquireQueuedSpinLock)
  532. #pragma alloc_text(PAGEVRFY,VerifierKeReleaseQueuedSpinLock)
  533. #pragma alloc_text(PAGEVRFY,VerifierKeReleaseMutex)
  534. #pragma alloc_text(PAGEVRFY,VerifierKeInitializeMutex)
  535. #pragma alloc_text(PAGEVRFY,VerifierKeReleaseMutant)
  536. #pragma alloc_text(PAGEVRFY,VerifierKeInitializeMutant)
  537. #pragma alloc_text(PAGEVRFY,VerifierKeInitializeSpinLock)
  538. #pragma alloc_text(PAGEVRFY,VerifierSynchronizeExecution)
  539. #pragma alloc_text(PAGEVRFY,VerifierReferenceObjectByHandle)
  540. #pragma alloc_text(PAGEVRFY,VerifierSetEvent)
  541. #pragma alloc_text(PAGEVRFY,ViFreeTrackedPool)
  542. #pragma alloc_text(PAGEVRFY,VeAllocatePoolWithTagPriority)
  543. #pragma alloc_text(PAGEVRFY,ViCheckMdlPages)
  544. #pragma alloc_text(PAGEVRFY,ViInsertVerifierEntry)
  545. #pragma alloc_text(PAGEVRFY,ViLocateVerifierEntry)
  546. #pragma alloc_text(PAGEVRFY,ViPostPoolAllocation)
  547. #pragma alloc_text(PAGEVRFY,ViInjectResourceFailure)
  548. #pragma alloc_text(PAGEVRFY,ViTrimAllSystemPagableMemory)
  549. #pragma alloc_text(PAGEVRFY,ViInitializeEntry)
  550. #pragma alloc_text(PAGEVRFY,ViReservePoolAllocation)
  551. #pragma alloc_text(PAGEVRFY,ViInsertPoolAllocation)
  552. #pragma alloc_text(PAGEVRFY,ViCancelPoolAllocation)
  553. #pragma alloc_text(PAGEVRFY,ViReleasePoolAllocation)
  554. #pragma alloc_text(PAGEVRFY,KfSanityCheckRaiseIrql)
  555. #pragma alloc_text(PAGEVRFY,KfSanityCheckLowerIrql)
  556. #pragma alloc_text(PAGEVRFY,ViTrackIrqlLog)
  557. #if defined(_X86_)
  558. #pragma alloc_text(PAGEVRFY,ViFaultTracesLog)
  559. #endif
  560. #if !defined(_X86_)
  561. #pragma alloc_text(PAGEVRFY,VerifierKeAcquireSpinLockRaiseToDpc)
  562. #endif
  563. #endif
  564. typedef struct _VERIFIER_THUNKS {
  565. union {
  566. PCHAR PristineRoutineAsciiName;
  567. //
  568. // The actual pristine routine address is derived from exports
  569. //
  570. PDRIVER_VERIFIER_THUNK_ROUTINE PristineRoutine;
  571. };
  572. PDRIVER_VERIFIER_THUNK_ROUTINE NewRoutine;
  573. } VERIFIER_THUNKS, *PVERIFIER_THUNKS;
  574. extern const VERIFIER_THUNKS MiVerifierThunks[];
  575. extern const VERIFIER_THUNKS MiVerifierPoolThunks[];
  576. #if defined (_X86_)
  577. #define VI_KE_RAISE_IRQL 0
  578. #define VI_KE_LOWER_IRQL 1
  579. #define VI_KE_ACQUIRE_SPINLOCK 2
  580. #define VI_KE_RELEASE_SPINLOCK 3
  581. #define VI_KF_RAISE_IRQL 4
  582. #define VI_KE_RAISE_IRQL_TO_DPC_LEVEL 5
  583. #define VI_KF_LOWER_IRQL 6
  584. #define VI_KF_ACQUIRE_SPINLOCK 7
  585. #define VI_KF_RELEASE_SPINLOCK 8
  586. #define VI_KE_ACQUIRE_QUEUED_SPINLOCK 9
  587. #define VI_KE_RELEASE_QUEUED_SPINLOCK 10
  588. #define VI_HALMAX 11
  589. PVOID MiKernelVerifierOriginalCalls[VI_HALMAX];
  590. #endif
  591. //
  592. // Track irql package declarations
  593. //
  594. #define VI_TRACK_IRQL_TRACE_LENGTH 5
  595. typedef struct _VI_TRACK_IRQL {
  596. PVOID Thread;
  597. KIRQL OldIrql;
  598. KIRQL NewIrql;
  599. UCHAR Processor;
  600. ULONG TickCount;
  601. PVOID StackTrace [VI_TRACK_IRQL_TRACE_LENGTH];
  602. } VI_TRACK_IRQL, *PVI_TRACK_IRQL;
  603. PVI_TRACK_IRQL ViTrackIrqlQueue;
  604. ULONG ViTrackIrqlIndex;
  605. ULONG ViTrackIrqlQueueLength = 128;
  606. VOID
  607. ViTrackIrqlInitialize (
  608. )
  609. {
  610. ULONG Length;
  611. ULONG Round;
  612. //
  613. // Round up length to a power of two and prepare
  614. // mask for the length.
  615. //
  616. Length = ViTrackIrqlQueueLength;
  617. if (Length > 0x10000) {
  618. Length = 0x10000;
  619. }
  620. for (Round = 0x10000; Round != 0; Round >>= 1) {
  621. if (Length == Round) {
  622. break;
  623. }
  624. else if ((Length & Round) == Round) {
  625. Length = (Round << 1);
  626. break;
  627. }
  628. }
  629. ViTrackIrqlQueueLength = Length;
  630. //
  631. // Note POOL_DRIVER_MASK must be set to stop the recursion loop
  632. // when using the kernel verifier.
  633. //
  634. ViTrackIrqlQueue = ExAllocatePoolWithTagPriority (
  635. NonPagedPool | POOL_DRIVER_MASK,
  636. ViTrackIrqlQueueLength * sizeof (VI_TRACK_IRQL),
  637. 'lqrI',
  638. HighPoolPriority);
  639. }
  640. VOID
  641. ViTrackIrqlLog (
  642. IN KIRQL CurrentIrql,
  643. IN KIRQL NewIrql
  644. )
  645. {
  646. PVI_TRACK_IRQL Information;
  647. LARGE_INTEGER TimeStamp;
  648. ULONG Index;
  649. ULONG Hash;
  650. ASSERT (ViTrackIrqlQueue != NULL);
  651. if (CurrentIrql > DISPATCH_LEVEL || NewIrql > DISPATCH_LEVEL) {
  652. return;
  653. }
  654. //
  655. // Get a slot to write into.
  656. //
  657. Index = InterlockedIncrement((PLONG)&ViTrackIrqlIndex);
  658. Index &= (ViTrackIrqlQueueLength - 1);
  659. //
  660. // Capture information.
  661. //
  662. Information = &(ViTrackIrqlQueue[Index]);
  663. Information->Thread = KeGetCurrentThread();
  664. Information->OldIrql = CurrentIrql;
  665. Information->NewIrql = NewIrql;
  666. Information->Processor = (UCHAR)(KeGetCurrentProcessorNumber());
  667. KeQueryTickCount(&TimeStamp);
  668. Information->TickCount = TimeStamp.LowPart;
  669. RtlCaptureStackBackTrace (2,
  670. VI_TRACK_IRQL_TRACE_LENGTH,
  671. Information->StackTrace,
  672. &Hash);
  673. }
  674. //
  675. // Detect the caller of the current function in an architecture
  676. // dependent way.
  677. //
  678. #define VI_DETECT_RETURN_ADDRESS(Caller) { \
  679. PVOID CallersCaller; \
  680. RtlGetCallersAddress(&Caller, &CallersCaller); \
  681. }
  682. //
  683. // Fault injection stack trace log.
  684. //
  685. #define VI_FAULT_TRACE_LENGTH 8
  686. typedef struct _VI_FAULT_TRACE {
  687. PVOID StackTrace [VI_FAULT_TRACE_LENGTH];
  688. } VI_FAULT_TRACE, *PVI_FAULT_TRACE;
  689. PVI_FAULT_TRACE ViFaultTraces;
  690. ULONG ViFaultTracesIndex;
  691. ULONG ViFaultTracesLength = 128;
  692. VOID
  693. ViFaultTracesInitialize (
  694. VOID
  695. )
  696. {
  697. //
  698. // Note POOL_DRIVER_MASK must be set to stop the recursion loop
  699. // when using the kernel verifier.
  700. //
  701. ViFaultTraces = ExAllocatePoolWithTagPriority (
  702. NonPagedPool | POOL_DRIVER_MASK,
  703. ViFaultTracesLength * sizeof (VI_FAULT_TRACE),
  704. 'ttlF',
  705. HighPoolPriority);
  706. }
  707. VOID
  708. ViFaultTracesLog (
  709. VOID
  710. )
  711. {
  712. PVI_FAULT_TRACE Information;
  713. ULONG Hash;
  714. ULONG Index;
  715. //
  716. // Sanity check
  717. //
  718. if (ViFaultTraces == NULL) {
  719. return;
  720. }
  721. //
  722. // Get slot to write into.
  723. //
  724. Index = InterlockedIncrement ((PLONG)&ViFaultTracesIndex);
  725. Index &= (ViFaultTracesLength - 1);
  726. //
  727. // Capture information. Even if we lose performance it is
  728. // worth zeroing the trace buffer to avoid confusing people
  729. // if old traces get merged with new ones. This zeroing
  730. // will happen only if we actually inject a failure.
  731. //
  732. Information = &(ViFaultTraces[Index]);
  733. RtlZeroMemory (Information, sizeof (VI_FAULT_TRACE));
  734. RtlCaptureStackBackTrace (2,
  735. VI_FAULT_TRACE_LENGTH,
  736. Information->StackTrace,
  737. &Hash);
  738. }
  739. //
  740. // Don't fail any requests in the first 7 or 8 minutes as we want to
  741. // give the system enough time to boot.
  742. //
  743. #define MI_CHECK_UPTIME() \
  744. if (VerifierSystemSufficientlyBooted == FALSE) { \
  745. LARGE_INTEGER _CurrentTime; \
  746. KeQuerySystemTime (&_CurrentTime); \
  747. if (_CurrentTime.QuadPart > KeBootTime.QuadPart + VerifierRequiredTimeSinceBoot.QuadPart) { \
  748. VerifierSystemSufficientlyBooted = TRUE; \
  749. } \
  750. }
  751. THUNKED_API
  752. VOID
  753. VerifierProbeAndLockPages (
  754. IN OUT PMDL MemoryDescriptorList,
  755. IN KPROCESSOR_MODE AccessMode,
  756. IN LOCK_OPERATION Operation
  757. )
  758. {
  759. ULONG i;
  760. KIRQL CurrentIrql;
  761. PPFN_NUMBER Page;
  762. PVOID StartingVa;
  763. LOGICAL ValidPfn;
  764. PFN_NUMBER NumberOfPages;
  765. PEPROCESS CurrentProcess;
  766. PLIST_ENTRY NextEntry;
  767. PPFN_NUMBER LastPage;
  768. PMI_PHYSICAL_VIEW PhysicalView;
  769. CurrentIrql = KeGetCurrentIrql();
  770. if (CurrentIrql > DISPATCH_LEVEL) {
  771. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  772. 0x70,
  773. CurrentIrql,
  774. (ULONG_PTR)MemoryDescriptorList,
  775. (ULONG_PTR)AccessMode);
  776. }
  777. if (ViInjectResourceFailure () == TRUE) {
  778. ExRaiseStatus (STATUS_WORKING_SET_QUOTA);
  779. }
  780. MmProbeAndLockPages (MemoryDescriptorList, AccessMode, Operation);
  781. //
  782. // Every page that has been probed and locked must have a PFN with the
  783. // exception of physical section mappings.
  784. //
  785. Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
  786. StartingVa = (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
  787. MemoryDescriptorList->ByteOffset);
  788. NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(StartingVa,
  789. MemoryDescriptorList->ByteCount);
  790. LastPage = Page + NumberOfPages;
  791. ASSERT (NumberOfPages != 0);
  792. LOCK_PFN2 (CurrentIrql);
  793. do {
  794. if (*Page == MM_EMPTY_LIST) {
  795. //
  796. // There are no more locked pages.
  797. //
  798. break;
  799. }
  800. ValidPfn = FALSE;
  801. for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i += 1) {
  802. if ((*Page >= MmPhysicalMemoryBlock->Run[i].BasePage) &&
  803. (*Page <= MmPhysicalMemoryBlock->Run[i].BasePage +
  804. MmPhysicalMemoryBlock->Run[i].PageCount)) {
  805. //
  806. // A valid PFN exists for this page, march to the next one.
  807. //
  808. ValidPfn = TRUE;
  809. break;
  810. }
  811. }
  812. if (ValidPfn == FALSE) {
  813. CurrentProcess = PsGetCurrentProcess ();
  814. //
  815. // Check for a transfer to/from a physical VAD - these are
  816. // allowed to have no backing PFNs.
  817. //
  818. if ((StartingVa <= MM_HIGHEST_USER_ADDRESS) &&
  819. (CurrentProcess->Flags & PS_PROCESS_FLAGS_HAS_PHYSICAL_VAD)) {
  820. //
  821. // This process has a physical VAD which maps directly to RAM
  822. // not necessarily present in the PFN database. See if the
  823. // MDL request intersects this physical VAD.
  824. //
  825. NextEntry = CurrentProcess->PhysicalVadList.Flink;
  826. while (NextEntry != &CurrentProcess->PhysicalVadList) {
  827. PhysicalView = CONTAINING_RECORD(NextEntry,
  828. MI_PHYSICAL_VIEW,
  829. ListEntry);
  830. if ((PhysicalView->Vad->u.VadFlags.PhysicalMapping == 1) &&
  831. (StartingVa >= (PVOID)PhysicalView->StartVa) &&
  832. (StartingVa <= (PVOID)PhysicalView->EndVa)) {
  833. ValidPfn = TRUE;
  834. break;
  835. }
  836. NextEntry = NextEntry->Flink;
  837. }
  838. }
  839. if (ValidPfn == FALSE) {
  840. //
  841. // The MDL being probed has no backing PFNs and it was not
  842. // a user physical VAD. This means that PFN entries had their
  843. // reference counts bumped, but since they don't exist, random
  844. // physical pages just got what are going to usually look
  845. // like single bit errors. This is bad.
  846. //
  847. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  848. 0x6F,
  849. (ULONG_PTR)MemoryDescriptorList,
  850. (ULONG_PTR)(*Page),
  851. (ULONG_PTR)MmHighestPhysicalPage);
  852. }
  853. break;
  854. }
  855. Page += 1;
  856. } while (Page < LastPage);
  857. UNLOCK_PFN2 (CurrentIrql);
  858. }
  859. THUNKED_API
  860. VOID
  861. VerifierProbeAndLockProcessPages (
  862. IN OUT PMDL MemoryDescriptorList,
  863. IN PEPROCESS Process,
  864. IN KPROCESSOR_MODE AccessMode,
  865. IN LOCK_OPERATION Operation
  866. )
  867. {
  868. KIRQL CurrentIrql;
  869. CurrentIrql = KeGetCurrentIrql();
  870. if (CurrentIrql > DISPATCH_LEVEL) {
  871. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  872. 0x71,
  873. CurrentIrql,
  874. (ULONG_PTR)MemoryDescriptorList,
  875. (ULONG_PTR)Process);
  876. }
  877. if (ViInjectResourceFailure () == TRUE) {
  878. ExRaiseStatus (STATUS_WORKING_SET_QUOTA);
  879. }
  880. MmProbeAndLockProcessPages (MemoryDescriptorList,
  881. Process,
  882. AccessMode,
  883. Operation);
  884. }
  885. THUNKED_API
  886. VOID
  887. VerifierProbeAndLockSelectedPages (
  888. IN OUT PMDL MemoryDescriptorList,
  889. IN PFILE_SEGMENT_ELEMENT SegmentArray,
  890. IN KPROCESSOR_MODE AccessMode,
  891. IN LOCK_OPERATION Operation
  892. )
  893. {
  894. KIRQL CurrentIrql;
  895. CurrentIrql = KeGetCurrentIrql();
  896. if (CurrentIrql > APC_LEVEL) {
  897. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  898. 0x72,
  899. CurrentIrql,
  900. (ULONG_PTR)MemoryDescriptorList,
  901. (ULONG_PTR)AccessMode);
  902. }
  903. if (ViInjectResourceFailure () == TRUE) {
  904. ExRaiseStatus (STATUS_WORKING_SET_QUOTA);
  905. }
  906. MmProbeAndLockSelectedPages (MemoryDescriptorList,
  907. SegmentArray,
  908. AccessMode,
  909. Operation);
  910. }
  911. THUNKED_API
  912. PVOID
  913. VerifierMapIoSpace (
  914. IN PHYSICAL_ADDRESS PhysicalAddress,
  915. IN SIZE_T NumberOfBytes,
  916. IN MEMORY_CACHING_TYPE CacheType
  917. )
  918. {
  919. KIRQL CurrentIrql;
  920. ULONG Hint;
  921. PMMPFN Pfn1;
  922. PFN_NUMBER NumberOfPages;
  923. PFN_NUMBER PageFrameIndex;
  924. CurrentIrql = KeGetCurrentIrql ();
  925. if (CurrentIrql > DISPATCH_LEVEL) {
  926. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  927. 0x73,
  928. CurrentIrql,
  929. (ULONG_PTR)PhysicalAddress.LowPart,
  930. NumberOfBytes);
  931. }
  932. //
  933. // See if the first frame is in the PFN database and if so, they all must
  934. // be.
  935. //
  936. Hint = 0;
  937. PageFrameIndex = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
  938. if (MiIsPhysicalMemoryAddress (PageFrameIndex, &Hint, TRUE) == TRUE) {
  939. Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
  940. NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES (PhysicalAddress.LowPart,
  941. NumberOfBytes);
  942. do {
  943. //
  944. // Each frame better be locked down already. Bugcheck if not.
  945. //
  946. if ((Pfn1->u3.e2.ReferenceCount != 0) ||
  947. ((Pfn1->u3.e1.Rom == 1) && ((CacheType & 0xFF) == MmCached))) {
  948. NOTHING;
  949. }
  950. else {
  951. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  952. 0x83,
  953. (ULONG_PTR)PhysicalAddress.LowPart,
  954. NumberOfBytes,
  955. (ULONG_PTR)(Pfn1 - MmPfnDatabase));
  956. }
  957. if (Pfn1->u3.e1.CacheAttribute == MiNotMapped) {
  958. //
  959. // This better be for a page allocated with
  960. // MmAllocatePagesForMdl. Otherwise it might be a
  961. // page on the freelist which could subsequently be
  962. // given out with a different attribute !
  963. //
  964. if ((Pfn1->u4.PteFrame == MI_MAGIC_AWE_PTEFRAME) ||
  965. #if defined (_MI_MORE_THAN_4GB_)
  966. (Pfn1->u4.PteFrame == MI_MAGIC_4GB_RECLAIM) ||
  967. #endif
  968. (Pfn1->PteAddress == (PVOID) (ULONG_PTR)(X64K | 0x1))) {
  969. NOTHING;
  970. }
  971. else {
  972. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  973. 0x84,
  974. (ULONG_PTR)PhysicalAddress.LowPart,
  975. NumberOfBytes,
  976. (ULONG_PTR)(Pfn1 - MmPfnDatabase));
  977. }
  978. }
  979. Pfn1 += 1;
  980. NumberOfPages -= 1;
  981. } while (NumberOfPages != 0);
  982. }
  983. if (ViInjectResourceFailure () == TRUE) {
  984. return NULL;
  985. }
  986. return MmMapIoSpace (PhysicalAddress, NumberOfBytes, CacheType);
  987. }
  988. VOID
  989. ViCheckMdlPages (
  990. IN PMDL MemoryDescriptorList,
  991. IN MEMORY_CACHING_TYPE CacheType
  992. )
  993. {
  994. PMMPFN Pfn1;
  995. PFN_NUMBER NumberOfPages;
  996. PPFN_NUMBER Page;
  997. PPFN_NUMBER LastPage;
  998. PVOID StartingVa;
  999. ASSERT ((MemoryDescriptorList->MdlFlags & MDL_IO_SPACE) == 0);
  1000. StartingVa = (PVOID)((PCHAR)MemoryDescriptorList->StartVa +
  1001. MemoryDescriptorList->ByteOffset);
  1002. Page = (PPFN_NUMBER)(MemoryDescriptorList + 1);
  1003. NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES (StartingVa,
  1004. MemoryDescriptorList->ByteCount);
  1005. LastPage = Page + NumberOfPages;
  1006. do {
  1007. if (*Page == MM_EMPTY_LIST) {
  1008. break;
  1009. }
  1010. Pfn1 = MI_PFN_ELEMENT (*Page);
  1011. //
  1012. // Each frame better be locked down already. Bugcheck if not.
  1013. //
  1014. if ((Pfn1->u3.e2.ReferenceCount != 0) ||
  1015. ((Pfn1->u3.e1.Rom == 1) && (CacheType == MmCached))) {
  1016. NOTHING;
  1017. }
  1018. else {
  1019. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1020. 0x85,
  1021. (ULONG_PTR)MemoryDescriptorList,
  1022. NumberOfPages,
  1023. (ULONG_PTR)(Pfn1 - MmPfnDatabase));
  1024. }
  1025. if (Pfn1->u3.e1.CacheAttribute == MiNotMapped) {
  1026. //
  1027. // This better be for a page allocated with
  1028. // MmAllocatePagesForMdl. Otherwise it might be a
  1029. // page on the freelist which could subsequently be
  1030. // given out with a different attribute !
  1031. //
  1032. if ((Pfn1->u4.PteFrame == MI_MAGIC_AWE_PTEFRAME) ||
  1033. #if defined (_MI_MORE_THAN_4GB_)
  1034. (Pfn1->u4.PteFrame == MI_MAGIC_4GB_RECLAIM) ||
  1035. #endif
  1036. (Pfn1->PteAddress == (PVOID) (ULONG_PTR)(X64K | 0x1))) {
  1037. NOTHING;
  1038. }
  1039. else {
  1040. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1041. 0x86,
  1042. (ULONG_PTR)MemoryDescriptorList,
  1043. NumberOfPages,
  1044. (ULONG_PTR)(Pfn1 - MmPfnDatabase));
  1045. }
  1046. }
  1047. Page += 1;
  1048. } while (Page < LastPage);
  1049. }
  1050. THUNKED_API
  1051. PVOID
  1052. VerifierMapLockedPages (
  1053. IN PMDL MemoryDescriptorList,
  1054. IN KPROCESSOR_MODE AccessMode
  1055. )
  1056. {
  1057. KIRQL CurrentIrql;
  1058. CurrentIrql = KeGetCurrentIrql();
  1059. if (AccessMode == KernelMode) {
  1060. if (CurrentIrql > DISPATCH_LEVEL) {
  1061. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1062. 0x74,
  1063. CurrentIrql,
  1064. (ULONG_PTR)MemoryDescriptorList,
  1065. (ULONG_PTR)AccessMode);
  1066. }
  1067. }
  1068. else {
  1069. if (CurrentIrql > APC_LEVEL) {
  1070. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1071. 0x75,
  1072. CurrentIrql,
  1073. (ULONG_PTR)MemoryDescriptorList,
  1074. (ULONG_PTR)AccessMode);
  1075. }
  1076. }
  1077. if ((MemoryDescriptorList->MdlFlags & MDL_IO_SPACE) == 0) {
  1078. ViCheckMdlPages (MemoryDescriptorList, MmCached);
  1079. }
  1080. if ((MemoryDescriptorList->MdlFlags & MDL_MAPPING_CAN_FAIL) == 0) {
  1081. MI_CHECK_UPTIME ();
  1082. if (VerifierSystemSufficientlyBooted == TRUE) {
  1083. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1084. 0x81,
  1085. (ULONG_PTR) MemoryDescriptorList,
  1086. MemoryDescriptorList->MdlFlags,
  1087. 0);
  1088. }
  1089. }
  1090. return MmMapLockedPages (MemoryDescriptorList, AccessMode);
  1091. }
  1092. THUNKED_API
  1093. PVOID
  1094. VerifierMapLockedPagesSpecifyCache (
  1095. IN PMDL MemoryDescriptorList,
  1096. IN KPROCESSOR_MODE AccessMode,
  1097. IN MEMORY_CACHING_TYPE CacheType,
  1098. IN PVOID RequestedAddress,
  1099. IN ULONG BugCheckOnFailure,
  1100. IN MM_PAGE_PRIORITY Priority
  1101. )
  1102. {
  1103. KIRQL CurrentIrql;
  1104. CurrentIrql = KeGetCurrentIrql ();
  1105. if (AccessMode == KernelMode) {
  1106. if (CurrentIrql > DISPATCH_LEVEL) {
  1107. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1108. 0x76,
  1109. CurrentIrql,
  1110. (ULONG_PTR)MemoryDescriptorList,
  1111. (ULONG_PTR)AccessMode);
  1112. }
  1113. }
  1114. else {
  1115. if (CurrentIrql > APC_LEVEL) {
  1116. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1117. 0x77,
  1118. CurrentIrql,
  1119. (ULONG_PTR)MemoryDescriptorList,
  1120. (ULONG_PTR)AccessMode);
  1121. }
  1122. }
  1123. if ((MemoryDescriptorList->MdlFlags & MDL_IO_SPACE) == 0) {
  1124. ViCheckMdlPages (MemoryDescriptorList, CacheType);
  1125. }
  1126. if ((MemoryDescriptorList->MdlFlags & MDL_MAPPING_CAN_FAIL) ||
  1127. (BugCheckOnFailure == 0)) {
  1128. if (ViInjectResourceFailure () == TRUE) {
  1129. return NULL;
  1130. }
  1131. }
  1132. else {
  1133. //
  1134. // All drivers must specify can fail or don't bugcheck.
  1135. //
  1136. MI_CHECK_UPTIME ();
  1137. if (VerifierSystemSufficientlyBooted == TRUE) {
  1138. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1139. 0x82,
  1140. (ULONG_PTR) MemoryDescriptorList,
  1141. MemoryDescriptorList->MdlFlags,
  1142. BugCheckOnFailure);
  1143. }
  1144. }
  1145. return MmMapLockedPagesSpecifyCache (MemoryDescriptorList,
  1146. AccessMode,
  1147. CacheType,
  1148. RequestedAddress,
  1149. BugCheckOnFailure,
  1150. Priority);
  1151. }
  1152. VOID
  1153. VerifierUnlockPages (
  1154. IN OUT PMDL MemoryDescriptorList
  1155. )
  1156. {
  1157. KIRQL CurrentIrql;
  1158. CurrentIrql = KeGetCurrentIrql();
  1159. if (CurrentIrql > DISPATCH_LEVEL) {
  1160. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1161. 0x78,
  1162. CurrentIrql,
  1163. (ULONG_PTR)MemoryDescriptorList,
  1164. 0);
  1165. }
  1166. if ((MemoryDescriptorList->MdlFlags & MDL_PAGES_LOCKED) == 0) {
  1167. //
  1168. // The caller is trying to unlock an MDL that was never locked down.
  1169. //
  1170. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1171. 0x7C,
  1172. (ULONG_PTR)MemoryDescriptorList,
  1173. (ULONG_PTR)MemoryDescriptorList->MdlFlags,
  1174. 0);
  1175. }
  1176. if (MemoryDescriptorList->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) {
  1177. //
  1178. // Nonpaged pool should never be locked down.
  1179. //
  1180. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1181. 0x7D,
  1182. (ULONG_PTR)MemoryDescriptorList,
  1183. (ULONG_PTR)MemoryDescriptorList->MdlFlags,
  1184. 0);
  1185. }
  1186. MmUnlockPages (MemoryDescriptorList);
  1187. }
  1188. VOID
  1189. VerifierUnmapLockedPages (
  1190. IN PVOID BaseAddress,
  1191. IN PMDL MemoryDescriptorList
  1192. )
  1193. {
  1194. KIRQL CurrentIrql;
  1195. CurrentIrql = KeGetCurrentIrql();
  1196. if (BaseAddress > MM_HIGHEST_USER_ADDRESS) {
  1197. if (CurrentIrql > DISPATCH_LEVEL) {
  1198. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1199. 0x79,
  1200. CurrentIrql,
  1201. (ULONG_PTR)BaseAddress,
  1202. (ULONG_PTR)MemoryDescriptorList);
  1203. }
  1204. }
  1205. else {
  1206. if (CurrentIrql > APC_LEVEL) {
  1207. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1208. 0x7A,
  1209. CurrentIrql,
  1210. (ULONG_PTR)BaseAddress,
  1211. (ULONG_PTR)MemoryDescriptorList);
  1212. }
  1213. }
  1214. MmUnmapLockedPages (BaseAddress, MemoryDescriptorList);
  1215. }
  1216. VOID
  1217. VerifierUnmapIoSpace (
  1218. IN PVOID BaseAddress,
  1219. IN SIZE_T NumberOfBytes
  1220. )
  1221. {
  1222. KIRQL CurrentIrql;
  1223. CurrentIrql = KeGetCurrentIrql();
  1224. if (CurrentIrql > DISPATCH_LEVEL) {
  1225. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1226. 0x7B,
  1227. CurrentIrql,
  1228. (ULONG_PTR)BaseAddress,
  1229. (ULONG_PTR)NumberOfBytes);
  1230. }
  1231. MmUnmapIoSpace (BaseAddress, NumberOfBytes);
  1232. }
  1233. THUNKED_API
  1234. PVOID
  1235. VerifierAllocatePool (
  1236. IN POOL_TYPE PoolType,
  1237. IN SIZE_T NumberOfBytes
  1238. )
  1239. {
  1240. PVOID CallingAddress;
  1241. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1242. VI_DETECT_RETURN_ADDRESS (CallingAddress);
  1243. if (KernelVerifier == TRUE) {
  1244. Verifier = ViLocateVerifierEntry (CallingAddress);
  1245. if ((Verifier == NULL) ||
  1246. ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) {
  1247. return ExAllocatePool (PoolType | POOL_DRIVER_MASK, NumberOfBytes);
  1248. }
  1249. PoolType |= POOL_DRIVER_MASK;
  1250. }
  1251. MmVerifierData.AllocationsWithNoTag += 1;
  1252. return VeAllocatePoolWithTagPriority (PoolType,
  1253. NumberOfBytes,
  1254. 'parW',
  1255. HighPoolPriority,
  1256. CallingAddress);
  1257. }
  1258. THUNKED_API
  1259. PVOID
  1260. VerifierAllocatePoolWithTag (
  1261. IN POOL_TYPE PoolType,
  1262. IN SIZE_T NumberOfBytes,
  1263. IN ULONG Tag
  1264. )
  1265. {
  1266. PVOID CallingAddress;
  1267. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1268. VI_DETECT_RETURN_ADDRESS (CallingAddress);
  1269. if (KernelVerifier == TRUE) {
  1270. Verifier = ViLocateVerifierEntry (CallingAddress);
  1271. if ((Verifier == NULL) ||
  1272. ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) {
  1273. return ExAllocatePoolWithTag (PoolType | POOL_DRIVER_MASK,
  1274. NumberOfBytes,
  1275. Tag);
  1276. }
  1277. PoolType |= POOL_DRIVER_MASK;
  1278. }
  1279. return VeAllocatePoolWithTagPriority (PoolType,
  1280. NumberOfBytes,
  1281. Tag,
  1282. HighPoolPriority,
  1283. CallingAddress);
  1284. }
  1285. THUNKED_API
  1286. PVOID
  1287. VerifierAllocatePoolWithQuota(
  1288. IN POOL_TYPE PoolType,
  1289. IN SIZE_T NumberOfBytes
  1290. )
  1291. {
  1292. PVOID Va;
  1293. LOGICAL RaiseOnQuotaFailure;
  1294. PVOID CallingAddress;
  1295. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1296. VI_DETECT_RETURN_ADDRESS (CallingAddress);
  1297. if (KernelVerifier == TRUE) {
  1298. Verifier = ViLocateVerifierEntry (CallingAddress);
  1299. if ((Verifier == NULL) ||
  1300. ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) {
  1301. return ExAllocatePoolWithQuota (PoolType | POOL_DRIVER_MASK,
  1302. NumberOfBytes);
  1303. }
  1304. PoolType |= POOL_DRIVER_MASK;
  1305. }
  1306. MmVerifierData.AllocationsWithNoTag += 1;
  1307. if (PoolType & POOL_QUOTA_FAIL_INSTEAD_OF_RAISE) {
  1308. RaiseOnQuotaFailure = FALSE;
  1309. PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE;
  1310. }
  1311. else {
  1312. RaiseOnQuotaFailure = TRUE;
  1313. }
  1314. Va = VeAllocatePoolWithTagPriority (PoolType,
  1315. NumberOfBytes,
  1316. 'parW',
  1317. HighPoolPriority,
  1318. CallingAddress);
  1319. if (Va == NULL) {
  1320. if (RaiseOnQuotaFailure == TRUE) {
  1321. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  1322. }
  1323. }
  1324. return Va;
  1325. }
  1326. THUNKED_API
  1327. PVOID
  1328. VerifierAllocatePoolWithQuotaTag(
  1329. IN POOL_TYPE PoolType,
  1330. IN SIZE_T NumberOfBytes,
  1331. IN ULONG Tag
  1332. )
  1333. {
  1334. PVOID Va;
  1335. LOGICAL RaiseOnQuotaFailure;
  1336. PVOID CallingAddress;
  1337. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1338. VI_DETECT_RETURN_ADDRESS (CallingAddress);
  1339. if (KernelVerifier == TRUE) {
  1340. Verifier = ViLocateVerifierEntry (CallingAddress);
  1341. if ((Verifier == NULL) ||
  1342. ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) {
  1343. return ExAllocatePoolWithQuotaTag (PoolType | POOL_DRIVER_MASK,
  1344. NumberOfBytes,
  1345. Tag);
  1346. }
  1347. PoolType |= POOL_DRIVER_MASK;
  1348. }
  1349. if (PoolType & POOL_QUOTA_FAIL_INSTEAD_OF_RAISE) {
  1350. RaiseOnQuotaFailure = FALSE;
  1351. PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE;
  1352. }
  1353. else {
  1354. RaiseOnQuotaFailure = TRUE;
  1355. }
  1356. Va = VeAllocatePoolWithTagPriority (PoolType,
  1357. NumberOfBytes,
  1358. Tag,
  1359. HighPoolPriority,
  1360. CallingAddress);
  1361. if (Va == NULL) {
  1362. if (RaiseOnQuotaFailure == TRUE) {
  1363. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  1364. }
  1365. }
  1366. return Va;
  1367. }
  1368. THUNKED_API
  1369. PVOID
  1370. VerifierAllocatePoolWithTagPriority(
  1371. IN POOL_TYPE PoolType,
  1372. IN SIZE_T NumberOfBytes,
  1373. IN ULONG Tag,
  1374. IN EX_POOL_PRIORITY Priority
  1375. )
  1376. /*++
  1377. Routine Description:
  1378. This thunked-in function:
  1379. - Performs sanity checks on the caller.
  1380. - Can optionally provide allocation failures to the caller.
  1381. - Attempts to provide the allocation from special pool.
  1382. - Tracks pool to ensure callers free everything they allocate.
  1383. --*/
  1384. {
  1385. PVOID CallingAddress;
  1386. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1387. VI_DETECT_RETURN_ADDRESS (CallingAddress);
  1388. if (KernelVerifier == TRUE) {
  1389. Verifier = ViLocateVerifierEntry (CallingAddress);
  1390. if ((Verifier == NULL) ||
  1391. ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0)) {
  1392. return ExAllocatePoolWithTagPriority (PoolType | POOL_DRIVER_MASK,
  1393. NumberOfBytes,
  1394. Tag,
  1395. Priority);
  1396. }
  1397. PoolType |= POOL_DRIVER_MASK;
  1398. }
  1399. return VeAllocatePoolWithTagPriority (PoolType,
  1400. NumberOfBytes,
  1401. Tag,
  1402. Priority,
  1403. CallingAddress);
  1404. }
  1405. LOGICAL
  1406. ViInjectResourceFailure (
  1407. VOID
  1408. )
  1409. /*++
  1410. Routine Description:
  1411. This function determines whether a resource allocation should be
  1412. deliberately failed. This may be a pool allocation, MDL creation,
  1413. system PTE allocation, etc.
  1414. Arguments:
  1415. None.
  1416. Return Value:
  1417. TRUE if the allocation should be failed. FALSE otherwise.
  1418. Environment:
  1419. Kernel mode. DISPATCH_LEVEL or below.
  1420. --*/
  1421. {
  1422. ULONG TimeLow;
  1423. LARGE_INTEGER CurrentTime;
  1424. if ((MmVerifierData.Level & DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES) == 0) {
  1425. return FALSE;
  1426. }
  1427. //
  1428. // Don't fail any requests in the first 7 or 8 minutes as we want to
  1429. // give the system enough time to boot.
  1430. //
  1431. MI_CHECK_UPTIME ();
  1432. if (VerifierSystemSufficientlyBooted == TRUE) {
  1433. KeQueryTickCount(&CurrentTime);
  1434. TimeLow = CurrentTime.LowPart;
  1435. if ((TimeLow & 0xF) == 0) {
  1436. MmVerifierData.AllocationsFailedDeliberately += 1;
  1437. //
  1438. // Deliberately fail this request.
  1439. //
  1440. if (MiFaultRetryMask != 0xFFFFFFFF) {
  1441. MiFaultRetryMask = 0xFFFFFFFF;
  1442. MiUserFaultRetryMask = 0xFFFFFFFF;
  1443. }
  1444. #if defined(_X86_)
  1445. ViFaultTracesLog ();
  1446. #endif
  1447. return TRUE;
  1448. }
  1449. //
  1450. // Approximately every 5 minutes (on most systems), fail all of this
  1451. // components allocations for a 10 second burst. This more closely
  1452. // simulates (and exaggerates) the duration of the typical low resource
  1453. // scenario.
  1454. //
  1455. TimeLow &= 0x7FFF;
  1456. if (TimeLow < 0x400) {
  1457. MmVerifierData.BurstAllocationsFailedDeliberately += 1;
  1458. //
  1459. // Deliberately fail this request.
  1460. //
  1461. if (MiFaultRetryMask != 0xFFFFFFFF) {
  1462. MiFaultRetryMask = 0xFFFFFFFF;
  1463. MiUserFaultRetryMask = 0xFFFFFFFF;
  1464. }
  1465. #if defined(_X86_)
  1466. ViFaultTracesLog ();
  1467. #endif
  1468. return TRUE;
  1469. }
  1470. }
  1471. return FALSE;
  1472. }
  1473. LOGICAL
  1474. ViReservePoolAllocation (
  1475. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  1476. )
  1477. {
  1478. ULONG_PTR OldSize;
  1479. ULONG_PTR NewSize;
  1480. ULONG_PTR NewHashOffset;
  1481. ULONG_PTR Increment;
  1482. ULONG_PTR Entries;
  1483. ULONG_PTR i;
  1484. KIRQL OldIrql;
  1485. PVOID NewHashTable;
  1486. PVI_POOL_ENTRY HashEntry;
  1487. PVI_POOL_ENTRY OldHashTable;
  1488. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  1489. while (Verifier->PoolHashSize <= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved) {
  1490. //
  1491. // More space is needed. Try for it now.
  1492. //
  1493. #define VI_POOL_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(VI_POOL_ENTRY))
  1494. OldSize = Verifier->PoolHashSize * sizeof(VI_POOL_ENTRY);
  1495. if (Verifier->PoolHashSize >= VI_POOL_ENTRIES_PER_PAGE) {
  1496. Increment = PAGE_SIZE;
  1497. }
  1498. else {
  1499. Increment = 16 * sizeof (VI_POOL_ENTRY);
  1500. }
  1501. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1502. NewSize = OldSize + Increment;
  1503. if (NewSize < OldSize) {
  1504. return FALSE;
  1505. }
  1506. //
  1507. // Note POOL_DRIVER_MASK must be set to stop the recursion loop
  1508. // when using the kernel verifier.
  1509. //
  1510. NewHashTable = ExAllocatePoolWithTagPriority (NonPagedPool | POOL_DRIVER_MASK,
  1511. NewSize,
  1512. 'ppeV',
  1513. HighPoolPriority);
  1514. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  1515. OldSize = Verifier->PoolHashSize * sizeof(VI_POOL_ENTRY);
  1516. if (NewHashTable == NULL) {
  1517. if (Verifier->PoolHashSize <= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved) {
  1518. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1519. return FALSE;
  1520. }
  1521. //
  1522. // Another thread got here before us and space is available.
  1523. //
  1524. break;
  1525. }
  1526. if (NewSize != OldSize + Increment) {
  1527. //
  1528. // Another thread got here before us.
  1529. //
  1530. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1531. ExFreePool (NewHashTable);
  1532. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  1533. }
  1534. else {
  1535. //
  1536. // Rebuild the list into the new table.
  1537. //
  1538. OldHashTable = Verifier->PoolHash;
  1539. if (OldHashTable != NULL) {
  1540. RtlCopyMemory (NewHashTable, OldHashTable, OldSize);
  1541. }
  1542. //
  1543. // Construct the freelist chaining it through any existing
  1544. // list (any free entries must be already reserved).
  1545. //
  1546. HashEntry = (PVI_POOL_ENTRY) ((PCHAR)NewHashTable + OldSize);
  1547. Entries = Increment / sizeof (VI_POOL_ENTRY);
  1548. NewHashOffset = HashEntry - (PVI_POOL_ENTRY)NewHashTable;
  1549. //
  1550. // If list compaction becomes important then chaining it on the
  1551. // end here will need to be revisited.
  1552. //
  1553. for (i = 0; i < Entries; i += 1) {
  1554. HashEntry->FreeListNext = NewHashOffset + i + 1;
  1555. HashEntry += 1;
  1556. }
  1557. HashEntry -= 1;
  1558. HashEntry->FreeListNext = Verifier->PoolHashFree;
  1559. Verifier->PoolHashFree = NewHashOffset;
  1560. Verifier->PoolHash = NewHashTable;
  1561. Verifier->PoolHashSize += Entries;
  1562. //
  1563. // Free the old table.
  1564. //
  1565. if (OldHashTable != NULL) {
  1566. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1567. ExFreePool (OldHashTable);
  1568. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  1569. }
  1570. }
  1571. }
  1572. Verifier->PoolHashReserved += 1;
  1573. ASSERT (Verifier->PoolHashSize >= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved);
  1574. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1575. return TRUE;
  1576. }
  1577. ULONG_PTR
  1578. ViInsertPoolAllocation (
  1579. IN PMI_VERIFIER_DRIVER_ENTRY Verifier,
  1580. IN PVOID VirtualAddress,
  1581. IN PVOID CallingAddress,
  1582. IN SIZE_T NumberOfBytes,
  1583. IN ULONG Tag
  1584. )
  1585. /*++
  1586. Routine Description:
  1587. This function inserts the specified virtual address into the verifier
  1588. list for this driver.
  1589. Arguments:
  1590. Verifier - Supplies the verifier entry to update.
  1591. VirtualAddress - Supplies the virtual address to insert.
  1592. CallingAddress - Supplies the caller's address.
  1593. NumberOfBytes - Supplies the number of bytes to allocate.
  1594. Tag - Supplies the tag for the pool being allocated.
  1595. Return Value:
  1596. The list index this virtual address was inserted at.
  1597. Environment:
  1598. Kernel mode, DISPATCH_LEVEL. The Verifier->VerifierPoolLock must be held.
  1599. --*/
  1600. {
  1601. ULONG_PTR Index;
  1602. PVI_POOL_ENTRY HashEntry;
  1603. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  1604. //
  1605. // The list entry must be reserved in advance.
  1606. //
  1607. ASSERT (Verifier->PoolHashReserved != 0);
  1608. ASSERT (Verifier->PoolHashSize >= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved);
  1609. //
  1610. // Use the next free list entry.
  1611. //
  1612. Index = Verifier->PoolHashFree;
  1613. ASSERT (Index != VI_POOL_FREELIST_END);
  1614. HashEntry = Verifier->PoolHash + Index;
  1615. Verifier->PoolHashFree = HashEntry->FreeListNext;
  1616. Verifier->PoolHashReserved -= 1;
  1617. #if defined (_X86_)
  1618. //
  1619. // MiUseMaximumSystemSpace denotes an x86 mode where kernel pointers don't
  1620. // necessarily have the high bit set.
  1621. //
  1622. ASSERT (((HashEntry->FreeListNext & MINLONG_PTR) == 0) ||
  1623. (HashEntry->FreeListNext == VI_POOL_FREELIST_END) ||
  1624. (MiUseMaximumSystemSpace != 0));
  1625. #else
  1626. ASSERT (((HashEntry->FreeListNext & MINLONG_PTR) == 0) ||
  1627. (HashEntry->FreeListNext == VI_POOL_FREELIST_END));
  1628. #endif
  1629. HashEntry->InUse.VirtualAddress = VirtualAddress;
  1630. HashEntry->InUse.CallingAddress = CallingAddress;
  1631. HashEntry->InUse.NumberOfBytes = NumberOfBytes;
  1632. HashEntry->InUse.Tag = Tag;
  1633. #if defined (_X86_)
  1634. //
  1635. // MiUseMaximumSystemSpace denotes an x86 mode where kernel pointers don't
  1636. // necessarily have the high bit set.
  1637. //
  1638. ASSERT (((HashEntry->FreeListNext & MINLONG_PTR) != 0) ||
  1639. (MiUseMaximumSystemSpace != 0));
  1640. #else
  1641. ASSERT ((HashEntry->FreeListNext & MINLONG_PTR) != 0);
  1642. #endif
  1643. return Index;
  1644. }
  1645. VOID
  1646. ViReleasePoolAllocation (
  1647. IN PMI_VERIFIER_DRIVER_ENTRY Verifier,
  1648. IN PVOID VirtualAddress,
  1649. IN ULONG_PTR ListIndex,
  1650. IN SIZE_T ChargedBytes
  1651. )
  1652. /*++
  1653. Routine Description:
  1654. This function removes the specified virtual address from the verifier
  1655. list for this driver.
  1656. Arguments:
  1657. Verifier - Supplies the verifier entry to update.
  1658. VirtualAddress - Supplies the virtual address to release.
  1659. ListIndex - Supplies the verifier pool hash index for the address being
  1660. released.
  1661. ChargedBytes - Supplies the bytes charged for this allocation.
  1662. Return Value:
  1663. None.
  1664. Environment:
  1665. Kernel mode, DISPATCH_LEVEL. The Verifier->VerifierPoolLock must be held.
  1666. --*/
  1667. {
  1668. PFN_NUMBER PageFrameIndex;
  1669. PFN_NUMBER PageFrameIndex2;
  1670. PVI_POOL_ENTRY HashEntry;
  1671. PMMPTE PointerPte;
  1672. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  1673. if (Verifier->PoolHash == NULL) {
  1674. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1675. 0x59,
  1676. (ULONG_PTR)VirtualAddress,
  1677. ListIndex,
  1678. (ULONG_PTR)Verifier);
  1679. }
  1680. //
  1681. // Ensure that the list pointer has not been overrun and still
  1682. // points at something decent.
  1683. //
  1684. HashEntry = Verifier->PoolHash + ListIndex;
  1685. if (ListIndex >= Verifier->PoolHashSize) {
  1686. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1687. 0x54,
  1688. (ULONG_PTR)VirtualAddress,
  1689. Verifier->PoolHashSize,
  1690. ListIndex);
  1691. }
  1692. if (HashEntry->InUse.VirtualAddress != VirtualAddress) {
  1693. PageFrameIndex = 0;
  1694. PageFrameIndex2 = 1;
  1695. if ((!MI_IS_PHYSICAL_ADDRESS(VirtualAddress)) &&
  1696. (MI_IS_PHYSICAL_ADDRESS(HashEntry->InUse.VirtualAddress))) {
  1697. PointerPte = MiGetPteAddress(VirtualAddress);
  1698. if (PointerPte->u.Hard.Valid == 1) {
  1699. PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
  1700. PageFrameIndex2 = MI_CONVERT_PHYSICAL_TO_PFN (HashEntry->InUse.VirtualAddress);
  1701. }
  1702. }
  1703. //
  1704. // Caller overran and corrupted the virtual address - the linked
  1705. // list cannot be counted on either.
  1706. //
  1707. if (PageFrameIndex != PageFrameIndex2) {
  1708. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1709. 0x52,
  1710. (ULONG_PTR)VirtualAddress,
  1711. (ULONG_PTR)HashEntry->InUse.VirtualAddress,
  1712. ChargedBytes);
  1713. }
  1714. }
  1715. if (HashEntry->InUse.NumberOfBytes != ChargedBytes) {
  1716. //
  1717. // Caller overran and corrupted the byte count - the linked
  1718. // list cannot be counted on either.
  1719. //
  1720. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  1721. 0x51,
  1722. (ULONG_PTR)VirtualAddress,
  1723. (ULONG_PTR)HashEntry,
  1724. ChargedBytes);
  1725. }
  1726. //
  1727. // Put this list entry into the freelist.
  1728. //
  1729. HashEntry->FreeListNext = Verifier->PoolHashFree;
  1730. Verifier->PoolHashFree = HashEntry - Verifier->PoolHash;
  1731. }
  1732. VOID
  1733. ViCancelPoolAllocation (
  1734. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  1735. )
  1736. /*++
  1737. Routine Description:
  1738. This function removes a reservation from the verifier list for this driver.
  1739. All reservations must be made in advance. This routine is used when an
  1740. earlier reservation is not going to be used (ie: the actual pool
  1741. allocation failed so no reservation will be needed after all).
  1742. Arguments:
  1743. Verifier - Supplies the verifier entry to update.
  1744. Return Value:
  1745. None.
  1746. Environment:
  1747. Kernel mode, DISPATCH_LEVEL or below, no verifier mutexes held.
  1748. --*/
  1749. {
  1750. KIRQL OldIrql;
  1751. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  1752. //
  1753. // The hash entry reserved earlier is not going to be used after all.
  1754. //
  1755. ASSERT (Verifier->PoolHashReserved != 0);
  1756. ASSERT (Verifier->PoolHashSize >= Verifier->CurrentPagedPoolAllocations + Verifier->CurrentNonPagedPoolAllocations + Verifier->PoolHashReserved);
  1757. ASSERT (Verifier->PoolHashFree != VI_POOL_FREELIST_END);
  1758. Verifier->PoolHashReserved -= 1;
  1759. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1760. }
  1761. PVOID
  1762. ViPostPoolAllocation (
  1763. IN PVOID VirtualAddress,
  1764. IN SIZE_T NumberOfBytes,
  1765. IN POOL_TYPE PoolType,
  1766. IN ULONG Tag,
  1767. IN PVOID CallingAddress
  1768. )
  1769. /*++
  1770. Routine Description:
  1771. This function performs verifier book-keeping on the allocation attempt.
  1772. Arguments:
  1773. VirtualAddress - Supplies the virtual address that should be allocated.
  1774. NumberOfBytes - Supplies the number of bytes to allocate.
  1775. PoolType - Supplies the type of pool being allocated.
  1776. Tag - Supplies the tag for the pool being allocated.
  1777. CallingAddress - Supplies the caller's address.
  1778. Return Value:
  1779. The virtual address the caller should use.
  1780. Environment:
  1781. Kernel mode. DISPATCH_LEVEL or below.
  1782. --*/
  1783. {
  1784. KIRQL OldIrql;
  1785. PMI_VERIFIER_POOL_HEADER Header;
  1786. SIZE_T ChargedBytes;
  1787. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1788. ULONG_PTR InsertedIndex;
  1789. LOGICAL SpecialPoolAllocation;
  1790. PPOOL_HEADER PoolHeader;
  1791. InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsSucceeded);
  1792. ChargedBytes = EX_REAL_POOL_USAGE(NumberOfBytes);
  1793. SpecialPoolAllocation = FALSE;
  1794. if (MmIsSpecialPoolAddress (VirtualAddress) == TRUE) {
  1795. ChargedBytes = NumberOfBytes;
  1796. InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsSucceededSpecialPool);
  1797. SpecialPoolAllocation = TRUE;
  1798. }
  1799. else if (NumberOfBytes <= POOL_BUDDY_MAX) {
  1800. ChargedBytes -= POOL_OVERHEAD;
  1801. }
  1802. else {
  1803. //
  1804. // This isn't exactly true but it does give the user a way to see
  1805. // if this machine is large enough to support special pool 100%.
  1806. //
  1807. InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsSucceededSpecialPool);
  1808. }
  1809. if ((PoolType & POOL_VERIFIER_MASK) == 0) {
  1810. return VirtualAddress;
  1811. }
  1812. if (NumberOfBytes > POOL_BUDDY_MAX) {
  1813. ASSERT (BYTE_OFFSET(VirtualAddress) == 0);
  1814. }
  1815. Verifier = ViLocateVerifierEntry (CallingAddress);
  1816. ASSERT (Verifier != NULL);
  1817. VerifierIsTrackingPool = TRUE;
  1818. if (SpecialPoolAllocation == TRUE) {
  1819. //
  1820. // Carefully adjust the special pool page to move the verifier tracking
  1821. // header to the front. This allows the allocation to remain butted
  1822. // against the end of the page so overruns can be detected immediately.
  1823. //
  1824. if (((ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1))) {
  1825. PoolHeader = (PPOOL_HEADER)(PAGE_ALIGN (VirtualAddress));
  1826. Header = (PMI_VERIFIER_POOL_HEADER) (PoolHeader + 1);
  1827. VirtualAddress = (PVOID) ((PCHAR)VirtualAddress + sizeof (MI_VERIFIER_POOL_HEADER));
  1828. }
  1829. else {
  1830. PoolHeader = (PPOOL_HEADER)((PCHAR)PAGE_ALIGN (VirtualAddress) + PAGE_SIZE - POOL_OVERHEAD);
  1831. Header = (PMI_VERIFIER_POOL_HEADER) (PoolHeader - 1);
  1832. }
  1833. // ASSERT (PoolHeader->Ulong1 & MI_SPECIAL_POOL_VERIFIER);
  1834. PoolHeader->Ulong1 -= sizeof (MI_VERIFIER_POOL_HEADER);
  1835. ChargedBytes -= sizeof (MI_VERIFIER_POOL_HEADER);
  1836. PoolHeader->Ulong1 |= MI_SPECIAL_POOL_VERIFIER;
  1837. }
  1838. else {
  1839. Header = (PMI_VERIFIER_POOL_HEADER)((PCHAR)VirtualAddress +
  1840. ChargedBytes -
  1841. sizeof(MI_VERIFIER_POOL_HEADER));
  1842. }
  1843. ASSERT (((ULONG_PTR)Header & (sizeof(ULONG) - 1)) == 0);
  1844. Header->Verifier = Verifier;
  1845. //
  1846. // Enqueue the entry and update per-driver counters.
  1847. // Note that paged pool allocations must be chained using nonpaged
  1848. // pool to prevent deadlocks.
  1849. //
  1850. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  1851. InsertedIndex = ViInsertPoolAllocation (Verifier,
  1852. VirtualAddress,
  1853. CallingAddress,
  1854. ChargedBytes,
  1855. Tag);
  1856. if ((PoolType & BASE_POOL_TYPE_MASK) == PagedPool) {
  1857. Verifier->PagedBytes += ChargedBytes;
  1858. if (Verifier->PagedBytes > Verifier->PeakPagedBytes) {
  1859. Verifier->PeakPagedBytes = Verifier->PagedBytes;
  1860. }
  1861. Verifier->CurrentPagedPoolAllocations += 1;
  1862. if (Verifier->CurrentPagedPoolAllocations > Verifier->PeakPagedPoolAllocations) {
  1863. Verifier->PeakPagedPoolAllocations = Verifier->CurrentPagedPoolAllocations;
  1864. }
  1865. }
  1866. else {
  1867. Verifier->NonPagedBytes += ChargedBytes;
  1868. if (Verifier->NonPagedBytes > Verifier->PeakNonPagedBytes) {
  1869. Verifier->PeakNonPagedBytes = Verifier->NonPagedBytes;
  1870. }
  1871. Verifier->CurrentNonPagedPoolAllocations += 1;
  1872. if (Verifier->CurrentNonPagedPoolAllocations > Verifier->PeakNonPagedPoolAllocations) {
  1873. Verifier->PeakNonPagedPoolAllocations = Verifier->CurrentNonPagedPoolAllocations;
  1874. }
  1875. }
  1876. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  1877. //
  1878. // Since the header for paged pool is paged, don't initialize it until the
  1879. // spinlock above is released.
  1880. //
  1881. Header->ListIndex = InsertedIndex;
  1882. //
  1883. // Update systemwide counters.
  1884. //
  1885. if ((PoolType & BASE_POOL_TYPE_MASK) == PagedPool) {
  1886. ExAcquireFastMutex (&VerifierPoolMutex);
  1887. MmVerifierData.PagedBytes += ChargedBytes;
  1888. if (MmVerifierData.PagedBytes > MmVerifierData.PeakPagedBytes) {
  1889. MmVerifierData.PeakPagedBytes = MmVerifierData.PagedBytes;
  1890. }
  1891. MmVerifierData.CurrentPagedPoolAllocations += 1;
  1892. if (MmVerifierData.CurrentPagedPoolAllocations > MmVerifierData.PeakPagedPoolAllocations) {
  1893. MmVerifierData.PeakPagedPoolAllocations = MmVerifierData.CurrentPagedPoolAllocations;
  1894. }
  1895. ExReleaseFastMutex (&VerifierPoolMutex);
  1896. }
  1897. else {
  1898. ExAcquireSpinLock (&VerifierPoolLock, &OldIrql);
  1899. MmVerifierData.NonPagedBytes += ChargedBytes;
  1900. if (MmVerifierData.NonPagedBytes > MmVerifierData.PeakNonPagedBytes) {
  1901. MmVerifierData.PeakNonPagedBytes = MmVerifierData.NonPagedBytes;
  1902. }
  1903. MmVerifierData.CurrentNonPagedPoolAllocations += 1;
  1904. if (MmVerifierData.CurrentNonPagedPoolAllocations > MmVerifierData.PeakNonPagedPoolAllocations) {
  1905. MmVerifierData.PeakNonPagedPoolAllocations = MmVerifierData.CurrentNonPagedPoolAllocations;
  1906. }
  1907. ExReleaseSpinLock (&VerifierPoolLock, OldIrql);
  1908. }
  1909. return VirtualAddress;
  1910. }
  1911. PVOID
  1912. VeAllocatePoolWithTagPriority (
  1913. IN POOL_TYPE PoolType,
  1914. IN SIZE_T NumberOfBytes,
  1915. IN ULONG Tag,
  1916. IN EX_POOL_PRIORITY Priority,
  1917. IN PVOID CallingAddress
  1918. )
  1919. /*++
  1920. Routine Description:
  1921. This routine is called both from ex\pool.c and directly within this module.
  1922. - Performs sanity checks on the caller.
  1923. - Can optionally provide allocation failures to the caller.
  1924. - Attempts to provide the allocation from special pool.
  1925. - Tracks pool to ensure callers free everything they allocate.
  1926. --*/
  1927. {
  1928. PVOID VirtualAddress;
  1929. EX_POOL_PRIORITY AllocationPriority;
  1930. SIZE_T ChargedBytes;
  1931. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  1932. LOGICAL ReservedHash;
  1933. ULONG HeaderSize;
  1934. ExAllocatePoolSanityChecks (PoolType, NumberOfBytes);
  1935. InterlockedIncrement ((PLONG)&MmVerifierData.AllocationsAttempted);
  1936. if ((PoolType & MUST_SUCCEED_POOL_TYPE_MASK) == 0) {
  1937. if (ViInjectResourceFailure () == TRUE) {
  1938. //
  1939. // Caller requested an exception - throw it here.
  1940. //
  1941. if ((PoolType & POOL_RAISE_IF_ALLOCATION_FAILURE) != 0) {
  1942. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  1943. }
  1944. return NULL;
  1945. }
  1946. }
  1947. else {
  1948. MI_CHECK_UPTIME ();
  1949. if (VerifierSystemSufficientlyBooted == TRUE) {
  1950. KeBugCheckEx (BAD_POOL_CALLER,
  1951. 0x9A,
  1952. PoolType,
  1953. NumberOfBytes,
  1954. Tag);
  1955. }
  1956. }
  1957. ASSERT ((PoolType & POOL_VERIFIER_MASK) == 0);
  1958. //
  1959. // Initializing Verifier is not needed for
  1960. // correctness but without it the compiler cannot compile this code
  1961. // W4 to check for use of uninitialized variables.
  1962. //
  1963. Verifier = NULL;
  1964. AllocationPriority = Priority;
  1965. if (MmVerifierData.Level & DRIVER_VERIFIER_SPECIAL_POOLING) {
  1966. //
  1967. // Try for a special pool overrun allocation unless the caller has
  1968. // explicitly specified otherwise.
  1969. //
  1970. if ((AllocationPriority & (LowPoolPrioritySpecialPoolOverrun | LowPoolPrioritySpecialPoolUnderrun)) == 0) {
  1971. if (MmSpecialPoolCatchOverruns == TRUE) {
  1972. AllocationPriority |= LowPoolPrioritySpecialPoolOverrun;
  1973. }
  1974. else {
  1975. AllocationPriority |= LowPoolPrioritySpecialPoolUnderrun;
  1976. }
  1977. }
  1978. }
  1979. ReservedHash = FALSE;
  1980. if (MmVerifierData.Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) {
  1981. if (PoolType & SESSION_POOL_MASK) {
  1982. //
  1983. // Session pool is directly tracked by default already.
  1984. //
  1985. NOTHING;
  1986. }
  1987. else {
  1988. HeaderSize = sizeof(MI_VERIFIER_POOL_HEADER);
  1989. ChargedBytes = MI_ROUND_TO_SIZE (NumberOfBytes, sizeof(ULONG)) + HeaderSize;
  1990. Verifier = ViLocateVerifierEntry (CallingAddress);
  1991. if ((Verifier == NULL) ||
  1992. ((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0) ||
  1993. (Verifier->Flags & VI_DISABLE_VERIFICATION)) {
  1994. //
  1995. // This can happen for many reasons including no framing (which
  1996. // can cause RtlGetCallersAddress to return the wrong address),
  1997. // etc.
  1998. //
  1999. MmVerifierData.UnTrackedPool += 1;
  2000. }
  2001. else if (ChargedBytes <= NumberOfBytes) {
  2002. //
  2003. // Don't let the verifier header transform a bad caller into a
  2004. // good caller. Fail via the fall through so an exception
  2005. // can be thrown if asked for, etc.
  2006. //
  2007. MmVerifierData.UnTrackedPool += 1;
  2008. }
  2009. else if (((PoolType & MUST_SUCCEED_POOL_TYPE_MASK) == 0) ||
  2010. (ChargedBytes <= PAGE_SIZE)) {
  2011. //
  2012. // Any pool allocation that is allowed to fail or where the
  2013. // total number of charged bytes fits in a page (nonpaged-
  2014. // must-succeed requires this) is suitable for tracking.
  2015. // Just ensure that the hash list has space for it.
  2016. //
  2017. if (ViReservePoolAllocation (Verifier) == TRUE) {
  2018. ReservedHash = TRUE;
  2019. NumberOfBytes = ChargedBytes;
  2020. PoolType |= POOL_VERIFIER_MASK;
  2021. }
  2022. }
  2023. else {
  2024. ASSERT ((PoolType & BASE_POOL_TYPE_MASK) == NonPagedPool);
  2025. MmVerifierData.UnTrackedPool += 1;
  2026. }
  2027. }
  2028. }
  2029. VirtualAddress = ExAllocatePoolWithTagPriority (PoolType,
  2030. NumberOfBytes,
  2031. Tag,
  2032. AllocationPriority);
  2033. if (VirtualAddress == NULL) {
  2034. MmVerifierData.AllocationsFailed += 1;
  2035. if (ReservedHash == TRUE) {
  2036. //
  2037. // Release the hash table entry now as it's not needed.
  2038. //
  2039. ViCancelPoolAllocation (Verifier);
  2040. }
  2041. if ((PoolType & POOL_RAISE_IF_ALLOCATION_FAILURE) != 0) {
  2042. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  2043. }
  2044. return NULL;
  2045. }
  2046. VirtualAddress = ViPostPoolAllocation (VirtualAddress,
  2047. NumberOfBytes,
  2048. PoolType,
  2049. Tag,
  2050. CallingAddress);
  2051. return VirtualAddress;
  2052. }
  2053. VOID
  2054. ViFreeTrackedPool (
  2055. IN PVOID VirtualAddress,
  2056. IN SIZE_T ChargedBytes,
  2057. IN LOGICAL CheckType,
  2058. IN LOGICAL SpecialPool
  2059. )
  2060. /*++
  2061. Routine Description:
  2062. Called directly from the pool manager or the memory manager for verifier-
  2063. tracked allocations. The call to ExFreePool is already in progress.
  2064. Arguments:
  2065. VirtualAddress - Supplies the virtual address being freed.
  2066. ChargedBytes - Supplies the number of bytes charged to this allocation.
  2067. CheckType - Supplies PagedPool or NonPagedPool.
  2068. SpecialPool - Supplies TRUE if the allocation is from special pool.
  2069. Return Value:
  2070. None.
  2071. Environment:
  2072. Kernel mode.
  2073. N.B.
  2074. Callers freeing small pool allocations hold no locks or mutexes on entry.
  2075. Callers freeing special pool hold no locks or mutexes on entry.
  2076. Callers freeing pool of PAGE_SIZE or larger hold the nonpaged pool spinlock
  2077. or the PagedPool mutex (depending on allocation type) on entry.
  2078. --*/
  2079. {
  2080. KIRQL OldIrql;
  2081. ULONG_PTR Index;
  2082. PPOOL_HEADER PoolHeader;
  2083. PMI_VERIFIER_POOL_HEADER Header;
  2084. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  2085. ASSERT (VerifierIsTrackingPool == TRUE);
  2086. if (SpecialPool == TRUE) {
  2087. //
  2088. // Special pool allocation.
  2089. //
  2090. if (((ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1))) {
  2091. PoolHeader = PAGE_ALIGN (VirtualAddress);
  2092. Header = (PMI_VERIFIER_POOL_HEADER)(PoolHeader + 1);
  2093. }
  2094. else {
  2095. PoolHeader = (PPOOL_HEADER)((PCHAR)PAGE_ALIGN (VirtualAddress) + PAGE_SIZE - POOL_OVERHEAD);
  2096. Header = (PMI_VERIFIER_POOL_HEADER)(PoolHeader - 1);
  2097. }
  2098. }
  2099. else if (PAGE_ALIGNED(VirtualAddress)) {
  2100. //
  2101. // Large page allocation.
  2102. //
  2103. Header = (PMI_VERIFIER_POOL_HEADER) ((PCHAR)VirtualAddress +
  2104. ChargedBytes -
  2105. sizeof(MI_VERIFIER_POOL_HEADER));
  2106. }
  2107. else {
  2108. ChargedBytes -= POOL_OVERHEAD;
  2109. Header = (PMI_VERIFIER_POOL_HEADER) ((PCHAR)VirtualAddress +
  2110. ChargedBytes -
  2111. sizeof(MI_VERIFIER_POOL_HEADER));
  2112. }
  2113. Verifier = Header->Verifier;
  2114. //
  2115. // Check the pointer now so we can give a more friendly bugcheck
  2116. // rather than crashing below on a bad reference.
  2117. //
  2118. if ((((ULONG_PTR)Verifier & (sizeof(ULONG) - 1)) != 0) ||
  2119. (!MmIsAddressValid(&Verifier->Signature)) ||
  2120. (Verifier->Signature != MI_VERIFIER_ENTRY_SIGNATURE)) {
  2121. //
  2122. // The caller corrupted the saved verifier field.
  2123. //
  2124. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2125. 0x53,
  2126. (ULONG_PTR)VirtualAddress,
  2127. (ULONG_PTR)Header,
  2128. (ULONG_PTR)Verifier);
  2129. }
  2130. Index = Header->ListIndex;
  2131. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  2132. ViReleasePoolAllocation (Verifier,
  2133. VirtualAddress,
  2134. Index,
  2135. ChargedBytes);
  2136. if (CheckType == PagedPool) {
  2137. Verifier->PagedBytes -= ChargedBytes;
  2138. Verifier->CurrentPagedPoolAllocations -= 1;
  2139. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  2140. ExAcquireFastMutex (&VerifierPoolMutex);
  2141. MmVerifierData.PagedBytes -= ChargedBytes;
  2142. MmVerifierData.CurrentPagedPoolAllocations -= 1;
  2143. ExReleaseFastMutex (&VerifierPoolMutex);
  2144. }
  2145. else {
  2146. Verifier->NonPagedBytes -= ChargedBytes;
  2147. Verifier->CurrentNonPagedPoolAllocations -= 1;
  2148. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  2149. ExAcquireSpinLock (&VerifierPoolLock, &OldIrql);
  2150. MmVerifierData.NonPagedBytes -= ChargedBytes;
  2151. MmVerifierData.CurrentNonPagedPoolAllocations -= 1;
  2152. ExReleaseSpinLock (&VerifierPoolLock, OldIrql);
  2153. }
  2154. }
  2155. VOID
  2156. VerifierFreeTrackedPool (
  2157. IN PVOID VirtualAddress,
  2158. IN SIZE_T ChargedBytes,
  2159. IN LOGICAL CheckType,
  2160. IN LOGICAL SpecialPool
  2161. )
  2162. /*++
  2163. Routine Description:
  2164. Called directly from the pool manager or the memory manager for verifier-
  2165. tracked allocations. The call to ExFreePool is already in progress.
  2166. Arguments:
  2167. VirtualAddress - Supplies the virtual address being freed.
  2168. ChargedBytes - Supplies the number of bytes charged to this allocation.
  2169. CheckType - Supplies PagedPool or NonPagedPool.
  2170. SpecialPool - Supplies TRUE if the allocation is from special pool.
  2171. Return Value:
  2172. None.
  2173. Environment:
  2174. Kernel mode.
  2175. N.B.
  2176. Callers freeing small pool allocations hold no locks or mutexes on entry.
  2177. Callers freeing special pool hold no locks or mutexes on entry.
  2178. Callers freeing pool of PAGE_SIZE or larger hold the nonpaged pool spinlock
  2179. or the PagedPool mutex (depending on allocation type) on entry.
  2180. --*/
  2181. {
  2182. if (VerifierIsTrackingPool == FALSE) {
  2183. //
  2184. // The verifier is not enabled so the only way this routine is being
  2185. // called is because the pool header is mangled or the caller specified
  2186. // a bad address. Either way it's a bugcheck.
  2187. //
  2188. KeBugCheckEx (BAD_POOL_CALLER,
  2189. 0x99,
  2190. (ULONG_PTR)VirtualAddress,
  2191. 0,
  2192. 0);
  2193. }
  2194. ViFreeTrackedPool (VirtualAddress, ChargedBytes, CheckType, SpecialPool);
  2195. }
  2196. THUNKED_API
  2197. VOID
  2198. VerifierFreePool(
  2199. IN PVOID P
  2200. )
  2201. {
  2202. if (KernelVerifier == TRUE) {
  2203. ExFreePool (P);
  2204. return;
  2205. }
  2206. VerifierFreePoolWithTag (P, 0);
  2207. }
  2208. THUNKED_API
  2209. VOID
  2210. VerifierFreePoolWithTag(
  2211. IN PVOID P,
  2212. IN ULONG TagToFree
  2213. )
  2214. {
  2215. if (KernelVerifier == TRUE) {
  2216. ExFreePoolWithTag (P, TagToFree);
  2217. return;
  2218. }
  2219. ExFreePoolSanityChecks (P);
  2220. ExFreePoolWithTag (P, TagToFree);
  2221. }
  2222. THUNKED_API
  2223. LONG
  2224. VerifierSetEvent (
  2225. IN PRKEVENT Event,
  2226. IN KPRIORITY Increment,
  2227. IN BOOLEAN Wait
  2228. )
  2229. {
  2230. KIRQL CurrentIrql;
  2231. CurrentIrql = KeGetCurrentIrql();
  2232. if (CurrentIrql > DISPATCH_LEVEL) {
  2233. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2234. 0x80,
  2235. CurrentIrql,
  2236. (ULONG_PTR)Event,
  2237. (ULONG_PTR)0);
  2238. }
  2239. return KeSetEvent (Event, Increment, Wait);
  2240. }
  2241. THUNKED_API
  2242. BOOLEAN
  2243. VerifierExAcquireResourceExclusiveLite(
  2244. IN PERESOURCE Resource,
  2245. IN BOOLEAN Wait
  2246. )
  2247. {
  2248. KIRQL CurrentIrql;
  2249. CurrentIrql = KeGetCurrentIrql ();
  2250. if ((CurrentIrql != APC_LEVEL) &&
  2251. (!IS_SYSTEM_THREAD(PsGetCurrentThread())) &&
  2252. (KeGetCurrentThread()->KernelApcDisable == 0)) {
  2253. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2254. 0x37,
  2255. CurrentIrql,
  2256. (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable),
  2257. (ULONG_PTR)Resource);
  2258. }
  2259. return ExAcquireResourceExclusiveLite (Resource, Wait);
  2260. }
  2261. THUNKED_API
  2262. VOID
  2263. FASTCALL
  2264. VerifierExReleaseResourceLite(
  2265. IN PERESOURCE Resource
  2266. )
  2267. {
  2268. KIRQL CurrentIrql;
  2269. CurrentIrql = KeGetCurrentIrql ();
  2270. if ((CurrentIrql != APC_LEVEL) &&
  2271. (!IS_SYSTEM_THREAD(PsGetCurrentThread())) &&
  2272. (KeGetCurrentThread()->KernelApcDisable == 0)) {
  2273. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2274. 0x38,
  2275. CurrentIrql,
  2276. (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable),
  2277. (ULONG_PTR)Resource);
  2278. }
  2279. ExReleaseResourceLite (Resource);
  2280. }
  2281. int VerifierIrqlData[0x10];
  2282. VOID
  2283. KfSanityCheckRaiseIrql (
  2284. IN KIRQL NewIrql
  2285. )
  2286. {
  2287. KIRQL CurrentIrql;
  2288. //
  2289. // Check for the caller inadvertently lowering.
  2290. //
  2291. CurrentIrql = KeGetCurrentIrql ();
  2292. if (CurrentIrql == NewIrql) {
  2293. VerifierIrqlData[0] += 1;
  2294. if (CurrentIrql == APC_LEVEL) {
  2295. VerifierIrqlData[1] += 1;
  2296. }
  2297. else if (CurrentIrql == DISPATCH_LEVEL) {
  2298. VerifierIrqlData[2] += 1;
  2299. }
  2300. else {
  2301. VerifierIrqlData[3] += 1;
  2302. }
  2303. }
  2304. else {
  2305. VerifierIrqlData[4] += 1;
  2306. }
  2307. if (CurrentIrql > NewIrql) {
  2308. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2309. 0x30,
  2310. CurrentIrql,
  2311. NewIrql,
  2312. 0);
  2313. }
  2314. //
  2315. // Check for the caller using an uninitialized variable.
  2316. //
  2317. if (NewIrql > HIGH_LEVEL) {
  2318. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2319. 0x30,
  2320. CurrentIrql,
  2321. NewIrql,
  2322. 0);
  2323. }
  2324. if (ViTrackIrqlQueue != NULL) {
  2325. ViTrackIrqlLog (CurrentIrql, NewIrql);
  2326. }
  2327. }
  2328. VOID
  2329. KfSanityCheckLowerIrql (
  2330. IN KIRQL NewIrql
  2331. )
  2332. {
  2333. KIRQL CurrentIrql;
  2334. //
  2335. // Check for the caller inadvertently lowering.
  2336. //
  2337. CurrentIrql = KeGetCurrentIrql ();
  2338. if (CurrentIrql == NewIrql) {
  2339. VerifierIrqlData[8] += 1;
  2340. if (CurrentIrql == APC_LEVEL) {
  2341. VerifierIrqlData[9] += 1;
  2342. }
  2343. else if (CurrentIrql == DISPATCH_LEVEL) {
  2344. VerifierIrqlData[10] += 1;
  2345. }
  2346. else {
  2347. VerifierIrqlData[11] += 1;
  2348. }
  2349. }
  2350. else {
  2351. VerifierIrqlData[12] += 1;
  2352. }
  2353. if (CurrentIrql < NewIrql) {
  2354. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2355. 0x31,
  2356. CurrentIrql,
  2357. NewIrql,
  2358. 0);
  2359. }
  2360. //
  2361. // Check for the caller using an uninitialized variable.
  2362. //
  2363. if (NewIrql > HIGH_LEVEL) {
  2364. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2365. 0x31,
  2366. CurrentIrql,
  2367. NewIrql,
  2368. 0);
  2369. }
  2370. if (ViTrackIrqlQueue != NULL) {
  2371. ViTrackIrqlLog (CurrentIrql, NewIrql);
  2372. }
  2373. }
  2374. #define VI_TRIM_KERNEL 0x00000001
  2375. #define VI_TRIM_USER 0x00000002
  2376. #define VI_TRIM_SESSION 0x00000004
  2377. #define VI_TRIM_PURGE 0x80000000
  2378. ULONG ViTrimSpaces = VI_TRIM_KERNEL;
  2379. VOID
  2380. ViTrimAllSystemPagableMemory (
  2381. VOID
  2382. )
  2383. {
  2384. LOGICAL PurgeTransition;
  2385. LARGE_INTEGER CurrentTime;
  2386. LOGICAL PageOut;
  2387. PageOut = TRUE;
  2388. if (KernelVerifier == TRUE) {
  2389. KeQueryTickCount(&CurrentTime);
  2390. if ((CurrentTime.LowPart & KernelVerifierTickPage) != 0) {
  2391. PageOut = FALSE;
  2392. }
  2393. }
  2394. if ((PageOut == TRUE) && (MiNoPageOnRaiseIrql == 0)) {
  2395. MmVerifierData.TrimRequests += 1;
  2396. if (ViTrimSpaces & VI_TRIM_PURGE) {
  2397. PurgeTransition = TRUE;
  2398. }
  2399. else {
  2400. PurgeTransition = FALSE;
  2401. }
  2402. if (ViTrimSpaces & VI_TRIM_KERNEL) {
  2403. if (MmTrimAllSystemPagableMemory (PurgeTransition) == TRUE) {
  2404. MmVerifierData.Trims += 1;
  2405. }
  2406. }
  2407. if (ViTrimSpaces & VI_TRIM_USER) {
  2408. if (MmTrimProcessMemory (PurgeTransition) == TRUE) {
  2409. MmVerifierData.UserTrims += 1;
  2410. }
  2411. }
  2412. if (ViTrimSpaces & VI_TRIM_SESSION) {
  2413. if (MmTrimSessionMemory (PurgeTransition) == TRUE) {
  2414. MmVerifierData.SessionTrims += 1;
  2415. }
  2416. }
  2417. }
  2418. }
  2419. typedef
  2420. VOID
  2421. (*PKE_ACQUIRE_SPINLOCK) (
  2422. IN PKSPIN_LOCK SpinLock,
  2423. OUT PKIRQL OldIrql
  2424. );
  2425. THUNKED_API
  2426. VOID
  2427. VerifierKeAcquireSpinLock (
  2428. IN PKSPIN_LOCK SpinLock,
  2429. OUT PKIRQL OldIrql
  2430. )
  2431. {
  2432. KIRQL CurrentIrql;
  2433. #if defined (_X86_)
  2434. PKE_ACQUIRE_SPINLOCK HalRoutine;
  2435. #endif
  2436. CurrentIrql = KeGetCurrentIrql ();
  2437. KfSanityCheckRaiseIrql (DISPATCH_LEVEL);
  2438. MmVerifierData.AcquireSpinLocks += 1;
  2439. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2440. if (CurrentIrql < DISPATCH_LEVEL) {
  2441. ViTrimAllSystemPagableMemory ();
  2442. }
  2443. }
  2444. #if defined (_X86_)
  2445. HalRoutine = (PKE_ACQUIRE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_ACQUIRE_SPINLOCK];
  2446. if (HalRoutine) {
  2447. (*HalRoutine)(SpinLock, OldIrql);
  2448. VfDeadlockAcquireResource(SpinLock,
  2449. VfDeadlockSpinLock,
  2450. KeGetCurrentThread(),
  2451. FALSE,
  2452. _ReturnAddress());
  2453. return;
  2454. }
  2455. #endif
  2456. KeAcquireSpinLock (SpinLock, OldIrql);
  2457. VfDeadlockAcquireResource(SpinLock,
  2458. VfDeadlockSpinLock,
  2459. KeGetCurrentThread(),
  2460. FALSE,
  2461. _ReturnAddress());
  2462. }
  2463. typedef
  2464. VOID
  2465. (*PKE_RELEASE_SPINLOCK) (
  2466. IN PKSPIN_LOCK SpinLock,
  2467. IN KIRQL NewIrql
  2468. );
  2469. THUNKED_API
  2470. VOID
  2471. VerifierKeReleaseSpinLock (
  2472. IN PKSPIN_LOCK SpinLock,
  2473. IN KIRQL NewIrql
  2474. )
  2475. {
  2476. KIRQL CurrentIrql;
  2477. #if defined (_X86_)
  2478. PKE_RELEASE_SPINLOCK HalRoutine;
  2479. #endif
  2480. CurrentIrql = KeGetCurrentIrql ();
  2481. //
  2482. // Caller better still be at DISPATCH_LEVEL when releasing the spinlock
  2483. //
  2484. if (CurrentIrql < DISPATCH_LEVEL) {
  2485. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2486. 0x32,
  2487. CurrentIrql,
  2488. (ULONG_PTR)SpinLock,
  2489. 0);
  2490. }
  2491. KfSanityCheckLowerIrql (NewIrql);
  2492. #if defined (_X86_)
  2493. HalRoutine = (PKE_RELEASE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_RELEASE_SPINLOCK];
  2494. if (HalRoutine) {
  2495. VfDeadlockReleaseResource(SpinLock,
  2496. VfDeadlockSpinLock,
  2497. KeGetCurrentThread(),
  2498. _ReturnAddress());
  2499. (*HalRoutine)(SpinLock, NewIrql);
  2500. return;
  2501. }
  2502. #endif
  2503. VfDeadlockReleaseResource(SpinLock,
  2504. VfDeadlockSpinLock,
  2505. KeGetCurrentThread(),
  2506. _ReturnAddress());
  2507. KeReleaseSpinLock (SpinLock, NewIrql);
  2508. }
  2509. //
  2510. // Verifier thunks for AcquireSpinLockAtDpcLevel and ReleaseSpinLockFromDpcLevel.
  2511. //
  2512. // On x86 the functions exported by the kernel that are used by the driver are:
  2513. // KefAcquire.../KefRelease.... On other platforms the functions used by drivers
  2514. // are KeAcquire.../KeRelease. Among other differences the x86 versions use the
  2515. // fastcall convention which requires additional precaution.
  2516. //
  2517. THUNKED_API
  2518. VOID
  2519. #if defined(_X86_)
  2520. FASTCALL
  2521. #endif
  2522. VerifierKeAcquireSpinLockAtDpcLevel (
  2523. IN PKSPIN_LOCK SpinLock
  2524. )
  2525. {
  2526. KIRQL CurrentIrql;
  2527. CurrentIrql = KeGetCurrentIrql ();
  2528. //
  2529. // Caller better be at or above DISPATCH_LEVEL.
  2530. //
  2531. if (CurrentIrql < DISPATCH_LEVEL) {
  2532. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2533. 0x40,
  2534. CurrentIrql,
  2535. (ULONG_PTR)SpinLock,
  2536. 0);
  2537. }
  2538. MmVerifierData.AcquireSpinLocks += 1;
  2539. KeAcquireSpinLockAtDpcLevel (SpinLock);
  2540. VfDeadlockAcquireResource(SpinLock,
  2541. VfDeadlockSpinLock,
  2542. KeGetCurrentThread(),
  2543. FALSE,
  2544. _ReturnAddress());
  2545. }
  2546. THUNKED_API
  2547. VOID
  2548. #if defined(_X86_)
  2549. FASTCALL
  2550. #endif
  2551. VerifierKeReleaseSpinLockFromDpcLevel (
  2552. IN PKSPIN_LOCK SpinLock
  2553. )
  2554. {
  2555. KIRQL CurrentIrql;
  2556. CurrentIrql = KeGetCurrentIrql ();
  2557. //
  2558. // Caller better be at DISPATCH_LEVEL.
  2559. //
  2560. if (CurrentIrql < DISPATCH_LEVEL) {
  2561. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2562. 0x41,
  2563. CurrentIrql,
  2564. (ULONG_PTR)SpinLock,
  2565. 0);
  2566. }
  2567. VfDeadlockReleaseResource(SpinLock,
  2568. VfDeadlockSpinLock,
  2569. KeGetCurrentThread(),
  2570. _ReturnAddress());
  2571. KeReleaseSpinLockFromDpcLevel (SpinLock);
  2572. }
  2573. #if !defined(_X86_)
  2574. THUNKED_API
  2575. KIRQL
  2576. VerifierKeAcquireSpinLockRaiseToDpc (
  2577. IN PKSPIN_LOCK SpinLock
  2578. )
  2579. {
  2580. KIRQL NewIrql = KeAcquireSpinLockRaiseToDpc (SpinLock);
  2581. VfDeadlockAcquireResource (SpinLock,
  2582. VfDeadlockSpinLock,
  2583. KeGetCurrentThread(),
  2584. FALSE,
  2585. _ReturnAddress());
  2586. return NewIrql;
  2587. }
  2588. #endif
  2589. #if defined (_X86_)
  2590. typedef
  2591. KIRQL
  2592. (FASTCALL *PKF_ACQUIRE_SPINLOCK) (
  2593. IN PKSPIN_LOCK SpinLock
  2594. );
  2595. THUNKED_API
  2596. KIRQL
  2597. FASTCALL
  2598. VerifierKfAcquireSpinLock (
  2599. IN PKSPIN_LOCK SpinLock
  2600. )
  2601. {
  2602. KIRQL CurrentIrql;
  2603. PKF_ACQUIRE_SPINLOCK HalRoutine;
  2604. CurrentIrql = KeGetCurrentIrql ();
  2605. KfSanityCheckRaiseIrql (DISPATCH_LEVEL);
  2606. MmVerifierData.AcquireSpinLocks += 1;
  2607. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2608. if (CurrentIrql < DISPATCH_LEVEL) {
  2609. ViTrimAllSystemPagableMemory ();
  2610. }
  2611. }
  2612. #if defined (_X86_)
  2613. HalRoutine = (PKF_ACQUIRE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_ACQUIRE_SPINLOCK];
  2614. if (HalRoutine) {
  2615. CurrentIrql = (*HalRoutine)(SpinLock);
  2616. VfDeadlockAcquireResource(SpinLock,
  2617. VfDeadlockSpinLock,
  2618. KeGetCurrentThread(),
  2619. FALSE,
  2620. _ReturnAddress());
  2621. return CurrentIrql;
  2622. }
  2623. #endif
  2624. CurrentIrql = KfAcquireSpinLock (SpinLock);
  2625. VfDeadlockAcquireResource(SpinLock,
  2626. VfDeadlockSpinLock,
  2627. KeGetCurrentThread(),
  2628. FALSE,
  2629. _ReturnAddress());
  2630. return CurrentIrql;
  2631. }
  2632. typedef
  2633. VOID
  2634. (FASTCALL *PKF_RELEASE_SPINLOCK) (
  2635. IN PKSPIN_LOCK SpinLock,
  2636. IN KIRQL NewIrql
  2637. );
  2638. THUNKED_API
  2639. VOID
  2640. FASTCALL
  2641. VerifierKfReleaseSpinLock (
  2642. IN PKSPIN_LOCK SpinLock,
  2643. IN KIRQL NewIrql
  2644. )
  2645. {
  2646. KIRQL CurrentIrql;
  2647. PKF_RELEASE_SPINLOCK HalRoutine;
  2648. CurrentIrql = KeGetCurrentIrql ();
  2649. //
  2650. // Caller better still be at DISPATCH_LEVEL when releasing the spinlock.
  2651. //
  2652. if (CurrentIrql < DISPATCH_LEVEL) {
  2653. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2654. 0x35,
  2655. CurrentIrql,
  2656. (ULONG_PTR)SpinLock,
  2657. NewIrql);
  2658. }
  2659. KfSanityCheckLowerIrql (NewIrql);
  2660. #if defined (_X86_)
  2661. HalRoutine = (PKF_RELEASE_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_RELEASE_SPINLOCK];
  2662. if (HalRoutine) {
  2663. VfDeadlockReleaseResource(SpinLock,
  2664. VfDeadlockSpinLock,
  2665. KeGetCurrentThread(),
  2666. _ReturnAddress());
  2667. (*HalRoutine)(SpinLock, NewIrql);
  2668. return;
  2669. }
  2670. #endif
  2671. VfDeadlockReleaseResource(SpinLock,
  2672. VfDeadlockSpinLock,
  2673. KeGetCurrentThread(),
  2674. _ReturnAddress());
  2675. KfReleaseSpinLock (SpinLock, NewIrql);
  2676. }
  2677. #if !defined(NT_UP)
  2678. typedef
  2679. KIRQL
  2680. (FASTCALL *PKE_ACQUIRE_QUEUED_SPINLOCK) (
  2681. IN KSPIN_LOCK_QUEUE_NUMBER Number
  2682. );
  2683. THUNKED_API
  2684. KIRQL
  2685. FASTCALL
  2686. VerifierKeAcquireQueuedSpinLock (
  2687. IN KSPIN_LOCK_QUEUE_NUMBER Number
  2688. )
  2689. {
  2690. KIRQL CurrentIrql;
  2691. PKE_ACQUIRE_QUEUED_SPINLOCK HalRoutine;
  2692. CurrentIrql = KeGetCurrentIrql ();
  2693. KfSanityCheckRaiseIrql (DISPATCH_LEVEL);
  2694. MmVerifierData.AcquireSpinLocks += 1;
  2695. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2696. if (CurrentIrql < DISPATCH_LEVEL) {
  2697. ViTrimAllSystemPagableMemory ();
  2698. }
  2699. }
  2700. #if defined (_X86_)
  2701. HalRoutine = (PKE_ACQUIRE_QUEUED_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_ACQUIRE_QUEUED_SPINLOCK];
  2702. if (HalRoutine) {
  2703. return (*HalRoutine)(Number);
  2704. }
  2705. #endif
  2706. CurrentIrql = KeAcquireQueuedSpinLock (Number);
  2707. return CurrentIrql;
  2708. }
  2709. typedef
  2710. VOID
  2711. (FASTCALL *PKE_RELEASE_QUEUED_SPINLOCK) (
  2712. IN KSPIN_LOCK_QUEUE_NUMBER Number,
  2713. IN KIRQL OldIrql
  2714. );
  2715. THUNKED_API
  2716. VOID
  2717. FASTCALL
  2718. VerifierKeReleaseQueuedSpinLock (
  2719. IN KSPIN_LOCK_QUEUE_NUMBER Number,
  2720. IN KIRQL OldIrql
  2721. )
  2722. {
  2723. KIRQL CurrentIrql;
  2724. PKE_RELEASE_QUEUED_SPINLOCK HalRoutine;
  2725. CurrentIrql = KeGetCurrentIrql ();
  2726. if (KernelVerifier == TRUE) {
  2727. if (CurrentIrql < DISPATCH_LEVEL) {
  2728. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2729. 0x36,
  2730. CurrentIrql,
  2731. (ULONG_PTR)Number,
  2732. (ULONG_PTR)OldIrql);
  2733. }
  2734. }
  2735. KfSanityCheckLowerIrql (OldIrql);
  2736. #if defined (_X86_)
  2737. HalRoutine = (PKE_RELEASE_QUEUED_SPINLOCK) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_RELEASE_QUEUED_SPINLOCK];
  2738. if (HalRoutine) {
  2739. (*HalRoutine)(Number, OldIrql);
  2740. return;
  2741. }
  2742. #endif
  2743. KeReleaseQueuedSpinLock (Number, OldIrql);
  2744. }
  2745. #endif // NT_UP
  2746. #endif // _X86_
  2747. #if defined(_X86_) || defined(_AMD64_)
  2748. typedef
  2749. KIRQL
  2750. (FASTCALL *PKF_RAISE_IRQL) (
  2751. IN KIRQL NewIrql
  2752. );
  2753. THUNKED_API
  2754. KIRQL
  2755. FASTCALL
  2756. VerifierKfRaiseIrql (
  2757. IN KIRQL NewIrql
  2758. )
  2759. {
  2760. #if defined (_X86_)
  2761. PKF_RAISE_IRQL HalRoutine;
  2762. #endif
  2763. KIRQL CurrentIrql;
  2764. CurrentIrql = KeGetCurrentIrql ();
  2765. KfSanityCheckRaiseIrql (NewIrql);
  2766. MmVerifierData.RaiseIrqls += 1;
  2767. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2768. if ((CurrentIrql < DISPATCH_LEVEL) && (NewIrql >= DISPATCH_LEVEL)) {
  2769. ViTrimAllSystemPagableMemory ();
  2770. }
  2771. }
  2772. #if defined (_X86_)
  2773. HalRoutine = (PKF_RAISE_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_RAISE_IRQL];
  2774. if (HalRoutine) {
  2775. return (*HalRoutine)(NewIrql);
  2776. }
  2777. #endif
  2778. return KfRaiseIrql (NewIrql);
  2779. }
  2780. typedef
  2781. KIRQL
  2782. (FASTCALL *PKE_RAISE_IRQL_TO_DPC_LEVEL) (
  2783. VOID
  2784. );
  2785. THUNKED_API
  2786. KIRQL
  2787. VerifierKeRaiseIrqlToDpcLevel (
  2788. VOID
  2789. )
  2790. {
  2791. #if defined (_X86_)
  2792. PKE_RAISE_IRQL_TO_DPC_LEVEL HalRoutine;
  2793. #endif
  2794. KIRQL CurrentIrql;
  2795. CurrentIrql = KeGetCurrentIrql ();
  2796. KfSanityCheckRaiseIrql (DISPATCH_LEVEL);
  2797. MmVerifierData.RaiseIrqls += 1;
  2798. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2799. if (CurrentIrql < DISPATCH_LEVEL) {
  2800. ViTrimAllSystemPagableMemory ();
  2801. }
  2802. }
  2803. #if defined (_X86_)
  2804. HalRoutine = (PKE_RAISE_IRQL_TO_DPC_LEVEL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_RAISE_IRQL_TO_DPC_LEVEL];
  2805. if (HalRoutine) {
  2806. return (*HalRoutine)();
  2807. }
  2808. #endif
  2809. return KeRaiseIrqlToDpcLevel ();
  2810. }
  2811. #endif // _X86_ || _AMD64_
  2812. #if defined(_X86_)
  2813. typedef
  2814. VOID
  2815. (FASTCALL *PKF_LOWER_IRQL) (
  2816. IN KIRQL NewIrql
  2817. );
  2818. THUNKED_API
  2819. VOID
  2820. FASTCALL
  2821. VerifierKfLowerIrql (
  2822. IN KIRQL NewIrql
  2823. )
  2824. {
  2825. PKF_LOWER_IRQL HalRoutine;
  2826. KfSanityCheckLowerIrql (NewIrql);
  2827. #if defined (_X86_)
  2828. HalRoutine = (PKF_LOWER_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KF_LOWER_IRQL];
  2829. if (HalRoutine) {
  2830. (*HalRoutine)(NewIrql);
  2831. return;
  2832. }
  2833. #endif
  2834. KfLowerIrql (NewIrql);
  2835. }
  2836. #endif
  2837. THUNKED_API
  2838. BOOLEAN
  2839. FASTCALL
  2840. VerifierExTryToAcquireFastMutex (
  2841. IN PFAST_MUTEX FastMutex
  2842. )
  2843. {
  2844. KIRQL CurrentIrql;
  2845. BOOLEAN Acquired;
  2846. CurrentIrql = KeGetCurrentIrql ();
  2847. //
  2848. // Caller better be at or below APC_LEVEL or have APCs blocked.
  2849. //
  2850. if (CurrentIrql > APC_LEVEL) {
  2851. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2852. 0x33,
  2853. CurrentIrql,
  2854. (ULONG_PTR)FastMutex,
  2855. 0);
  2856. }
  2857. Acquired = ExTryToAcquireFastMutex (FastMutex);
  2858. if (Acquired != FALSE) {
  2859. VfDeadlockAcquireResource(FastMutex,
  2860. VfDeadlockFastMutex,
  2861. KeGetCurrentThread(),
  2862. TRUE,
  2863. _ReturnAddress());
  2864. }
  2865. return Acquired;
  2866. }
  2867. THUNKED_API
  2868. VOID
  2869. FASTCALL
  2870. VerifierExAcquireFastMutex (
  2871. IN PFAST_MUTEX FastMutex
  2872. )
  2873. {
  2874. KIRQL CurrentIrql;
  2875. CurrentIrql = KeGetCurrentIrql ();
  2876. //
  2877. // Caller better be at or below APC_LEVEL or have APCs blocked.
  2878. //
  2879. if (CurrentIrql > APC_LEVEL) {
  2880. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2881. 0x33,
  2882. CurrentIrql,
  2883. (ULONG_PTR)FastMutex,
  2884. 0);
  2885. }
  2886. ExAcquireFastMutex (FastMutex);
  2887. VfDeadlockAcquireResource(FastMutex,
  2888. VfDeadlockFastMutex,
  2889. KeGetCurrentThread(),
  2890. FALSE,
  2891. _ReturnAddress());
  2892. }
  2893. THUNKED_API
  2894. VOID
  2895. FASTCALL
  2896. VerifierExAcquireFastMutexUnsafe (
  2897. IN PFAST_MUTEX FastMutex
  2898. )
  2899. {
  2900. KIRQL CurrentIrql;
  2901. CurrentIrql = KeGetCurrentIrql ();
  2902. //
  2903. // Caller better be at APC_LEVEL or have APCs blocked.
  2904. //
  2905. if ((CurrentIrql != APC_LEVEL) &&
  2906. (!IS_SYSTEM_THREAD(PsGetCurrentThread())) &&
  2907. (KeGetCurrentThread()->KernelApcDisable == 0)) {
  2908. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2909. 0x39,
  2910. CurrentIrql,
  2911. (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable),
  2912. (ULONG_PTR)FastMutex);
  2913. }
  2914. ExAcquireFastMutexUnsafe (FastMutex);
  2915. VfDeadlockAcquireResource(FastMutex,
  2916. VfDeadlockFastMutexUnsafe,
  2917. KeGetCurrentThread(),
  2918. FALSE,
  2919. _ReturnAddress());
  2920. }
  2921. THUNKED_API
  2922. VOID
  2923. FASTCALL
  2924. VerifierExReleaseFastMutex (
  2925. IN PFAST_MUTEX FastMutex
  2926. )
  2927. {
  2928. KIRQL CurrentIrql;
  2929. CurrentIrql = KeGetCurrentIrql ();
  2930. //
  2931. // Caller better be at APC_LEVEL or have APCs blocked.
  2932. //
  2933. if ((CurrentIrql != APC_LEVEL) &&
  2934. (!IS_SYSTEM_THREAD(PsGetCurrentThread())) &&
  2935. (KeGetCurrentThread()->KernelApcDisable == 0)) {
  2936. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2937. 0x34,
  2938. CurrentIrql,
  2939. (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable),
  2940. (ULONG_PTR)FastMutex);
  2941. }
  2942. VfDeadlockReleaseResource(FastMutex,
  2943. VfDeadlockFastMutex,
  2944. KeGetCurrentThread(),
  2945. _ReturnAddress());
  2946. ExReleaseFastMutex (FastMutex);
  2947. }
  2948. THUNKED_API
  2949. VOID
  2950. FASTCALL
  2951. VerifierExReleaseFastMutexUnsafe (
  2952. IN PFAST_MUTEX FastMutex
  2953. )
  2954. {
  2955. KIRQL CurrentIrql;
  2956. CurrentIrql = KeGetCurrentIrql ();
  2957. //
  2958. // Caller better be at APC_LEVEL or have APCs blocked.
  2959. //
  2960. if ((CurrentIrql != APC_LEVEL) &&
  2961. (!IS_SYSTEM_THREAD(PsGetCurrentThread())) &&
  2962. (KeGetCurrentThread()->KernelApcDisable == 0)) {
  2963. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  2964. 0x3A,
  2965. CurrentIrql,
  2966. (ULONG_PTR)(KeGetCurrentThread()->KernelApcDisable),
  2967. (ULONG_PTR)FastMutex);
  2968. }
  2969. VfDeadlockReleaseResource(FastMutex,
  2970. VfDeadlockFastMutexUnsafe,
  2971. KeGetCurrentThread(),
  2972. _ReturnAddress());
  2973. ExReleaseFastMutexUnsafe (FastMutex);
  2974. }
  2975. typedef
  2976. VOID
  2977. (*PKE_RAISE_IRQL) (
  2978. IN KIRQL NewIrql,
  2979. OUT PKIRQL OldIrql
  2980. );
  2981. THUNKED_API
  2982. VOID
  2983. VerifierKeRaiseIrql (
  2984. IN KIRQL NewIrql,
  2985. OUT PKIRQL OldIrql
  2986. )
  2987. {
  2988. #if defined (_X86_)
  2989. PKE_RAISE_IRQL HalRoutine;
  2990. #endif
  2991. *OldIrql = KeGetCurrentIrql ();
  2992. KfSanityCheckRaiseIrql (NewIrql);
  2993. MmVerifierData.RaiseIrqls += 1;
  2994. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  2995. if ((*OldIrql < DISPATCH_LEVEL) && (NewIrql >= DISPATCH_LEVEL)) {
  2996. ViTrimAllSystemPagableMemory ();
  2997. }
  2998. }
  2999. #if defined (_X86_)
  3000. HalRoutine = (PKE_RAISE_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_RAISE_IRQL];
  3001. if (HalRoutine) {
  3002. (*HalRoutine)(NewIrql, OldIrql);
  3003. return;
  3004. }
  3005. #endif
  3006. KeRaiseIrql (NewIrql, OldIrql);
  3007. }
  3008. typedef
  3009. VOID
  3010. (*PKE_LOWER_IRQL) (
  3011. IN KIRQL NewIrql
  3012. );
  3013. THUNKED_API
  3014. VOID
  3015. VerifierKeLowerIrql (
  3016. IN KIRQL NewIrql
  3017. )
  3018. {
  3019. #if defined (_X86_)
  3020. PKE_LOWER_IRQL HalRoutine;
  3021. #endif
  3022. KfSanityCheckLowerIrql (NewIrql);
  3023. #if defined (_X86_)
  3024. HalRoutine = (PKE_LOWER_IRQL) (ULONG_PTR) MiKernelVerifierOriginalCalls[VI_KE_LOWER_IRQL];
  3025. if (HalRoutine) {
  3026. (*HalRoutine)(NewIrql);
  3027. return;
  3028. }
  3029. #endif
  3030. KeLowerIrql (NewIrql);
  3031. }
  3032. THUNKED_API
  3033. BOOLEAN
  3034. VerifierSynchronizeExecution (
  3035. IN PKINTERRUPT Interrupt,
  3036. IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  3037. IN PVOID SynchronizeContext
  3038. )
  3039. {
  3040. KIRQL OldIrql;
  3041. OldIrql = KeGetCurrentIrql ();
  3042. KfSanityCheckRaiseIrql (Interrupt->SynchronizeIrql);
  3043. MmVerifierData.SynchronizeExecutions += 1;
  3044. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  3045. if ((OldIrql < DISPATCH_LEVEL) && (Interrupt->SynchronizeIrql >= DISPATCH_LEVEL)) {
  3046. ViTrimAllSystemPagableMemory ();
  3047. }
  3048. }
  3049. return KeSynchronizeExecution (Interrupt,
  3050. SynchronizeRoutine,
  3051. SynchronizeContext);
  3052. }
  3053. THUNKED_API
  3054. VOID
  3055. VerifierKeInitializeTimerEx(
  3056. IN PKTIMER Timer,
  3057. IN TIMER_TYPE Type
  3058. )
  3059. {
  3060. //
  3061. // Check the object being initialized isn't already an
  3062. // active timer. Make sure the timer table list is initialized.
  3063. //
  3064. if (KiTimerTableListHead[0].Flink != NULL) {
  3065. KeCheckForTimer(Timer, sizeof(KTIMER));
  3066. }
  3067. KeInitializeTimerEx(Timer, Type);
  3068. }
  3069. THUNKED_API
  3070. VOID
  3071. VerifierKeInitializeTimer(
  3072. IN PKTIMER Timer
  3073. )
  3074. {
  3075. VerifierKeInitializeTimerEx(Timer, NotificationTimer);
  3076. }
  3077. THUNKED_API
  3078. NTSTATUS
  3079. VerifierKeWaitForSingleObject (
  3080. IN PVOID Object,
  3081. IN KWAIT_REASON WaitReason,
  3082. IN KPROCESSOR_MODE WaitMode,
  3083. IN BOOLEAN Alertable,
  3084. IN PLARGE_INTEGER Timeout OPTIONAL
  3085. )
  3086. {
  3087. KIRQL CurrentIrql;
  3088. PRKTHREAD Thread;
  3089. NTSTATUS Status;
  3090. BOOLEAN TryAcquire;
  3091. if (! ((ARGUMENT_PRESENT(Timeout)) && (Timeout->QuadPart == 0))) {
  3092. CurrentIrql = KeGetCurrentIrql ();
  3093. if (CurrentIrql >= DISPATCH_LEVEL) {
  3094. Thread = KeGetCurrentThread();
  3095. //
  3096. // Skip situations where KeWait is called at DPC level
  3097. // to optimize dispatcher database lock handling.
  3098. //
  3099. if (Thread->WaitNext == FALSE) {
  3100. //
  3101. // Cannot call KeWait at DPC level.
  3102. //
  3103. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  3104. 0x3B,
  3105. (ULONG_PTR)CurrentIrql,
  3106. (ULONG_PTR)Object,
  3107. (ULONG_PTR)Timeout);
  3108. }
  3109. }
  3110. }
  3111. Status = KeWaitForSingleObject (Object,
  3112. WaitReason,
  3113. WaitMode,
  3114. Alertable,
  3115. Timeout);
  3116. if ((STATUS_SUCCESS == Status) &&
  3117. (((PRKMUTANT) Object)->Header.Type == MutantObject)) {
  3118. if (ARGUMENT_PRESENT(Timeout)) {
  3119. TryAcquire = TRUE;
  3120. }
  3121. else {
  3122. TryAcquire = FALSE;
  3123. }
  3124. VfDeadlockAcquireResource (Object,
  3125. VfDeadlockMutex,
  3126. KeGetCurrentThread (),
  3127. TryAcquire,
  3128. _ReturnAddress ());
  3129. }
  3130. return Status;
  3131. }
  3132. THUNKED_API
  3133. LONG
  3134. VerifierKeReleaseMutex(
  3135. IN PRKMUTEX Mutex,
  3136. IN BOOLEAN Wait
  3137. )
  3138. {
  3139. VfDeadlockReleaseResource(Mutex,
  3140. VfDeadlockMutex,
  3141. KeGetCurrentThread(),
  3142. _ReturnAddress());
  3143. return KeReleaseMutex(Mutex, Wait);
  3144. }
  3145. THUNKED_API
  3146. VOID
  3147. VerifierKeInitializeMutex(
  3148. IN PRKMUTEX Mutex,
  3149. IN ULONG Level
  3150. )
  3151. {
  3152. KeInitializeMutex (Mutex,Level);
  3153. VfDeadlockInitializeResource (Mutex, VfDeadlockMutex, _ReturnAddress(), FALSE);
  3154. }
  3155. THUNKED_API
  3156. LONG
  3157. VerifierKeReleaseMutant(
  3158. IN PRKMUTANT Mutant,
  3159. IN KPRIORITY Increment,
  3160. IN BOOLEAN Abandoned,
  3161. IN BOOLEAN Wait
  3162. )
  3163. {
  3164. VfDeadlockReleaseResource(Mutant,
  3165. VfDeadlockMutex,
  3166. KeGetCurrentThread(),
  3167. _ReturnAddress());
  3168. return KeReleaseMutant(Mutant, Increment, Abandoned, Wait);
  3169. }
  3170. THUNKED_API
  3171. VOID
  3172. VerifierKeInitializeMutant(
  3173. IN PRKMUTANT Mutant,
  3174. IN BOOLEAN InitialOwner
  3175. )
  3176. {
  3177. KeInitializeMutant (Mutant, InitialOwner);
  3178. VfDeadlockInitializeResource (Mutant, VfDeadlockMutex, _ReturnAddress(), FALSE);
  3179. if (InitialOwner) {
  3180. VfDeadlockAcquireResource (Mutant,
  3181. VfDeadlockMutex,
  3182. KeGetCurrentThread(),
  3183. FALSE,
  3184. _ReturnAddress());
  3185. }
  3186. }
  3187. THUNKED_API
  3188. VOID
  3189. VerifierKeInitializeSpinLock(
  3190. IN PKSPIN_LOCK SpinLock
  3191. )
  3192. {
  3193. KeInitializeSpinLock (SpinLock);
  3194. VfDeadlockInitializeResource (SpinLock, VfDeadlockSpinLock, _ReturnAddress(), FALSE);
  3195. }
  3196. NTSTATUS
  3197. VerifierReferenceObjectByHandle (
  3198. IN HANDLE Handle,
  3199. IN ACCESS_MASK DesiredAccess,
  3200. IN POBJECT_TYPE ObjectType OPTIONAL,
  3201. IN KPROCESSOR_MODE AccessMode,
  3202. OUT PVOID *Object,
  3203. OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
  3204. )
  3205. {
  3206. NTSTATUS Status;
  3207. Status = ObReferenceObjectByHandle (Handle,
  3208. DesiredAccess,
  3209. ObjectType,
  3210. AccessMode,
  3211. Object,
  3212. HandleInformation);
  3213. if (AccessMode == KernelMode || PsIsSystemThread (PsGetCurrentThread ())) {
  3214. if (Status == STATUS_INVALID_HANDLE || Status == STATUS_OBJECT_TYPE_MISMATCH) {
  3215. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  3216. 0x3C,
  3217. (ULONG_PTR)Handle,
  3218. (ULONG_PTR)ObjectType,
  3219. (ULONG_PTR)0);
  3220. }
  3221. }
  3222. return Status;
  3223. }
  3224. VOID
  3225. ViInitializeEntry (
  3226. IN PMI_VERIFIER_DRIVER_ENTRY Verifier,
  3227. IN LOGICAL FirstLoad
  3228. )
  3229. /*++
  3230. Routine Description:
  3231. Initialize various verifier fields as the driver is being (re)loaded now.
  3232. Arguments:
  3233. Verifier - Supplies the verifier entry to be initialized.
  3234. FirstLoad - Supplies TRUE if this is the first load of this driver.
  3235. Return Value:
  3236. None.
  3237. --*/
  3238. {
  3239. KIRQL OldIrql;
  3240. //
  3241. // Only the BaseName field is initialized on entry.
  3242. //
  3243. KeInitializeSpinLock (&Verifier->VerifierPoolLock);
  3244. Verifier->CurrentPagedPoolAllocations = 0;
  3245. Verifier->CurrentNonPagedPoolAllocations = 0;
  3246. Verifier->PeakPagedPoolAllocations = 0;
  3247. Verifier->PeakNonPagedPoolAllocations = 0;
  3248. Verifier->PagedBytes = 0;
  3249. Verifier->NonPagedBytes = 0;
  3250. Verifier->PeakPagedBytes = 0;
  3251. Verifier->PeakNonPagedBytes = 0;
  3252. Verifier->PoolHash = NULL;
  3253. Verifier->PoolHashSize = 0;
  3254. Verifier->PoolHashFree = VI_POOL_FREELIST_END;
  3255. Verifier->PoolHashReserved = 0;
  3256. Verifier->Signature = MI_VERIFIER_ENTRY_SIGNATURE;
  3257. if (FirstLoad == TRUE) {
  3258. Verifier->Flags = 0;
  3259. Verifier->Loads = 0;
  3260. Verifier->Unloads = 0;
  3261. }
  3262. ExAcquireSpinLock (&VerifierListLock, &OldIrql);
  3263. Verifier->StartAddress = NULL;
  3264. Verifier->EndAddress = NULL;
  3265. ExReleaseSpinLock (&VerifierListLock, OldIrql);
  3266. }
  3267. #define UNICODE_TAB 0x0009
  3268. #define UNICODE_LF 0x000A
  3269. #define UNICODE_CR 0x000D
  3270. #define UNICODE_SPACE 0x0020
  3271. #define UNICODE_CJK_SPACE 0x3000
  3272. #define UNICODE_WHITESPACE(_ch) (((_ch) == UNICODE_TAB) || \
  3273. ((_ch) == UNICODE_LF) || \
  3274. ((_ch) == UNICODE_CR) || \
  3275. ((_ch) == UNICODE_SPACE) || \
  3276. ((_ch) == UNICODE_CJK_SPACE) || \
  3277. ((_ch) == UNICODE_NULL))
  3278. LOGICAL
  3279. MiInitializeDriverVerifierList (
  3280. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  3281. )
  3282. /*++
  3283. Routine Description:
  3284. Parse the registry settings and set up the list of driver names that will
  3285. be put through the validation process.
  3286. It is important that this list be parsed early because the machine-specific
  3287. memory management initialization needs to know whether the verifier is
  3288. going to be enabled.
  3289. Arguments:
  3290. LoaderBlock - Supplies the loader block used by the system to boot.
  3291. Return Value:
  3292. TRUE if successful, FALSE if not.
  3293. Environment:
  3294. Kernel mode, Phase 0 Initialization.
  3295. Nonpaged (but not paged) pool exists.
  3296. The PsLoadedModuleList has not been set up yet AND the boot drivers
  3297. have NOT been relocated to their final resting places.
  3298. --*/
  3299. {
  3300. PWCHAR Start;
  3301. PWCHAR End;
  3302. PWCHAR Walk;
  3303. ULONG NameLength;
  3304. LARGE_INTEGER CurrentTime;
  3305. UNICODE_STRING KernelString;
  3306. UNICODE_STRING DriverBaseName;
  3307. UNREFERENCED_PARAMETER (LoaderBlock);
  3308. InitializeListHead (&MiSuspectDriverList);
  3309. if (MmVerifyDriverLevel != (ULONG)-1) {
  3310. if (MmVerifyDriverLevel & DRIVER_VERIFIER_IO_CHECKING) {
  3311. if (MmVerifyDriverBufferLength == (ULONG)-1) {
  3312. MmVerifyDriverBufferLength = 0; // Mm will not page out verifier pages.
  3313. }
  3314. }
  3315. }
  3316. if (MmVerifyDriverBufferLength == (ULONG)-1) {
  3317. if (MmDontVerifyRandomDrivers == TRUE) {
  3318. return FALSE;
  3319. }
  3320. MmVerifyDriverBufferLength = 0;
  3321. CurrentTime = KeQueryPerformanceCounter (NULL);
  3322. CurrentTime.LowPart = (CurrentTime.LowPart % 26);
  3323. MiVerifyRandomDrivers = (WCHAR)('A' + (WCHAR)CurrentTime.LowPart);
  3324. if ((MiVerifyRandomDrivers == (WCHAR)'H') ||
  3325. (MiVerifyRandomDrivers == (WCHAR)'J') ||
  3326. (MiVerifyRandomDrivers == (WCHAR)'X') ||
  3327. (MiVerifyRandomDrivers == (WCHAR)'Y') ||
  3328. (MiVerifyRandomDrivers == (WCHAR)'Z')) {
  3329. MiVerifyRandomDrivers = (WCHAR)'X';
  3330. }
  3331. }
  3332. KeInitializeSpinLock (&VerifierListLock);
  3333. KeInitializeSpinLock (&VerifierPoolLock);
  3334. ExInitializeFastMutex (&VerifierPoolMutex);
  3335. //
  3336. // Initializing this listhead indicates to the rest of this module that
  3337. // the system was booted with verification of some sort configured.
  3338. //
  3339. InitializeListHead (&MiVerifierDriverAddedThunkListHead);
  3340. //
  3341. // If no default is specified, then special pool, pagable code/data
  3342. // flushing and pool leak detection are enabled.
  3343. //
  3344. if (MmVerifyDriverLevel == (ULONG)-1) {
  3345. MmVerifierData.Level = DRIVER_VERIFIER_SPECIAL_POOLING |
  3346. DRIVER_VERIFIER_FORCE_IRQL_CHECKING |
  3347. DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS;
  3348. }
  3349. else {
  3350. MmVerifierData.Level = MmVerifyDriverLevel;
  3351. }
  3352. VerifierModifyableOptions = (DRIVER_VERIFIER_SPECIAL_POOLING |
  3353. DRIVER_VERIFIER_FORCE_IRQL_CHECKING |
  3354. DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES);
  3355. //
  3356. // An initial parse of the driver list is needed here to see if it's the
  3357. // kernel as special machine-dependent initialization is needed to fully
  3358. // support kernel verification (ie: no use of large pages, etc).
  3359. //
  3360. if (MiVerifyRandomDrivers == (WCHAR)0) {
  3361. RtlInitUnicodeString (&KernelString, (PUSHORT)L"ntoskrnl.exe");
  3362. Start = MmVerifyDriverBuffer;
  3363. End = MmVerifyDriverBuffer + (MmVerifyDriverBufferLength - sizeof(WCHAR)) / sizeof(WCHAR);
  3364. while (Start < End) {
  3365. if (UNICODE_WHITESPACE(*Start)) {
  3366. Start += 1;
  3367. continue;
  3368. }
  3369. if (*Start == (WCHAR)'*') {
  3370. MiVerifyAllDrivers = TRUE;
  3371. break;
  3372. }
  3373. for (Walk = Start; Walk < End; Walk += 1) {
  3374. if (UNICODE_WHITESPACE(*Walk)) {
  3375. break;
  3376. }
  3377. }
  3378. //
  3379. // Got a string - see if it indicates the kernel.
  3380. //
  3381. NameLength = (ULONG)(Walk - Start + 1) * sizeof (WCHAR);
  3382. DriverBaseName.Buffer = Start;
  3383. DriverBaseName.Length = (USHORT)(NameLength - sizeof (UNICODE_NULL));
  3384. DriverBaseName.MaximumLength = (USHORT)NameLength;
  3385. if (RtlEqualUnicodeString (&KernelString,
  3386. &DriverBaseName,
  3387. TRUE)) {
  3388. //
  3389. // AcquireAtDpc/ReleaseFromDpc calls made by the kernel are not
  3390. // intercepted which confuses the deadlock verifier. So disable
  3391. // deadlock verification if we are kernel verifying.
  3392. //
  3393. MmVerifyDriverLevel &= ~DRIVER_VERIFIER_DEADLOCK_DETECTION;
  3394. MmVerifierData.Level &= ~DRIVER_VERIFIER_DEADLOCK_DETECTION;
  3395. //
  3396. //
  3397. // All driver pool allocation calls must be intercepted so
  3398. // they are not mistaken for kernel pool allocations.
  3399. //
  3400. MiVerifyAllDrivers = TRUE;
  3401. KernelVerifier = TRUE;
  3402. ExSetPoolFlags (EX_KERNEL_VERIFIER_ENABLED);
  3403. break;
  3404. }
  3405. Start = Walk + 1;
  3406. }
  3407. }
  3408. return TRUE;
  3409. }
  3410. VOID
  3411. MiReApplyVerifierToLoadedModules(
  3412. IN PLIST_ENTRY ModuleListHead
  3413. )
  3414. /*++
  3415. Routine Description:
  3416. Walk the supplied module list and re-thunk any drivers that are being
  3417. verified. This allows the module to pick up any new thunks that have
  3418. been added.
  3419. Arguments:
  3420. ModuleListHead - Supplies a pointer to the head of a loaded module list.
  3421. Environment:
  3422. Kernel mode, Phase 0 Initialization only.
  3423. --*/
  3424. {
  3425. LOGICAL Skip;
  3426. PLIST_ENTRY Entry;
  3427. PKLDR_DATA_TABLE_ENTRY TableEntry;
  3428. UNICODE_STRING HalString;
  3429. UNICODE_STRING KernelString;
  3430. //
  3431. // If the thunk listhead is NULL then the verifier is not enabled so
  3432. // don't notify any components.
  3433. //
  3434. if (MiVerifierDriverAddedThunkListHead.Flink == NULL) {
  3435. return;
  3436. }
  3437. //
  3438. // Initialize unicode strings to use to bypass modules
  3439. // in the list. There's no reason to reapply verifier to
  3440. // the kernel or to the hal.
  3441. //
  3442. RtlInitUnicodeString (&KernelString, (PUSHORT)L"ntoskrnl.exe");
  3443. RtlInitUnicodeString (&HalString, (PUSHORT)L"hal.dll");
  3444. //
  3445. // Walk the list and reapply verifier to all the modules except those
  3446. // selected for exclusion.
  3447. //
  3448. Entry = ModuleListHead->Flink;
  3449. while (Entry != ModuleListHead) {
  3450. TableEntry = CONTAINING_RECORD(Entry,
  3451. KLDR_DATA_TABLE_ENTRY,
  3452. InLoadOrderLinks);
  3453. Skip = TRUE;
  3454. if (RtlEqualUnicodeString (&KernelString,
  3455. &TableEntry->BaseDllName,
  3456. TRUE)) {
  3457. NOTHING;
  3458. }
  3459. else if (RtlEqualUnicodeString (&HalString,
  3460. &TableEntry->BaseDllName,
  3461. TRUE)) {
  3462. NOTHING;
  3463. }
  3464. else {
  3465. Skip = FALSE;
  3466. }
  3467. //
  3468. // Reapply verifier thunks to the image if it is already being
  3469. // verified and if it is not one of the modules we've decided to skip.
  3470. //
  3471. if ((Skip == FALSE) && (TableEntry->Flags & LDRP_IMAGE_VERIFYING)) {
  3472. #if DBG
  3473. PLIST_ENTRY NextEntry;
  3474. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  3475. //
  3476. // Initializing Verifier is not needed for correctness, but
  3477. // without it the compiler cannot compile this code W4 to check
  3478. // for use of uninitialized variables.
  3479. //
  3480. Verifier = NULL;
  3481. //
  3482. // Find the entry for this driver in the suspect list. This is
  3483. // expected to succeed since we are re-applying thunks to a module
  3484. // that has already been verified at least once before.
  3485. //
  3486. NextEntry = MiSuspectDriverList.Flink;
  3487. while (NextEntry != &MiSuspectDriverList) {
  3488. Verifier = CONTAINING_RECORD(NextEntry,
  3489. MI_VERIFIER_DRIVER_ENTRY,
  3490. Links);
  3491. if (RtlEqualUnicodeString (&Verifier->BaseName,
  3492. &TableEntry->BaseDllName,
  3493. TRUE)) {
  3494. break;
  3495. }
  3496. NextEntry = NextEntry->Flink;
  3497. }
  3498. ASSERT (NextEntry != &MiSuspectDriverList);
  3499. //
  3500. // Sanity tests. We should always find this module in the suspect
  3501. // driver list because it is already being verified. And the
  3502. // start and end addresses should still match those of the this
  3503. // module.
  3504. //
  3505. ASSERT(NextEntry != &MiSuspectDriverList);
  3506. ASSERT(Verifier->StartAddress == TableEntry->DllBase);
  3507. ASSERT(Verifier->EndAddress ==
  3508. (PVOID)((ULONG_PTR)TableEntry->DllBase +
  3509. TableEntry->SizeOfImage));
  3510. #endif
  3511. MiReEnableVerifier (TableEntry);
  3512. }
  3513. Entry = Entry->Flink;
  3514. }
  3515. }
  3516. LOGICAL
  3517. MiInitializeVerifyingComponents (
  3518. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  3519. )
  3520. /*++
  3521. Routine Description:
  3522. Walk the loaded module list and thunk any drivers that need/deserve it.
  3523. Arguments:
  3524. LoaderBlock - Supplies the loader block used by the system to boot.
  3525. Return Value:
  3526. TRUE if successful, FALSE if not.
  3527. Environment:
  3528. Kernel mode, Phase 0 Initialization.
  3529. Both nonpaged and paged pool exist.
  3530. The PsLoadedModuleList has not been set up yet although the boot drivers
  3531. have been relocated to their final resting places.
  3532. --*/
  3533. {
  3534. ULONG i;
  3535. PWCHAR Start;
  3536. PWCHAR End;
  3537. PWCHAR Walk;
  3538. ULONG NameLength;
  3539. PLIST_ENTRY NextEntry;
  3540. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  3541. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  3542. PMI_VERIFIER_DRIVER_ENTRY KernelEntry;
  3543. PMI_VERIFIER_DRIVER_ENTRY HalEntry;
  3544. UNICODE_STRING HalString;
  3545. UNICODE_STRING KernelString;
  3546. PVERIFIER_THUNKS Thunk;
  3547. PDRIVER_VERIFIER_THUNK_ROUTINE PristineRoutine;
  3548. //
  3549. // If the thunk listhead is NULL then the verifier is not enabled so
  3550. // don't notify any components.
  3551. //
  3552. if (MiVerifierDriverAddedThunkListHead.Flink == NULL) {
  3553. return FALSE;
  3554. }
  3555. KernelEntry = NULL;
  3556. HalEntry = NULL;
  3557. if (MiVerifyRandomDrivers == (WCHAR)0) {
  3558. RtlInitUnicodeString (&KernelString, (PUSHORT)L"ntoskrnl.exe");
  3559. RtlInitUnicodeString (&HalString, (PUSHORT)L"hal.dll");
  3560. Start = MmVerifyDriverBuffer;
  3561. End = MmVerifyDriverBuffer + (MmVerifyDriverBufferLength - sizeof(WCHAR)) / sizeof(WCHAR);
  3562. while (Start < End) {
  3563. if (UNICODE_WHITESPACE(*Start)) {
  3564. Start += 1;
  3565. continue;
  3566. }
  3567. if (*Start == (WCHAR)'*') {
  3568. MiVerifyAllDrivers = TRUE;
  3569. break;
  3570. }
  3571. for (Walk = Start; Walk < End; Walk += 1) {
  3572. if (UNICODE_WHITESPACE(*Walk)) {
  3573. break;
  3574. }
  3575. }
  3576. //
  3577. // Got a string. Save it.
  3578. //
  3579. NameLength = (ULONG)(Walk - Start + 1) * sizeof (WCHAR);
  3580. Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag (
  3581. NonPagedPool,
  3582. sizeof (MI_VERIFIER_DRIVER_ENTRY) +
  3583. NameLength,
  3584. 'dLmM');
  3585. if (Verifier == NULL) {
  3586. break;
  3587. }
  3588. Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier +
  3589. sizeof (MI_VERIFIER_DRIVER_ENTRY));
  3590. Verifier->BaseName.Length = (USHORT)(NameLength - sizeof (UNICODE_NULL));
  3591. Verifier->BaseName.MaximumLength = (USHORT)NameLength;
  3592. RtlCopyMemory (Verifier->BaseName.Buffer,
  3593. Start,
  3594. NameLength - sizeof (UNICODE_NULL));
  3595. ViInitializeEntry (Verifier, TRUE);
  3596. Verifier->Flags |= VI_VERIFYING_DIRECTLY;
  3597. ViInsertVerifierEntry (Verifier);
  3598. if (RtlEqualUnicodeString (&KernelString,
  3599. &Verifier->BaseName,
  3600. TRUE)) {
  3601. //
  3602. // All driver pool allocation calls must be intercepted so
  3603. // they are not mistaken for kernel pool allocations.
  3604. //
  3605. ASSERT (MiVerifyAllDrivers == TRUE);
  3606. ASSERT (KernelVerifier == TRUE);
  3607. KernelEntry = Verifier;
  3608. }
  3609. else if (RtlEqualUnicodeString (&HalString,
  3610. &Verifier->BaseName,
  3611. TRUE)) {
  3612. HalEntry = Verifier;
  3613. }
  3614. Start = Walk + 1;
  3615. }
  3616. }
  3617. //
  3618. // Enable deadlock detection if the deadlock bit was set in the
  3619. // registry.
  3620. //
  3621. if (MmVerifierData.Level & DRIVER_VERIFIER_DEADLOCK_DETECTION) {
  3622. VfDeadlockDetectionInitialize (MiVerifyAllDrivers, KernelVerifier);
  3623. ExSetPoolFlags (EX_VERIFIER_DEADLOCK_DETECTION_ENABLED);
  3624. }
  3625. //
  3626. // Initialize i/o verifier.
  3627. //
  3628. IoVerifierInit (MmVerifierData.Level);
  3629. if (MiTriageAddDrivers (LoaderBlock) == TRUE) {
  3630. //
  3631. // Disable random driver verification if triage has picked driver(s).
  3632. //
  3633. MiVerifyRandomDrivers = (WCHAR)0;
  3634. }
  3635. Thunk = (PVERIFIER_THUNKS) &MiVerifierThunks[0];
  3636. while (Thunk->PristineRoutineAsciiName != NULL) {
  3637. PristineRoutine = MiResolveVerifierExports (LoaderBlock,
  3638. Thunk->PristineRoutineAsciiName);
  3639. ASSERT (PristineRoutine != NULL);
  3640. Thunk->PristineRoutine = PristineRoutine;
  3641. Thunk += 1;
  3642. }
  3643. Thunk = (PVERIFIER_THUNKS) &MiVerifierPoolThunks[0];
  3644. while (Thunk->PristineRoutineAsciiName != NULL) {
  3645. PristineRoutine = MiResolveVerifierExports (LoaderBlock,
  3646. Thunk->PristineRoutineAsciiName);
  3647. ASSERT (PristineRoutine != NULL);
  3648. Thunk->PristineRoutine = PristineRoutine;
  3649. Thunk += 1;
  3650. }
  3651. //
  3652. // Process the boot-loaded drivers now.
  3653. //
  3654. i = 0;
  3655. NextEntry = LoaderBlock->LoadOrderListHead.Flink;
  3656. for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) {
  3657. DataTableEntry = CONTAINING_RECORD(NextEntry,
  3658. KLDR_DATA_TABLE_ENTRY,
  3659. InLoadOrderLinks);
  3660. //
  3661. // Process the kernel and HAL specially.
  3662. //
  3663. if (i == 0) {
  3664. if (KernelEntry != NULL) {
  3665. MiApplyDriverVerifier (DataTableEntry, KernelEntry);
  3666. }
  3667. }
  3668. else if (i == 1) {
  3669. if (HalEntry != NULL) {
  3670. MiApplyDriverVerifier (DataTableEntry, HalEntry);
  3671. }
  3672. }
  3673. else {
  3674. MiApplyDriverVerifier (DataTableEntry, NULL);
  3675. }
  3676. i += 1;
  3677. }
  3678. //
  3679. // Initialize irql tracking package. The drivers that will be verified
  3680. // will have automatically tracked all their raise/lower irql operations.
  3681. //
  3682. ViTrackIrqlInitialize ();
  3683. //
  3684. // Initialize fault injection stack trace log package.
  3685. //
  3686. #if defined(_X86_)
  3687. ViFaultTracesInitialize ();
  3688. #endif
  3689. return TRUE;
  3690. }
  3691. NTSTATUS
  3692. MmAddVerifierEntry (
  3693. IN PUNICODE_STRING ImageFileName
  3694. )
  3695. /*++
  3696. Routine Description:
  3697. This routine inserts a new verifier entry for the specified driver so that
  3698. when the driver is loaded it will automatically be verified.
  3699. Note that if the driver is already loaded, then no entry is added and
  3700. STATUS_IMAGE_ALREADY_LOADED is returned.
  3701. If the system was booted with an empty verifier list, then no entries can
  3702. be added now as the current system configuration will not support special
  3703. pool, etc.
  3704. Note also that no registry changes are made so any insertions made by this
  3705. routine are lost on reboot.
  3706. Arguments:
  3707. ImageFileName - Supplies the name of the desired driver.
  3708. Return Value:
  3709. Various NTSTATUS codes.
  3710. Environment:
  3711. Kernel mode, PASSIVE_LEVEL, arbitrary process context.
  3712. --*/
  3713. {
  3714. PKTHREAD CurrentThread;
  3715. PLIST_ENTRY NextEntry;
  3716. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  3717. PMI_VERIFIER_DRIVER_ENTRY VerifierEntry;
  3718. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  3719. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  3720. //
  3721. // If the system was not booted with verification on, then bail.
  3722. //
  3723. if (MiVerifierDriverAddedThunkListHead.Flink == NULL) {
  3724. return STATUS_NOT_SUPPORTED;
  3725. }
  3726. //
  3727. // First build up a verifier entry.
  3728. //
  3729. Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag (
  3730. NonPagedPool,
  3731. sizeof (MI_VERIFIER_DRIVER_ENTRY) +
  3732. ImageFileName->MaximumLength,
  3733. 'dLmM');
  3734. if (Verifier == NULL) {
  3735. return STATUS_INSUFFICIENT_RESOURCES;
  3736. }
  3737. Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier +
  3738. sizeof (MI_VERIFIER_DRIVER_ENTRY));
  3739. Verifier->BaseName.Length = ImageFileName->Length;
  3740. Verifier->BaseName.MaximumLength = ImageFileName->MaximumLength;
  3741. RtlCopyMemory (Verifier->BaseName.Buffer,
  3742. ImageFileName->Buffer,
  3743. ImageFileName->Length);
  3744. ViInitializeEntry (Verifier, TRUE);
  3745. Verifier->Flags |= VI_VERIFYING_DIRECTLY;
  3746. //
  3747. // Arbitrary process context so prevent suspend APCs now.
  3748. //
  3749. CurrentThread = KeGetCurrentThread ();
  3750. KeEnterCriticalRegionThread (CurrentThread);
  3751. //
  3752. // Acquire the load lock so the verifier list can be read.
  3753. // Then ensure that the specified driver is not already in the list.
  3754. //
  3755. KeWaitForSingleObject (&MmSystemLoadLock,
  3756. WrVirtualMemory,
  3757. KernelMode,
  3758. FALSE,
  3759. (PLARGE_INTEGER)NULL);
  3760. //
  3761. // Check to make sure the requested entry is not already present in
  3762. // the verifier list and that the driver is not currently loaded.
  3763. //
  3764. NextEntry = MiSuspectDriverList.Flink;
  3765. while (NextEntry != &MiSuspectDriverList) {
  3766. VerifierEntry = CONTAINING_RECORD(NextEntry,
  3767. MI_VERIFIER_DRIVER_ENTRY,
  3768. Links);
  3769. if (RtlEqualUnicodeString (&Verifier->BaseName,
  3770. &VerifierEntry->BaseName,
  3771. TRUE)) {
  3772. //
  3773. // The driver is already in the verifier list - just mark the
  3774. // entry as verification-enabled and free the temporary allocation.
  3775. //
  3776. if ((VerifierEntry->Loads > VerifierEntry->Unloads) &&
  3777. (VerifierEntry->Flags & VI_DISABLE_VERIFICATION)) {
  3778. //
  3779. // The driver is loaded and verification is disabled. Don't
  3780. // turn it on now because we don't want to mislead our caller.
  3781. //
  3782. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3783. KeLeaveCriticalRegionThread (CurrentThread);
  3784. ExFreePool (Verifier);
  3785. return STATUS_IMAGE_ALREADY_LOADED;
  3786. }
  3787. VerifierEntry->Flags &= ~VI_DISABLE_VERIFICATION;
  3788. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3789. KeLeaveCriticalRegionThread (CurrentThread);
  3790. ExFreePool (Verifier);
  3791. return STATUS_SUCCESS;
  3792. }
  3793. NextEntry = NextEntry->Flink;
  3794. }
  3795. //
  3796. // A new verifier entry will need to be added so check to
  3797. // make sure the specified driver is not already loaded.
  3798. //
  3799. ExAcquireResourceSharedLite (&PsLoadedModuleResource, TRUE);
  3800. NextEntry = PsLoadedModuleList.Flink;
  3801. while (NextEntry != &PsLoadedModuleList) {
  3802. DataTableEntry = CONTAINING_RECORD(NextEntry,
  3803. KLDR_DATA_TABLE_ENTRY,
  3804. InLoadOrderLinks);
  3805. if (RtlEqualUnicodeString (&Verifier->BaseName,
  3806. &DataTableEntry->BaseDllName,
  3807. TRUE)) {
  3808. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3809. ExReleaseResourceLite (&PsLoadedModuleResource);
  3810. KeLeaveCriticalRegionThread (CurrentThread);
  3811. ExFreePool (Verifier);
  3812. return STATUS_IMAGE_ALREADY_LOADED;
  3813. }
  3814. NextEntry = NextEntry->Flink;
  3815. }
  3816. //
  3817. // The entry is not already in the verifier list and the driver is not
  3818. // currently loaded. Proceed to insert it now.
  3819. //
  3820. ViInsertVerifierEntry (Verifier);
  3821. ExReleaseResourceLite (&PsLoadedModuleResource);
  3822. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3823. KeLeaveCriticalRegionThread (CurrentThread);
  3824. return STATUS_SUCCESS;
  3825. }
  3826. NTSTATUS
  3827. MmRemoveVerifierEntry (
  3828. IN PUNICODE_STRING ImageFileName
  3829. )
  3830. /*++
  3831. Routine Description:
  3832. This routine doesn't actually remove the verifier entry for the
  3833. specified driver as we don't want to lose any valuable information
  3834. already gathered on the driver if it was previously loaded.
  3835. Instead, this routine disables verification for this driver for future
  3836. loads.
  3837. Note that if the driver is already loaded, then the removal is not
  3838. performed and STATUS_IMAGE_ALREADY_LOADED is returned.
  3839. Note also that no registry changes are made so any removals made by this
  3840. routine are lost on reboot.
  3841. Arguments:
  3842. ImageFileName - Supplies the name of the desired driver.
  3843. Return Value:
  3844. Various NTSTATUS codes.
  3845. Environment:
  3846. Kernel mode, PASSIVE_LEVEL, arbitrary process context.
  3847. --*/
  3848. {
  3849. PKTHREAD CurrentThread;
  3850. PLIST_ENTRY NextEntry;
  3851. PMI_VERIFIER_DRIVER_ENTRY VerifierEntry;
  3852. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  3853. //
  3854. // If the system was not booted with verification on, then bail.
  3855. //
  3856. if (MiVerifierDriverAddedThunkListHead.Flink == NULL) {
  3857. return STATUS_NOT_SUPPORTED;
  3858. }
  3859. //
  3860. // Arbitrary process context so prevent suspend APCs now.
  3861. //
  3862. CurrentThread = KeGetCurrentThread ();
  3863. KeEnterCriticalRegionThread (CurrentThread);
  3864. //
  3865. // Acquire the load lock so the verifier list can be read.
  3866. // Then ensure that the specified driver is not already in the list.
  3867. //
  3868. KeWaitForSingleObject (&MmSystemLoadLock,
  3869. WrVirtualMemory,
  3870. KernelMode,
  3871. FALSE,
  3872. (PLARGE_INTEGER)NULL);
  3873. //
  3874. // Check to make sure the requested entry is not already present in
  3875. // the verifier list and that the driver is not currently loaded.
  3876. //
  3877. NextEntry = MiSuspectDriverList.Flink;
  3878. while (NextEntry != &MiSuspectDriverList) {
  3879. VerifierEntry = CONTAINING_RECORD(NextEntry,
  3880. MI_VERIFIER_DRIVER_ENTRY,
  3881. Links);
  3882. if (RtlEqualUnicodeString (ImageFileName,
  3883. &VerifierEntry->BaseName,
  3884. TRUE)) {
  3885. //
  3886. // The driver is already in the verifier list - just mark the
  3887. // entry as verification-enabled and free the temporary allocation.
  3888. // No need to check the loaded module list if the entry is already
  3889. // in the verifier list.
  3890. //
  3891. if ((VerifierEntry->Loads > VerifierEntry->Unloads) &&
  3892. ((VerifierEntry->Flags & VI_DISABLE_VERIFICATION) == 0)) {
  3893. //
  3894. // The driver is loaded and verification is enabled. Don't
  3895. // disable it now because we don't want to mislead our caller.
  3896. //
  3897. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3898. KeLeaveCriticalRegionThread (CurrentThread);
  3899. return STATUS_IMAGE_ALREADY_LOADED;
  3900. }
  3901. VerifierEntry->Flags |= VI_DISABLE_VERIFICATION;
  3902. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3903. KeLeaveCriticalRegionThread (CurrentThread);
  3904. return STATUS_SUCCESS;
  3905. }
  3906. NextEntry = NextEntry->Flink;
  3907. }
  3908. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  3909. KeLeaveCriticalRegionThread (CurrentThread);
  3910. return STATUS_NOT_FOUND;
  3911. }
  3912. VOID
  3913. ViInsertVerifierEntry (
  3914. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  3915. )
  3916. /*++
  3917. Routine Description:
  3918. Nonpagable wrapper to insert a new verifier entry.
  3919. Note that the system load mutant or the verifier load spinlock is sufficient
  3920. for readers to access the list. This is because the insertion path
  3921. acquires both.
  3922. Lock synchronization is needed because pool allocators walk the
  3923. verifier list at DISPATCH_LEVEL.
  3924. Arguments:
  3925. Verifier - Supplies a caller-initialized entry for the driver.
  3926. Return Value:
  3927. None.
  3928. --*/
  3929. {
  3930. KIRQL OldIrql;
  3931. ExAcquireSpinLock (&VerifierListLock, &OldIrql);
  3932. InsertTailList (&MiSuspectDriverList, &Verifier->Links);
  3933. ExReleaseSpinLock (&VerifierListLock, OldIrql);
  3934. }
  3935. PMI_VERIFIER_DRIVER_ENTRY
  3936. ViLocateVerifierEntry (
  3937. IN PVOID SystemAddress
  3938. )
  3939. /*++
  3940. Routine Description:
  3941. Locate the Driver Verifier entry for the specified system address.
  3942. Arguments:
  3943. SystemAddress - Supplies a code or data address within a driver.
  3944. Return Value:
  3945. The Verifier entry corresponding to the driver or NULL.
  3946. Environment:
  3947. The caller may be at DISPATCH_LEVEL and does not hold the MmSystemLoadLock.
  3948. --*/
  3949. {
  3950. KIRQL OldIrql;
  3951. PLIST_ENTRY NextEntry;
  3952. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  3953. ExAcquireSpinLock (&VerifierListLock, &OldIrql);
  3954. NextEntry = MiSuspectDriverList.Flink;
  3955. while (NextEntry != &MiSuspectDriverList) {
  3956. Verifier = CONTAINING_RECORD(NextEntry,
  3957. MI_VERIFIER_DRIVER_ENTRY,
  3958. Links);
  3959. if ((SystemAddress >= Verifier->StartAddress) &&
  3960. (SystemAddress < Verifier->EndAddress)) {
  3961. ExReleaseSpinLock (&VerifierListLock, OldIrql);
  3962. return Verifier;
  3963. }
  3964. NextEntry = NextEntry->Flink;
  3965. }
  3966. ExReleaseSpinLock (&VerifierListLock, OldIrql);
  3967. return NULL;
  3968. }
  3969. LOGICAL
  3970. MiApplyDriverVerifier (
  3971. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry,
  3972. IN PMI_VERIFIER_DRIVER_ENTRY Verifier
  3973. )
  3974. /*++
  3975. Routine Description:
  3976. This function is called as each module is loaded. If the module being
  3977. loaded is in the suspect list, thunk it here.
  3978. Arguments:
  3979. DataTableEntry - Supplies the data table entry for the module.
  3980. Verifier - Non-NULL if verification must be applied. FALSE indicates
  3981. that the driver name must match for verification to be
  3982. applied.
  3983. Return Value:
  3984. TRUE if thunking was applied, FALSE if not.
  3985. Environment:
  3986. Kernel mode, Phase 0 Initialization and normal runtime.
  3987. Non paged pool exists in Phase0, but paged pool does not.
  3988. Post-Phase0 serialization is provided by the MmSystemLoadLock.
  3989. --*/
  3990. {
  3991. WCHAR FirstChar;
  3992. LOGICAL Found;
  3993. PLIST_ENTRY NextEntry;
  3994. ULONG VerifierFlags;
  3995. if (Verifier != NULL) {
  3996. Found = TRUE;
  3997. }
  3998. else {
  3999. Found = FALSE;
  4000. NextEntry = MiSuspectDriverList.Flink;
  4001. while (NextEntry != &MiSuspectDriverList) {
  4002. Verifier = CONTAINING_RECORD(NextEntry,
  4003. MI_VERIFIER_DRIVER_ENTRY,
  4004. Links);
  4005. if (RtlEqualUnicodeString (&Verifier->BaseName,
  4006. &DataTableEntry->BaseDllName,
  4007. TRUE)) {
  4008. Found = TRUE;
  4009. ViInitializeEntry (Verifier, FALSE);
  4010. break;
  4011. }
  4012. NextEntry = NextEntry->Flink;
  4013. }
  4014. }
  4015. if (Found == FALSE) {
  4016. VerifierFlags = VI_VERIFYING_DIRECTLY;
  4017. if (MiVerifyAllDrivers == TRUE) {
  4018. if (KernelVerifier == TRUE) {
  4019. VerifierFlags = VI_VERIFYING_INVERSELY;
  4020. }
  4021. Found = TRUE;
  4022. }
  4023. else if (MiVerifyRandomDrivers != (WCHAR)0) {
  4024. //
  4025. // Wildcard match drivers randomly.
  4026. //
  4027. FirstChar = RtlUpcaseUnicodeChar(DataTableEntry->BaseDllName.Buffer[0]);
  4028. if (MiVerifyRandomDrivers == FirstChar) {
  4029. Found = TRUE;
  4030. }
  4031. else if (MiVerifyRandomDrivers == (WCHAR)'X') {
  4032. if ((FirstChar >= (WCHAR)'0') && (FirstChar <= (WCHAR)'9')) {
  4033. Found = TRUE;
  4034. }
  4035. }
  4036. }
  4037. if (Found == FALSE) {
  4038. return FALSE;
  4039. }
  4040. Verifier = (PMI_VERIFIER_DRIVER_ENTRY)ExAllocatePoolWithTag (
  4041. NonPagedPool,
  4042. sizeof (MI_VERIFIER_DRIVER_ENTRY) +
  4043. DataTableEntry->BaseDllName.MaximumLength,
  4044. 'dLmM');
  4045. if (Verifier == NULL) {
  4046. return FALSE;
  4047. }
  4048. Verifier->BaseName.Buffer = (PWSTR)((PCHAR)Verifier +
  4049. sizeof (MI_VERIFIER_DRIVER_ENTRY));
  4050. Verifier->BaseName.Length = DataTableEntry->BaseDllName.Length;
  4051. Verifier->BaseName.MaximumLength = DataTableEntry->BaseDllName.MaximumLength;
  4052. RtlCopyMemory (Verifier->BaseName.Buffer,
  4053. DataTableEntry->BaseDllName.Buffer,
  4054. DataTableEntry->BaseDllName.Length);
  4055. ViInitializeEntry (Verifier, TRUE);
  4056. Verifier->Flags = VerifierFlags;
  4057. ViInsertVerifierEntry (Verifier);
  4058. }
  4059. Verifier->StartAddress = DataTableEntry->DllBase;
  4060. Verifier->EndAddress = (PVOID)((ULONG_PTR)DataTableEntry->DllBase + DataTableEntry->SizeOfImage);
  4061. ASSERT (Found == TRUE);
  4062. if (Verifier->Flags & VI_DISABLE_VERIFICATION) {
  4063. //
  4064. // We've been instructed to not verify this driver. If kernel
  4065. // verification is enabled, then the driver must still be thunked
  4066. // for "inverse-verification". If kernel verification is disabled,
  4067. // nothing needs to be done here except load/unload counting.
  4068. //
  4069. if (KernelVerifier == TRUE) {
  4070. Found = MiEnableVerifier (DataTableEntry);
  4071. }
  4072. else {
  4073. Found = FALSE;
  4074. }
  4075. }
  4076. else {
  4077. Found = MiEnableVerifier (DataTableEntry);
  4078. }
  4079. if (Found == TRUE) {
  4080. if (Verifier->Flags & VI_VERIFYING_DIRECTLY &&
  4081. ((DataTableEntry->Flags & LDRP_IMAGE_VERIFYING) == 0)) {
  4082. ViPrintString (&DataTableEntry->BaseDllName);
  4083. }
  4084. MmVerifierData.Loads += 1;
  4085. Verifier->Loads += 1;
  4086. DataTableEntry->Flags |= LDRP_IMAGE_VERIFYING;
  4087. MiActiveVerifies += 1;
  4088. if (MiActiveVerifies == 1) {
  4089. #ifndef NO_POOL_CHECKS
  4090. //
  4091. // If a loaded driver(s) is undergoing validation, the default
  4092. // special pool randomizer is disabled as the precious virtual
  4093. // address space and physical memory is being put to specific
  4094. // use.
  4095. //
  4096. MiEnableRandomSpecialPool (FALSE);
  4097. #endif
  4098. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  4099. //
  4100. // Page out all thread stacks as soon as possible to
  4101. // catch drivers using local events that do usermode waits.
  4102. //
  4103. if (KernelVerifier == FALSE) {
  4104. MiVerifierStackProtectTime = KiStackProtectTime;
  4105. KiStackProtectTime = 0;
  4106. }
  4107. }
  4108. }
  4109. }
  4110. return Found;
  4111. }
  4112. PUNICODE_STRING ViBadDriver;
  4113. VOID
  4114. MiVerifyingDriverUnloading (
  4115. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  4116. )
  4117. /*++
  4118. Routine Description:
  4119. This function is called as a driver that was being verified is now being
  4120. unloaded.
  4121. Arguments:
  4122. DataTableEntry - Supplies the data table entry for the driver.
  4123. Return Value:
  4124. TRUE if thunking was applied, FALSE if not.
  4125. Environment:
  4126. Kernel mode, Phase 0 Initialization and normal runtime.
  4127. Non paged pool exists in Phase0, but paged pool does not.
  4128. Post-Phase0 serialization is provided by the MmSystemLoadLock.
  4129. --*/
  4130. {
  4131. KIRQL OldIrql;
  4132. PLIST_ENTRY NextEntry;
  4133. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  4134. PVI_POOL_ENTRY OldHashTable;
  4135. //
  4136. // Initializing Verifier is not needed for correctness, but without it
  4137. // the compiler cannot compile this code W4 to check for use of
  4138. // uninitialized variables.
  4139. //
  4140. Verifier = NULL;
  4141. NextEntry = MiSuspectDriverList.Flink;
  4142. while (NextEntry != &MiSuspectDriverList) {
  4143. Verifier = CONTAINING_RECORD(NextEntry,
  4144. MI_VERIFIER_DRIVER_ENTRY,
  4145. Links);
  4146. if (RtlEqualUnicodeString (&Verifier->BaseName,
  4147. &DataTableEntry->BaseDllName,
  4148. TRUE)) {
  4149. break;
  4150. }
  4151. NextEntry = NextEntry->Flink;
  4152. }
  4153. ASSERT (NextEntry != &MiSuspectDriverList);
  4154. //
  4155. // Delete any static locks in the driver image.
  4156. //
  4157. // silviuc: might be able to get rid of this call if we get a
  4158. // hook in MmSystemImageUnload.
  4159. //
  4160. VfDeadlockDeleteMemoryRange(DataTableEntry->DllBase,
  4161. (SIZE_T) DataTableEntry->SizeOfImage);
  4162. if (MmVerifierData.Level & DRIVER_VERIFIER_TRACK_POOL_ALLOCATIONS) {
  4163. //
  4164. // Better not be any pool left that wasn't freed.
  4165. //
  4166. if (Verifier->PagedBytes) {
  4167. #if DBG
  4168. DbgPrint ("Driver %wZ leaked %d paged pool allocations (0x%x bytes)\n",
  4169. &DataTableEntry->FullDllName,
  4170. Verifier->CurrentPagedPoolAllocations,
  4171. Verifier->PagedBytes);
  4172. #endif
  4173. //
  4174. // It would be nice to fault in the driver's paged pool allocations
  4175. // now to make debugging easier, but this cannot be easily done
  4176. // in a deadlock free manner.
  4177. //
  4178. // At least disable the paging of pool on IRQL raising in attempt
  4179. // to keep some of these allocations resident for debugging.
  4180. // No need to undo the increment as we're about to bugcheck anyway.
  4181. //
  4182. InterlockedIncrement ((PLONG)&MiNoPageOnRaiseIrql);
  4183. }
  4184. #if DBG
  4185. if (Verifier->NonPagedBytes) {
  4186. DbgPrint ("Driver %wZ leaked %d nonpaged pool allocations (0x%x bytes)\n",
  4187. &DataTableEntry->FullDllName,
  4188. Verifier->CurrentNonPagedPoolAllocations,
  4189. Verifier->NonPagedBytes);
  4190. }
  4191. #endif
  4192. if (Verifier->PagedBytes || Verifier->NonPagedBytes) {
  4193. #if 0
  4194. DbgBreakPoint ();
  4195. InterlockedDecrement (&MiNoPageOnRaiseIrql);
  4196. #else
  4197. //
  4198. // Snap this so the build/BVT lab can easily triage the culprit.
  4199. //
  4200. ViBadDriver = &Verifier->BaseName;
  4201. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  4202. 0x60,
  4203. Verifier->PagedBytes,
  4204. Verifier->NonPagedBytes,
  4205. Verifier->CurrentPagedPoolAllocations +
  4206. Verifier->CurrentNonPagedPoolAllocations);
  4207. #endif
  4208. }
  4209. ExAcquireSpinLock (&Verifier->VerifierPoolLock, &OldIrql);
  4210. if (Verifier->PoolHashReserved != 0) {
  4211. KeBugCheckEx (DRIVER_VERIFIER_DETECTED_VIOLATION,
  4212. 0x61,
  4213. Verifier->PagedBytes,
  4214. Verifier->NonPagedBytes,
  4215. Verifier->CurrentPagedPoolAllocations +
  4216. Verifier->CurrentNonPagedPoolAllocations);
  4217. }
  4218. OldHashTable = Verifier->PoolHash;
  4219. if (OldHashTable != NULL) {
  4220. Verifier->PoolHashSize = 0;
  4221. Verifier->PoolHashFree = VI_POOL_FREELIST_END;
  4222. Verifier->PoolHash = NULL;
  4223. }
  4224. else {
  4225. ASSERT (Verifier->PoolHashSize == 0);
  4226. ASSERT (Verifier->PoolHashFree == VI_POOL_FREELIST_END);
  4227. }
  4228. ExReleaseSpinLock (&Verifier->VerifierPoolLock, OldIrql);
  4229. if (OldHashTable != NULL) {
  4230. ExFreePool (OldHashTable);
  4231. }
  4232. //
  4233. // Clear these fields so reuse of stale addresses don't trigger
  4234. // erroneous bucket fills.
  4235. //
  4236. ExAcquireSpinLock (&VerifierListLock, &OldIrql);
  4237. Verifier->StartAddress = NULL;
  4238. Verifier->EndAddress = NULL;
  4239. ExReleaseSpinLock (&VerifierListLock, OldIrql);
  4240. }
  4241. Verifier->Unloads += 1;
  4242. MmVerifierData.Unloads += 1;
  4243. MiActiveVerifies -= 1;
  4244. if (MiActiveVerifies == 0) {
  4245. if (MmVerifierData.Level & DRIVER_VERIFIER_FORCE_IRQL_CHECKING) {
  4246. //
  4247. // Return to normal thread stack protection.
  4248. //
  4249. if (KernelVerifier == FALSE) {
  4250. KiStackProtectTime = MiVerifierStackProtectTime;
  4251. }
  4252. }
  4253. #ifndef NO_POOL_CHECKS
  4254. MiEnableRandomSpecialPool (TRUE);
  4255. #endif
  4256. }
  4257. }
  4258. NTKERNELAPI
  4259. LOGICAL
  4260. MmIsDriverVerifying (
  4261. IN PDRIVER_OBJECT DriverObject
  4262. )
  4263. /*++
  4264. Routine Description:
  4265. This function informs the caller if the argument driver is being verified.
  4266. Arguments:
  4267. DriverObject - Supplies the driver object.
  4268. Return Value:
  4269. TRUE if this driver is being verified, FALSE if not.
  4270. Environment:
  4271. Kernel mode, any IRQL, any needed synchronization must be provided by the
  4272. caller.
  4273. --*/
  4274. {
  4275. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  4276. DataTableEntry = (PKLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
  4277. if (DataTableEntry == NULL) {
  4278. return FALSE;
  4279. }
  4280. if ((DataTableEntry->Flags & LDRP_IMAGE_VERIFYING) == 0) {
  4281. return FALSE;
  4282. }
  4283. return TRUE;
  4284. }
  4285. NTSTATUS
  4286. MmAddVerifierThunks (
  4287. IN PVOID ThunkBuffer,
  4288. IN ULONG ThunkBufferSize
  4289. )
  4290. /*++
  4291. Routine Description:
  4292. This routine adds another set of thunks to the verifier list.
  4293. Arguments:
  4294. ThunkBuffer - Supplies the buffer containing the thunk pairs.
  4295. ThunkBufferSize - Supplies the number of bytes in the thunk buffer.
  4296. Return Value:
  4297. Returns the status of the operation.
  4298. Environment:
  4299. Kernel mode. APC_LEVEL and below, arbitrary process context.
  4300. --*/
  4301. {
  4302. ULONG i;
  4303. PKTHREAD CurrentThread;
  4304. ULONG NumberOfThunkPairs;
  4305. PDRIVER_VERIFIER_THUNK_PAIRS ThunkPairs;
  4306. PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable;
  4307. PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase;
  4308. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  4309. PKLDR_DATA_TABLE_ENTRY DataTableEntry2;
  4310. PLIST_ENTRY NextEntry;
  4311. PVOID DriverStartAddress;
  4312. PVOID DriverEndAddress;
  4313. PAGED_CODE();
  4314. if (MiVerifierDriverAddedThunkListHead.Flink == NULL) {
  4315. return STATUS_NOT_SUPPORTED;
  4316. }
  4317. ThunkPairs = (PDRIVER_VERIFIER_THUNK_PAIRS)ThunkBuffer;
  4318. NumberOfThunkPairs = ThunkBufferSize / sizeof(DRIVER_VERIFIER_THUNK_PAIRS);
  4319. if (NumberOfThunkPairs == 0) {
  4320. return STATUS_INVALID_PARAMETER_1;
  4321. }
  4322. ThunkTableBase = (PDRIVER_SPECIFIED_VERIFIER_THUNKS) ExAllocatePoolWithTag (
  4323. PagedPool,
  4324. sizeof (DRIVER_SPECIFIED_VERIFIER_THUNKS) + NumberOfThunkPairs * sizeof (DRIVER_VERIFIER_THUNK_PAIRS),
  4325. 'tVmM');
  4326. if (ThunkTableBase == NULL) {
  4327. return STATUS_INSUFFICIENT_RESOURCES;
  4328. }
  4329. ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(ThunkTableBase + 1);
  4330. RtlCopyMemory (ThunkTable,
  4331. ThunkPairs,
  4332. NumberOfThunkPairs * sizeof(DRIVER_VERIFIER_THUNK_PAIRS));
  4333. CurrentThread = KeGetCurrentThread ();
  4334. KeEnterCriticalRegionThread (CurrentThread);
  4335. KeWaitForSingleObject (&MmSystemLoadLock,
  4336. WrVirtualMemory,
  4337. KernelMode,
  4338. FALSE,
  4339. (PLARGE_INTEGER)NULL);
  4340. //
  4341. // Find and validate the image that contains the routines to be thunked.
  4342. //
  4343. DataTableEntry = MiLookupDataTableEntry ((PVOID)(ULONG_PTR)ThunkTable->PristineRoutine,
  4344. TRUE);
  4345. if (DataTableEntry == NULL) {
  4346. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  4347. KeLeaveCriticalRegionThread (CurrentThread);
  4348. ExFreePool (ThunkTableBase);
  4349. return STATUS_INVALID_PARAMETER_2;
  4350. }
  4351. DriverStartAddress = (PVOID)(DataTableEntry->DllBase);
  4352. DriverEndAddress = (PVOID)((PCHAR)DataTableEntry->DllBase + DataTableEntry->SizeOfImage);
  4353. //
  4354. // Don't let drivers hook calls to kernel or HAL routines.
  4355. //
  4356. i = 0;
  4357. NextEntry = PsLoadedModuleList.Flink;
  4358. while (NextEntry != &PsLoadedModuleList) {
  4359. DataTableEntry2 = CONTAINING_RECORD(NextEntry,
  4360. KLDR_DATA_TABLE_ENTRY,
  4361. InLoadOrderLinks);
  4362. if (DataTableEntry == DataTableEntry2) {
  4363. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  4364. KeLeaveCriticalRegionThread (CurrentThread);
  4365. ExFreePool (ThunkTableBase);
  4366. return STATUS_INVALID_PARAMETER_2;
  4367. }
  4368. NextEntry = NextEntry->Flink;
  4369. i += 1;
  4370. if (i >= 2) {
  4371. break;
  4372. }
  4373. }
  4374. for (i = 0; i < NumberOfThunkPairs; i += 1) {
  4375. //
  4376. // Ensure all the routines being thunked are in the same driver.
  4377. //
  4378. if (((ULONG_PTR)ThunkTable->PristineRoutine < (ULONG_PTR)DriverStartAddress) ||
  4379. ((ULONG_PTR)ThunkTable->PristineRoutine >= (ULONG_PTR)DriverEndAddress) ||
  4380. ((ULONG_PTR)ThunkTable->NewRoutine < (ULONG_PTR)DriverStartAddress) ||
  4381. ((ULONG_PTR)ThunkTable->NewRoutine >= (ULONG_PTR)DriverEndAddress)
  4382. ) {
  4383. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  4384. KeLeaveCriticalRegionThread (CurrentThread);
  4385. ExFreePool (ThunkTableBase);
  4386. return STATUS_INVALID_PARAMETER_2;
  4387. }
  4388. ThunkTable += 1;
  4389. }
  4390. //
  4391. // Add the validated thunk table to the verifier's global list.
  4392. //
  4393. ThunkTableBase->DataTableEntry = DataTableEntry;
  4394. ThunkTableBase->NumberOfThunks = NumberOfThunkPairs;
  4395. MiActiveVerifierThunks += 1;
  4396. InsertTailList (&MiVerifierDriverAddedThunkListHead,
  4397. &ThunkTableBase->ListEntry);
  4398. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  4399. KeLeaveCriticalRegionThread (CurrentThread);
  4400. //
  4401. // Indicate that new thunks have been added to the verifier list.
  4402. //
  4403. MiVerifierThunksAdded += 1;
  4404. return STATUS_SUCCESS;
  4405. }
  4406. VOID
  4407. MiVerifierCheckThunks (
  4408. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  4409. )
  4410. /*++
  4411. Routine Description:
  4412. This routine adds another set of thunks to the verifier list.
  4413. Arguments:
  4414. DataTableEntry - Supplies the data table entry for the driver.
  4415. Return Value:
  4416. None.
  4417. Environment:
  4418. Kernel mode. APC_LEVEL and below.
  4419. The system load lock must be held by the caller.
  4420. --*/
  4421. {
  4422. PLIST_ENTRY NextEntry;
  4423. PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase;
  4424. PAGED_CODE ();
  4425. //
  4426. // N.B. The DataTableEntry can move (see MiInitializeLoadedModuleList),
  4427. // but this only happens long before IoInitialize so this is safe.
  4428. //
  4429. NextEntry = MiVerifierDriverAddedThunkListHead.Flink;
  4430. while (NextEntry != &MiVerifierDriverAddedThunkListHead) {
  4431. ThunkTableBase = CONTAINING_RECORD(NextEntry,
  4432. DRIVER_SPECIFIED_VERIFIER_THUNKS,
  4433. ListEntry);
  4434. if (ThunkTableBase->DataTableEntry == DataTableEntry) {
  4435. RemoveEntryList (NextEntry);
  4436. NextEntry = NextEntry->Flink;
  4437. ExFreePool (ThunkTableBase);
  4438. MiActiveVerifierThunks -= 1;
  4439. //
  4440. // Keep looking as the driver may have made multiple calls.
  4441. //
  4442. continue;
  4443. }
  4444. NextEntry = NextEntry->Flink;
  4445. }
  4446. }
  4447. NTSTATUS
  4448. MmIsVerifierEnabled (
  4449. OUT PULONG VerifierFlags
  4450. )
  4451. /*++
  4452. Routine Description:
  4453. This routine is called by drivers to query whether the Driver Verifier
  4454. is enabled and to find out what the currently enabled options are.
  4455. Arguments:
  4456. VerifierFlags - Returns the current driver verifier flags. Note these
  4457. flags can change dynamically without rebooting.
  4458. Return Value:
  4459. Returns STATUS_SUCCESS if the verifier is enabled, or a failure code if not.
  4460. Environment:
  4461. Kernel mode, PASSIVE_LEVEL.
  4462. --*/
  4463. {
  4464. if (MiVerifierDriverAddedThunkListHead.Flink == NULL) {
  4465. *VerifierFlags = 0;
  4466. return STATUS_NOT_SUPPORTED;
  4467. }
  4468. *VerifierFlags = MmVerifierData.Level;
  4469. return STATUS_SUCCESS;
  4470. }
  4471. #define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \
  4472. ((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))
  4473. NTSTATUS
  4474. MmGetVerifierInformation (
  4475. OUT PVOID SystemInformation,
  4476. IN ULONG SystemInformationLength,
  4477. OUT PULONG Length
  4478. )
  4479. /*++
  4480. Routine Description:
  4481. This routine returns information about drivers undergoing verification.
  4482. Arguments:
  4483. SystemInformation - Returns the driver verification information.
  4484. SystemInformationLength - Supplies the length of the SystemInformation
  4485. buffer.
  4486. Length - Returns the length of the driver verification file information
  4487. placed in the buffer.
  4488. Return Value:
  4489. Returns the status of the operation.
  4490. Environment:
  4491. The SystemInformation buffer is in user space and our caller has wrapped
  4492. a try-except around this entire routine. Capture any exceptions here and
  4493. release resources accordingly.
  4494. --*/
  4495. {
  4496. PKTHREAD CurrentThread;
  4497. PSYSTEM_VERIFIER_INFORMATION UserVerifyBuffer;
  4498. ULONG NextEntryOffset;
  4499. ULONG TotalSize;
  4500. NTSTATUS Status;
  4501. PLIST_ENTRY NextEntry;
  4502. PMI_VERIFIER_DRIVER_ENTRY Verifier;
  4503. UNICODE_STRING UserBufferDriverName;
  4504. PAGED_CODE();
  4505. NextEntryOffset = 0;
  4506. TotalSize = 0;
  4507. *Length = 0;
  4508. UserVerifyBuffer = (PSYSTEM_VERIFIER_INFORMATION)SystemInformation;
  4509. //
  4510. // Capture the number of verifying drivers and the relevant data while
  4511. // synchronized. Then return it to our caller.
  4512. //
  4513. Status = STATUS_SUCCESS;
  4514. CurrentThread = KeGetCurrentThread ();
  4515. KeEnterCriticalRegionThread (CurrentThread);
  4516. KeWaitForSingleObject (&MmSystemLoadLock,
  4517. WrVirtualMemory,
  4518. KernelMode,
  4519. FALSE,
  4520. (PLARGE_INTEGER)NULL);
  4521. try {
  4522. NextEntry = MiSuspectDriverList.Flink;
  4523. while (NextEntry != &MiSuspectDriverList) {
  4524. Verifier = CONTAINING_RECORD(NextEntry,
  4525. MI_VERIFIER_DRIVER_ENTRY,
  4526. Links);
  4527. if (((Verifier->Flags & VI_VERIFYING_DIRECTLY) == 0) ||
  4528. (Verifier->Flags & VI_DISABLE_VERIFICATION)) {
  4529. NextEntry = NextEntry->Flink;
  4530. continue;
  4531. }
  4532. UserVerifyBuffer = (PSYSTEM_VERIFIER_INFORMATION)(
  4533. (PUCHAR)UserVerifyBuffer + NextEntryOffset);
  4534. NextEntryOffset = sizeof(SYSTEM_VERIFIER_INFORMATION);
  4535. TotalSize += sizeof(SYSTEM_VERIFIER_INFORMATION);
  4536. if (TotalSize > SystemInformationLength) {
  4537. ExRaiseStatus (STATUS_INFO_LENGTH_MISMATCH);
  4538. }
  4539. //
  4540. // This data is cumulative for all drivers.
  4541. //
  4542. UserVerifyBuffer->Level = MmVerifierData.Level;
  4543. UserVerifyBuffer->RaiseIrqls = MmVerifierData.RaiseIrqls;
  4544. UserVerifyBuffer->AcquireSpinLocks = MmVerifierData.AcquireSpinLocks;
  4545. UserVerifyBuffer->UnTrackedPool = MmVerifierData.UnTrackedPool;
  4546. UserVerifyBuffer->SynchronizeExecutions = MmVerifierData.SynchronizeExecutions;
  4547. UserVerifyBuffer->AllocationsAttempted = MmVerifierData.AllocationsAttempted;
  4548. UserVerifyBuffer->AllocationsSucceeded = MmVerifierData.AllocationsSucceeded;
  4549. UserVerifyBuffer->AllocationsSucceededSpecialPool = MmVerifierData.AllocationsSucceededSpecialPool;
  4550. UserVerifyBuffer->AllocationsWithNoTag = MmVerifierData.AllocationsWithNoTag;
  4551. UserVerifyBuffer->TrimRequests = MmVerifierData.TrimRequests;
  4552. UserVerifyBuffer->Trims = MmVerifierData.Trims;
  4553. UserVerifyBuffer->AllocationsFailed = MmVerifierData.AllocationsFailed;
  4554. UserVerifyBuffer->AllocationsFailedDeliberately = MmVerifierData.AllocationsFailedDeliberately;
  4555. //
  4556. // This data is kept on a per-driver basis.
  4557. //
  4558. UserVerifyBuffer->CurrentPagedPoolAllocations = Verifier->CurrentPagedPoolAllocations;
  4559. UserVerifyBuffer->CurrentNonPagedPoolAllocations = Verifier->CurrentNonPagedPoolAllocations;
  4560. UserVerifyBuffer->PeakPagedPoolAllocations = Verifier->PeakPagedPoolAllocations;
  4561. UserVerifyBuffer->PeakNonPagedPoolAllocations = Verifier->PeakNonPagedPoolAllocations;
  4562. UserVerifyBuffer->PagedPoolUsageInBytes = Verifier->PagedBytes;
  4563. UserVerifyBuffer->NonPagedPoolUsageInBytes = Verifier->NonPagedBytes;
  4564. UserVerifyBuffer->PeakPagedPoolUsageInBytes = Verifier->PeakPagedBytes;
  4565. UserVerifyBuffer->PeakNonPagedPoolUsageInBytes = Verifier->PeakNonPagedBytes;
  4566. UserVerifyBuffer->Loads = Verifier->Loads;
  4567. UserVerifyBuffer->Unloads = Verifier->Unloads;
  4568. //
  4569. // The DriverName portion of the UserVerifyBuffer must be saved
  4570. // locally to protect against a malicious thread changing the
  4571. // contents. This is because we will reference the contents
  4572. // ourselves when the actual string is copied out carefully below.
  4573. //
  4574. UserBufferDriverName.Length = Verifier->BaseName.Length;
  4575. UserBufferDriverName.MaximumLength = (USHORT)(Verifier->BaseName.Length + sizeof (WCHAR));
  4576. UserBufferDriverName.Buffer = (PWCHAR)(UserVerifyBuffer + 1);
  4577. UserVerifyBuffer->DriverName = UserBufferDriverName;
  4578. TotalSize += ROUND_UP (UserBufferDriverName.MaximumLength,
  4579. sizeof(PVOID));
  4580. NextEntryOffset += ROUND_UP (UserBufferDriverName.MaximumLength,
  4581. sizeof(PVOID));
  4582. if (TotalSize > SystemInformationLength) {
  4583. ExRaiseStatus (STATUS_INFO_LENGTH_MISMATCH);
  4584. }
  4585. //
  4586. // Carefully reference the UserVerifyBuffer here.
  4587. //
  4588. RtlCopyMemory(UserBufferDriverName.Buffer,
  4589. Verifier->BaseName.Buffer,
  4590. Verifier->BaseName.Length);
  4591. UserBufferDriverName.Buffer[
  4592. Verifier->BaseName.Length/sizeof(WCHAR)] = UNICODE_NULL;
  4593. UserVerifyBuffer->NextEntryOffset = NextEntryOffset;
  4594. NextEntry = NextEntry->Flink;
  4595. }
  4596. } except (EXCEPTION_EXECUTE_HANDLER) {
  4597. Status = GetExceptionCode();
  4598. }
  4599. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  4600. KeLeaveCriticalRegionThread (CurrentThread);
  4601. if (Status != STATUS_INFO_LENGTH_MISMATCH) {
  4602. UserVerifyBuffer->NextEntryOffset = 0;
  4603. *Length = TotalSize;
  4604. }
  4605. return Status;
  4606. }
  4607. NTSTATUS
  4608. MmSetVerifierInformation (
  4609. IN OUT PVOID SystemInformation,
  4610. IN ULONG SystemInformationLength
  4611. )
  4612. /*++
  4613. Routine Description:
  4614. This routine sets any driver verifier flags that can be done without
  4615. rebooting.
  4616. Arguments:
  4617. SystemInformation - Gets and returns the driver verification flags.
  4618. SystemInformationLength - Supplies the length of the SystemInformation
  4619. buffer.
  4620. Return Value:
  4621. Returns the status of the operation.
  4622. Environment:
  4623. The SystemInformation buffer is in user space and our caller has wrapped
  4624. a try-except around this entire routine. Capture any exceptions here and
  4625. release resources accordingly.
  4626. --*/
  4627. {
  4628. PKTHREAD CurrentThread;
  4629. ULONG UserFlags;
  4630. ULONG NewFlags;
  4631. ULONG NewFlagsOn;
  4632. ULONG NewFlagsOff;
  4633. NTSTATUS Status;
  4634. PULONG UserVerifyBuffer;
  4635. PAGED_CODE();
  4636. if (SystemInformationLength < sizeof (ULONG)) {
  4637. ExRaiseStatus (STATUS_INFO_LENGTH_MISMATCH);
  4638. }
  4639. UserVerifyBuffer = (PULONG)SystemInformation;
  4640. //
  4641. // Synchronize all changes to the flags here.
  4642. //
  4643. Status = STATUS_SUCCESS;
  4644. CurrentThread = KeGetCurrentThread ();
  4645. KeEnterCriticalRegionThread (CurrentThread);
  4646. KeWaitForSingleObject (&MmSystemLoadLock,
  4647. WrVirtualMemory,
  4648. KernelMode,
  4649. FALSE,
  4650. (PLARGE_INTEGER)NULL);
  4651. try {
  4652. UserFlags = *UserVerifyBuffer;
  4653. //
  4654. // Ensure nothing is being set or cleared that isn't supported.
  4655. //
  4656. //
  4657. NewFlagsOn = UserFlags & VerifierModifyableOptions;
  4658. NewFlags = MmVerifierData.Level | NewFlagsOn;
  4659. //
  4660. // Any bits set in NewFlagsOff must be zeroed in the NewFlags.
  4661. //
  4662. NewFlagsOff = ((~UserFlags) & VerifierModifyableOptions);
  4663. NewFlags &= ~NewFlagsOff;
  4664. if (NewFlags != MmVerifierData.Level) {
  4665. VerifierOptionChanges += 1;
  4666. MmVerifierData.Level = NewFlags;
  4667. *UserVerifyBuffer = NewFlags;
  4668. }
  4669. } except (EXCEPTION_EXECUTE_HANDLER) {
  4670. Status = GetExceptionCode();
  4671. }
  4672. KeReleaseMutant (&MmSystemLoadLock, 1, FALSE, FALSE);
  4673. KeLeaveCriticalRegionThread (CurrentThread);
  4674. return Status;
  4675. }
  4676. typedef struct _VERIFIER_STRING_INFO {
  4677. ULONG BuildNumber;
  4678. ULONG DriverVerifierLevel;
  4679. ULONG Flags;
  4680. ULONG Check;
  4681. } VERIFIER_STRING_INFO, *PVERIFIER_STRING_INFO;
  4682. #ifdef ALLOC_DATA_PRAGMA
  4683. #pragma const_seg("PAGECONST")
  4684. #endif
  4685. static const WCHAR Printable[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  4686. static const ULONG PrintableChars = sizeof (Printable) / sizeof (Printable[0]) - 1;
  4687. #ifdef ALLOC_DATA_PRAGMA
  4688. #pragma const_seg()
  4689. #endif
  4690. VOID
  4691. ViPrintString (
  4692. IN PUNICODE_STRING DriverName
  4693. )
  4694. /*++
  4695. Routine Description:
  4696. This routine does a really bad hash of build number, verifier level and
  4697. flags by using the driver name as a stream of bytes to XOR into the flags,
  4698. etc.
  4699. This is a Neill Clift special.
  4700. Arguments:
  4701. DriverName - Supplies the name of the driver.
  4702. Return Value:
  4703. None.
  4704. --*/
  4705. {
  4706. VERIFIER_STRING_INFO Bld;
  4707. PUCHAR BufPtr;
  4708. PWCHAR DriverPtr;
  4709. ULONG BufLen;
  4710. ULONG i;
  4711. ULONG j;
  4712. ULONG DriverChars;
  4713. ULONG MaxChars;
  4714. WCHAR OutBuf[sizeof (VERIFIER_STRING_INFO) * 2 + 1];
  4715. UNICODE_STRING OutBufU;
  4716. ULONG Rem;
  4717. ULONG LastRem;
  4718. LOGICAL Done;
  4719. Bld.BuildNumber = NtBuildNumber;
  4720. Bld.DriverVerifierLevel = MmVerifierData.Level;
  4721. //
  4722. // Unloads and other actions could be encoded in the Flags field here.
  4723. //
  4724. Bld.Flags = 0;
  4725. //
  4726. // Make the last ULONG a weird function of the others.
  4727. //
  4728. Bld.Check = ((Bld.Flags + 1) * Bld.BuildNumber * (Bld.DriverVerifierLevel + 1)) * 123456789;
  4729. BufPtr = (PUCHAR) &Bld;
  4730. BufLen = sizeof (Bld);
  4731. DriverChars = DriverName->Length / sizeof (DriverName->Buffer[0]);
  4732. DriverPtr = DriverName->Buffer;
  4733. MaxChars = DriverChars;
  4734. if (DriverChars < sizeof (VERIFIER_STRING_INFO)) {
  4735. MaxChars = sizeof (VERIFIER_STRING_INFO);
  4736. }
  4737. //
  4738. // Xor each character in the driver name into the buffer.
  4739. //
  4740. for (i = 0; i < MaxChars; i += 1) {
  4741. BufPtr[i % BufLen] ^= (UCHAR) RtlUpcaseUnicodeChar(DriverPtr[i % DriverChars]);
  4742. }
  4743. //
  4744. // Produce a base N decoding of the binary buffer using the printable
  4745. // characters defines. Treat the binary as a byte array and do the
  4746. // division for each, tracking the carry.
  4747. //
  4748. j = 0;
  4749. do {
  4750. Done = TRUE;
  4751. for (i = 0, LastRem = 0; i < sizeof (VERIFIER_STRING_INFO); i += 1) {
  4752. Rem = BufPtr[i] + 256 * LastRem;
  4753. BufPtr[i] = (UCHAR) (Rem / PrintableChars);
  4754. LastRem = Rem % PrintableChars;
  4755. if (BufPtr[i]) {
  4756. Done = FALSE;
  4757. }
  4758. }
  4759. OutBuf[j++] = Printable[LastRem];
  4760. if (j >= sizeof (OutBuf) / sizeof (OutBuf[0])) {
  4761. //
  4762. // The stack buffer isn't big enough.
  4763. //
  4764. return;
  4765. }
  4766. } while (Done == FALSE);
  4767. OutBuf[j] = L'\0';
  4768. OutBufU.Length = OutBufU.MaximumLength = (USHORT) (j * sizeof (WCHAR));
  4769. OutBufU.Buffer = OutBuf;
  4770. DbgPrint ("*******************************************************************************\n"
  4771. "*\n"
  4772. "* This is the string you add to your checkin description\n"
  4773. "* Driver Verifier: Enabled for %Z on Build %ld %wZ\n"
  4774. "*\n"
  4775. "*******************************************************************************\n",
  4776. DriverName, NtBuildNumber & 0xFFFFFFF, &OutBufU);
  4777. return;
  4778. }
  4779. //
  4780. // BEWARE: Various kernel macros are undefined here so we can pull in the
  4781. // real routines. This is needed because the real routines are exported for
  4782. // driver compatibility. This module has been carefully laid out so these
  4783. // macros are not referenced from this point down and references go to the
  4784. // real routines.
  4785. //
  4786. #undef KeRaiseIrql
  4787. #undef KeLowerIrql
  4788. #undef KeAcquireSpinLock
  4789. #undef KeReleaseSpinLock
  4790. #undef KeAcquireSpinLockAtDpcLevel
  4791. #undef KeReleaseSpinLockFromDpcLevel
  4792. #if 0
  4793. #undef ExAcquireResourceExclusive
  4794. #endif
  4795. #if !defined(_AMD64_)
  4796. VOID
  4797. KeRaiseIrql (
  4798. IN KIRQL NewIrql,
  4799. OUT PKIRQL OldIrql
  4800. );
  4801. #endif
  4802. VOID
  4803. KeLowerIrql (
  4804. IN KIRQL NewIrql
  4805. );
  4806. #if !defined(_AMD64_)
  4807. VOID
  4808. KeAcquireSpinLock (
  4809. IN PKSPIN_LOCK SpinLock,
  4810. OUT PKIRQL OldIrql
  4811. );
  4812. #endif
  4813. VOID
  4814. KeReleaseSpinLock (
  4815. IN PKSPIN_LOCK SpinLock,
  4816. IN KIRQL NewIrql
  4817. );
  4818. VOID
  4819. KeAcquireSpinLockAtDpcLevel (
  4820. IN PKSPIN_LOCK SpinLock
  4821. );
  4822. VOID
  4823. KeReleaseSpinLockFromDpcLevel (
  4824. IN PKSPIN_LOCK SpinLock
  4825. );
  4826. #if 0
  4827. BOOLEAN
  4828. ExAcquireResourceExclusive (
  4829. IN PERESOURCE Resource,
  4830. IN BOOLEAN Wait
  4831. );
  4832. #endif
  4833. #ifdef ALLOC_DATA_PRAGMA
  4834. #pragma const_seg("PAGECONST")
  4835. #endif
  4836. const VERIFIER_THUNKS MiVerifierThunks[] = {
  4837. "KeSetEvent",
  4838. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierSetEvent,
  4839. "ExAcquireFastMutexUnsafe",
  4840. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireFastMutexUnsafe,
  4841. "ExReleaseFastMutexUnsafe",
  4842. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExReleaseFastMutexUnsafe,
  4843. "ExAcquireResourceExclusiveLite",
  4844. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireResourceExclusiveLite,
  4845. "ExReleaseResourceLite",
  4846. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExReleaseResourceLite,
  4847. "MmProbeAndLockPages",
  4848. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierProbeAndLockPages,
  4849. #if 0
  4850. //
  4851. // Don't bother thunking this API as it appears no drivers use it.
  4852. //
  4853. "MmProbeAndLockSelectedPages",
  4854. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierProbeAndLockSelectedPages,
  4855. #endif
  4856. "MmProbeAndLockProcessPages",
  4857. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierProbeAndLockProcessPages,
  4858. "MmMapIoSpace",
  4859. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierMapIoSpace,
  4860. "MmMapLockedPages",
  4861. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierMapLockedPages,
  4862. "MmMapLockedPagesSpecifyCache",
  4863. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierMapLockedPagesSpecifyCache,
  4864. "MmUnlockPages",
  4865. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierUnlockPages,
  4866. "MmUnmapLockedPages",
  4867. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierUnmapLockedPages,
  4868. "MmUnmapIoSpace",
  4869. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierUnmapIoSpace,
  4870. "ExAcquireFastMutex",
  4871. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExAcquireFastMutex,
  4872. "ExTryToAcquireFastMutex",
  4873. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExTryToAcquireFastMutex,
  4874. "ExReleaseFastMutex",
  4875. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierExReleaseFastMutex,
  4876. #if !defined(_AMD64_)
  4877. "KeRaiseIrql",
  4878. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeRaiseIrql,
  4879. #endif
  4880. "KeLowerIrql",
  4881. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeLowerIrql,
  4882. #if !defined(_AMD64_)
  4883. "KeAcquireSpinLock",
  4884. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLock,
  4885. #endif
  4886. "KeReleaseSpinLock",
  4887. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLock,
  4888. #if defined(_X86_)
  4889. "KefAcquireSpinLockAtDpcLevel",
  4890. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLockAtDpcLevel,
  4891. "KefReleaseSpinLockFromDpcLevel",
  4892. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLockFromDpcLevel,
  4893. #else
  4894. "KeAcquireSpinLockAtDpcLevel",
  4895. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLockAtDpcLevel,
  4896. "KeReleaseSpinLockFromDpcLevel",
  4897. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLockFromDpcLevel,
  4898. #endif
  4899. "KeSynchronizeExecution",
  4900. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierSynchronizeExecution,
  4901. "KeInitializeTimerEx",
  4902. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeInitializeTimerEx,
  4903. "KeInitializeTimer",
  4904. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeInitializeTimer,
  4905. "KeWaitForSingleObject",
  4906. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeWaitForSingleObject,
  4907. #if defined(_X86_) || defined(_AMD64_)
  4908. "KfRaiseIrql",
  4909. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfRaiseIrql,
  4910. "KeRaiseIrqlToDpcLevel",
  4911. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeRaiseIrqlToDpcLevel,
  4912. #endif
  4913. #if defined(_X86_)
  4914. "KfLowerIrql",
  4915. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfLowerIrql,
  4916. "KfAcquireSpinLock",
  4917. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfAcquireSpinLock,
  4918. "KfReleaseSpinLock",
  4919. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfReleaseSpinLock,
  4920. #endif
  4921. #if !defined(_X86_)
  4922. "KeAcquireSpinLockRaiseToDpc",
  4923. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLockRaiseToDpc,
  4924. #endif
  4925. "IoFreeIrp",
  4926. (PDRIVER_VERIFIER_THUNK_ROUTINE)IovFreeIrp,
  4927. "IofCallDriver",
  4928. (PDRIVER_VERIFIER_THUNK_ROUTINE)IovCallDriver,
  4929. "IofCompleteRequest",
  4930. (PDRIVER_VERIFIER_THUNK_ROUTINE)IovCompleteRequest,
  4931. "IoBuildDeviceIoControlRequest",
  4932. (PDRIVER_VERIFIER_THUNK_ROUTINE)IovBuildDeviceIoControlRequest,
  4933. "IoBuildAsynchronousFsdRequest",
  4934. (PDRIVER_VERIFIER_THUNK_ROUTINE)IovBuildAsynchronousFsdRequest,
  4935. "IoInitializeTimer",
  4936. (PDRIVER_VERIFIER_THUNK_ROUTINE)IovInitializeTimer,
  4937. "KeQueryPerformanceCounter",
  4938. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfQueryPerformanceCounter,
  4939. "IoGetDmaAdapter",
  4940. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfGetDmaAdapter,
  4941. "HalAllocateCrashDumpRegisters",
  4942. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfAllocateCrashDumpRegisters,
  4943. "ObReferenceObjectByHandle",
  4944. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierReferenceObjectByHandle,
  4945. "KeReleaseMutex",
  4946. (PDRIVER_VERIFIER_THUNK_ROUTINE) VerifierKeReleaseMutex,
  4947. "KeInitializeMutex",
  4948. (PDRIVER_VERIFIER_THUNK_ROUTINE) VerifierKeInitializeMutex,
  4949. "KeReleaseMutant",
  4950. (PDRIVER_VERIFIER_THUNK_ROUTINE) VerifierKeReleaseMutant,
  4951. "KeInitializeMutant",
  4952. (PDRIVER_VERIFIER_THUNK_ROUTINE) VerifierKeInitializeMutant,
  4953. "KeInitializeSpinLock",
  4954. (PDRIVER_VERIFIER_THUNK_ROUTINE) VerifierKeInitializeSpinLock,
  4955. #if !defined(NO_LEGACY_DRIVERS)
  4956. "HalGetAdapter",
  4957. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfLegacyGetAdapter,
  4958. "IoMapTransfer",
  4959. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfMapTransfer,
  4960. "IoFlushAdapterBuffers",
  4961. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfFlushAdapterBuffers,
  4962. "HalAllocateCommonBuffer",
  4963. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfAllocateCommonBuffer,
  4964. "HalFreeCommonBuffer",
  4965. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfFreeCommonBuffer,
  4966. "IoAllocateAdapterChannel",
  4967. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfAllocateAdapterChannel,
  4968. "IoFreeAdapterChannel",
  4969. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfFreeAdapterChannel,
  4970. "IoFreeMapRegisters",
  4971. (PDRIVER_VERIFIER_THUNK_ROUTINE)VfFreeMapRegisters,
  4972. #endif
  4973. "NtCreateFile",
  4974. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierNtCreateFile,
  4975. "NtWriteFile",
  4976. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierNtWriteFile,
  4977. "NtReadFile",
  4978. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierNtReadFile,
  4979. NULL,
  4980. NULL,
  4981. };
  4982. const VERIFIER_THUNKS MiVerifierPoolThunks[] = {
  4983. "ExAllocatePool",
  4984. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePool,
  4985. "ExAllocatePoolWithQuota",
  4986. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithQuota,
  4987. "ExAllocatePoolWithQuotaTag",
  4988. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithQuotaTag,
  4989. "ExAllocatePoolWithTag",
  4990. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithTag,
  4991. "ExAllocatePoolWithTagPriority",
  4992. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierAllocatePoolWithTagPriority,
  4993. "ExFreePool",
  4994. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierFreePool,
  4995. "ExFreePoolWithTag",
  4996. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierFreePoolWithTag,
  4997. NULL,
  4998. NULL,
  4999. };
  5000. #ifdef ALLOC_DATA_PRAGMA
  5001. #pragma data_seg()
  5002. #endif
  5003. PDRIVER_VERIFIER_THUNK_ROUTINE
  5004. MiResolveVerifierExports (
  5005. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  5006. IN PCHAR PristineName
  5007. )
  5008. /*++
  5009. Routine Description:
  5010. This function scans the kernel & HAL exports for the specified routine name.
  5011. Arguments:
  5012. DataTableEntry - Supplies the data table entry for the driver.
  5013. Return Value:
  5014. Non-NULL address of routine to thunk or NULL if the routine could not be
  5015. found.
  5016. Environment:
  5017. Kernel mode, Phase 0 Initialization only.
  5018. The PsLoadedModuleList has not been initialized yet.
  5019. Non paged pool exists in Phase0, but paged pool does not.
  5020. --*/
  5021. {
  5022. ULONG i;
  5023. PIMAGE_EXPORT_DIRECTORY ExportDirectory;
  5024. PULONG NameTableBase;
  5025. PUSHORT NameOrdinalTableBase;
  5026. PULONG Addr;
  5027. ULONG ExportSize;
  5028. ULONG Low;
  5029. ULONG Middle;
  5030. ULONG High;
  5031. PLIST_ENTRY NextEntry;
  5032. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  5033. USHORT OrdinalNumber;
  5034. LONG Result;
  5035. PCHAR DllBase;
  5036. i = 0;
  5037. NextEntry = LoaderBlock->LoadOrderListHead.Flink;
  5038. for ( ; NextEntry != &LoaderBlock->LoadOrderListHead; NextEntry = NextEntry->Flink) {
  5039. DataTableEntry = CONTAINING_RECORD (NextEntry,
  5040. KLDR_DATA_TABLE_ENTRY,
  5041. InLoadOrderLinks);
  5042. //
  5043. // Process the kernel and HAL exports so the proper routine
  5044. // addresses can be generated now that relocations are complete.
  5045. //
  5046. DllBase = (PCHAR) DataTableEntry->DllBase;
  5047. ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
  5048. (PVOID) DllBase,
  5049. TRUE,
  5050. IMAGE_DIRECTORY_ENTRY_EXPORT,
  5051. &ExportSize);
  5052. if (ExportDirectory != NULL) {
  5053. //
  5054. // Lookup the import name in the name table using a binary search.
  5055. //
  5056. NameTableBase = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfNames);
  5057. NameOrdinalTableBase = (PUSHORT)(DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
  5058. Low = 0;
  5059. High = ExportDirectory->NumberOfNames - 1;
  5060. //
  5061. // Initializing Middle is not needed for correctness, but without it
  5062. // the compiler cannot compile this code W4 to check for use of
  5063. // uninitialized variables.
  5064. //
  5065. Middle = 0;
  5066. while (High >= Low) {
  5067. //
  5068. // Compute the next probe index and compare the import name
  5069. // with the export name entry.
  5070. //
  5071. Middle = (Low + High) >> 1;
  5072. Result = strcmp (PristineName,
  5073. (PCHAR)DllBase + NameTableBase[Middle]);
  5074. if (Result < 0) {
  5075. High = Middle - 1;
  5076. } else if (Result > 0) {
  5077. Low = Middle + 1;
  5078. }
  5079. else {
  5080. break;
  5081. }
  5082. }
  5083. //
  5084. // If the high index is less than the low index, then a matching
  5085. // table entry was not found. Otherwise, get the ordinal number
  5086. // from the ordinal table.
  5087. //
  5088. if ((LONG)High >= (LONG)Low) {
  5089. OrdinalNumber = NameOrdinalTableBase[Middle];
  5090. //
  5091. // If OrdinalNumber is not within the Export Address Table,
  5092. // then DLL does not implement function. Otherwise we have
  5093. // the export that matches the specified argument routine name.
  5094. //
  5095. if ((ULONG)OrdinalNumber < ExportDirectory->NumberOfFunctions) {
  5096. Addr = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
  5097. return (PDRIVER_VERIFIER_THUNK_ROUTINE)(ULONG_PTR)(DllBase + Addr[OrdinalNumber]);
  5098. }
  5099. }
  5100. }
  5101. i += 1;
  5102. if (i == 2) {
  5103. break;
  5104. }
  5105. }
  5106. return NULL;
  5107. }
  5108. LOGICAL
  5109. MiEnableVerifier (
  5110. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  5111. )
  5112. /*++
  5113. Routine Description:
  5114. This function enables the verifier for the argument driver by thunking
  5115. relevant system APIs in the argument driver import table.
  5116. Arguments:
  5117. DataTableEntry - Supplies the data table entry for the driver.
  5118. Return Value:
  5119. TRUE if thunking was applied, FALSE if not.
  5120. Environment:
  5121. Kernel mode, Phase 0 Initialization and normal runtime.
  5122. Non paged pool exists in Phase0, but paged pool does not.
  5123. --*/
  5124. {
  5125. ULONG i;
  5126. ULONG j;
  5127. PULONG_PTR ImportThunk;
  5128. ULONG ImportSize;
  5129. VERIFIER_THUNKS const *VerifierThunk;
  5130. LOGICAL Found;
  5131. ULONG_PTR RealRoutine;
  5132. PLIST_ENTRY NextEntry;
  5133. PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable;
  5134. PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase;
  5135. ImportThunk = (PULONG_PTR)RtlImageDirectoryEntryToData(
  5136. DataTableEntry->DllBase,
  5137. TRUE,
  5138. IMAGE_DIRECTORY_ENTRY_IAT,
  5139. &ImportSize);
  5140. if (ImportThunk == NULL) {
  5141. return FALSE;
  5142. }
  5143. ImportSize /= sizeof(PULONG_PTR);
  5144. for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) {
  5145. Found = FALSE;
  5146. if (KernelVerifier == FALSE) {
  5147. VerifierThunk = MiVerifierThunks;
  5148. while (VerifierThunk->PristineRoutineAsciiName != NULL) {
  5149. RealRoutine = (ULONG_PTR)VerifierThunk->PristineRoutine;
  5150. if (*ImportThunk == RealRoutine) {
  5151. *ImportThunk = (ULONG_PTR)(VerifierThunk->NewRoutine);
  5152. Found = TRUE;
  5153. break;
  5154. }
  5155. VerifierThunk += 1;
  5156. }
  5157. }
  5158. if (Found == FALSE) {
  5159. VerifierThunk = MiVerifierPoolThunks;
  5160. while (VerifierThunk->PristineRoutineAsciiName != NULL) {
  5161. RealRoutine = (ULONG_PTR)VerifierThunk->PristineRoutine;
  5162. if (*ImportThunk == RealRoutine) {
  5163. *ImportThunk = (ULONG_PTR)(VerifierThunk->NewRoutine);
  5164. Found = TRUE;
  5165. break;
  5166. }
  5167. VerifierThunk += 1;
  5168. }
  5169. }
  5170. if (Found == FALSE) {
  5171. NextEntry = MiVerifierDriverAddedThunkListHead.Flink;
  5172. while (NextEntry != &MiVerifierDriverAddedThunkListHead) {
  5173. ThunkTableBase = CONTAINING_RECORD(NextEntry,
  5174. DRIVER_SPECIFIED_VERIFIER_THUNKS,
  5175. ListEntry);
  5176. ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(ThunkTableBase + 1);
  5177. for (j = 0; j < ThunkTableBase->NumberOfThunks; j += 1) {
  5178. if (*ImportThunk == (ULONG_PTR)ThunkTable->PristineRoutine) {
  5179. *ImportThunk = (ULONG_PTR)(ThunkTable->NewRoutine);
  5180. Found = TRUE;
  5181. break;
  5182. }
  5183. ThunkTable += 1;
  5184. }
  5185. if (Found == TRUE) {
  5186. break;
  5187. }
  5188. NextEntry = NextEntry->Flink;
  5189. }
  5190. }
  5191. }
  5192. return TRUE;
  5193. }
  5194. LOGICAL
  5195. MiReEnableVerifier (
  5196. IN PKLDR_DATA_TABLE_ENTRY DataTableEntry
  5197. )
  5198. /*++
  5199. Routine Description:
  5200. This function thunks DLL-supplied APIs in the argument driver import table.
  5201. Arguments:
  5202. DataTableEntry - Supplies the data table entry for the driver.
  5203. Return Value:
  5204. TRUE if thunking was applied, FALSE if not.
  5205. Environment:
  5206. Kernel mode, Phase 0 Initialization only.
  5207. Non paged pool exists in Phase0, but paged pool does not.
  5208. --*/
  5209. {
  5210. ULONG i;
  5211. ULONG j;
  5212. PULONG_PTR ImportThunk;
  5213. ULONG ImportSize;
  5214. LOGICAL Found;
  5215. PLIST_ENTRY NextEntry;
  5216. PMMPTE PointerPte;
  5217. PULONG_PTR VirtualThunk;
  5218. PFN_NUMBER PageFrameIndex;
  5219. PFN_NUMBER VirtualPageFrameIndex;
  5220. PDRIVER_VERIFIER_THUNK_PAIRS ThunkTable;
  5221. PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase;
  5222. ULONG Offset;
  5223. ImportThunk = (PULONG_PTR)RtlImageDirectoryEntryToData(
  5224. DataTableEntry->DllBase,
  5225. TRUE,
  5226. IMAGE_DIRECTORY_ENTRY_IAT,
  5227. &ImportSize);
  5228. if (ImportThunk == NULL) {
  5229. return FALSE;
  5230. }
  5231. VirtualThunk = NULL;
  5232. ImportSize /= sizeof(PULONG_PTR);
  5233. //
  5234. // Initializing VirtualPageFrameIndex is not needed for correctness, but
  5235. // without it the compiler cannot compile this code W4 to check for use of
  5236. // uninitialized variables.
  5237. //
  5238. VirtualPageFrameIndex = 0;
  5239. for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) {
  5240. Found = FALSE;
  5241. NextEntry = MiVerifierDriverAddedThunkListHead.Flink;
  5242. while (NextEntry != &MiVerifierDriverAddedThunkListHead) {
  5243. ThunkTableBase = CONTAINING_RECORD(NextEntry,
  5244. DRIVER_SPECIFIED_VERIFIER_THUNKS,
  5245. ListEntry);
  5246. ThunkTable = (PDRIVER_VERIFIER_THUNK_PAIRS)(ThunkTableBase + 1);
  5247. for (j = 0; j < ThunkTableBase->NumberOfThunks; j += 1) {
  5248. if (*ImportThunk == (ULONG_PTR)ThunkTable->PristineRoutine) {
  5249. ASSERT (MI_IS_PHYSICAL_ADDRESS(ImportThunk) == 0);
  5250. PointerPte = MiGetPteAddress (ImportThunk);
  5251. ASSERT (PointerPte->u.Hard.Valid == 1);
  5252. PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
  5253. Offset = (ULONG) MiGetByteOffset(ImportThunk);
  5254. if ((VirtualThunk != NULL) &&
  5255. (VirtualPageFrameIndex == PageFrameIndex)) {
  5256. NOTHING;
  5257. }
  5258. else {
  5259. VirtualThunk = MiMapSinglePage (VirtualThunk,
  5260. PageFrameIndex,
  5261. MmCached,
  5262. HighPagePriority);
  5263. if (VirtualThunk == NULL) {
  5264. return FALSE;
  5265. }
  5266. VirtualPageFrameIndex = PageFrameIndex;
  5267. }
  5268. *(PULONG_PTR)((PUCHAR)VirtualThunk + Offset) =
  5269. (ULONG_PTR)(ThunkTable->NewRoutine);
  5270. Found = TRUE;
  5271. break;
  5272. }
  5273. ThunkTable += 1;
  5274. }
  5275. if (Found == TRUE) {
  5276. break;
  5277. }
  5278. NextEntry = NextEntry->Flink;
  5279. }
  5280. }
  5281. if (VirtualThunk != NULL) {
  5282. MiUnmapSinglePage (VirtualThunk);
  5283. }
  5284. return TRUE;
  5285. }
  5286. typedef struct _KERNEL_VERIFIER_THUNK_PAIRS {
  5287. PDRIVER_VERIFIER_THUNK_ROUTINE PristineRoutine;
  5288. PDRIVER_VERIFIER_THUNK_ROUTINE NewRoutine;
  5289. } KERNEL_VERIFIER_THUNK_PAIRS, *PKERNEL_VERIFIER_THUNK_PAIRS;
  5290. #if defined(_X86_)
  5291. #ifdef ALLOC_DATA_PRAGMA
  5292. #pragma const_seg("INITCONST")
  5293. #endif
  5294. const KERNEL_VERIFIER_THUNK_PAIRS MiKernelVerifierThunks[] = {
  5295. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeRaiseIrql,
  5296. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeRaiseIrql,
  5297. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeLowerIrql,
  5298. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeLowerIrql,
  5299. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireSpinLock,
  5300. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireSpinLock,
  5301. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeReleaseSpinLock,
  5302. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseSpinLock,
  5303. (PDRIVER_VERIFIER_THUNK_ROUTINE)KfRaiseIrql,
  5304. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfRaiseIrql,
  5305. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeRaiseIrqlToDpcLevel,
  5306. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeRaiseIrqlToDpcLevel,
  5307. (PDRIVER_VERIFIER_THUNK_ROUTINE)KfLowerIrql,
  5308. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfLowerIrql,
  5309. (PDRIVER_VERIFIER_THUNK_ROUTINE)KfAcquireSpinLock,
  5310. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfAcquireSpinLock,
  5311. (PDRIVER_VERIFIER_THUNK_ROUTINE)KfReleaseSpinLock,
  5312. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKfReleaseSpinLock,
  5313. #if !defined(NT_UP)
  5314. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeAcquireQueuedSpinLock,
  5315. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeAcquireQueuedSpinLock,
  5316. (PDRIVER_VERIFIER_THUNK_ROUTINE)KeReleaseQueuedSpinLock,
  5317. (PDRIVER_VERIFIER_THUNK_ROUTINE)VerifierKeReleaseQueuedSpinLock,
  5318. #endif
  5319. };
  5320. #ifdef ALLOC_DATA_PRAGMA
  5321. #pragma data_seg()
  5322. #endif
  5323. VOID
  5324. MiEnableKernelVerifier (
  5325. VOID
  5326. )
  5327. /*++
  5328. Routine Description:
  5329. This function enables the verifier for the kernel by thunking
  5330. relevant HAL APIs in the kernel's import table.
  5331. Arguments:
  5332. None.
  5333. Return Value:
  5334. None.
  5335. Environment:
  5336. Kernel mode, Phase 1 Initialization.
  5337. --*/
  5338. {
  5339. ULONG i;
  5340. PULONG_PTR ImportThunk;
  5341. ULONG ImportSize;
  5342. KERNEL_VERIFIER_THUNK_PAIRS const *VerifierThunk;
  5343. ULONG ThunkCount;
  5344. ULONG_PTR RealRoutine;
  5345. PULONG_PTR PointerRealRoutine;
  5346. if (KernelVerifier == FALSE) {
  5347. return;
  5348. }
  5349. ImportThunk = (PULONG_PTR)RtlImageDirectoryEntryToData(
  5350. PsNtosImageBase,
  5351. TRUE,
  5352. IMAGE_DIRECTORY_ENTRY_IAT,
  5353. &ImportSize);
  5354. if (ImportThunk == NULL) {
  5355. return;
  5356. }
  5357. ImportSize /= sizeof(PULONG_PTR);
  5358. for (i = 0; i < ImportSize; i += 1, ImportThunk += 1) {
  5359. VerifierThunk = MiKernelVerifierThunks;
  5360. for (ThunkCount = 0; ThunkCount < sizeof (MiKernelVerifierThunks) / sizeof (KERNEL_VERIFIER_THUNK_PAIRS); ThunkCount += 1) {
  5361. //
  5362. // Only the x86 has/needs this oddity - take the kernel address,
  5363. // knowing that it points at a 2 byte jmp opcode followed by
  5364. // a 4-byte indirect pointer to a destination address.
  5365. //
  5366. PointerRealRoutine = (PULONG_PTR)*((PULONG_PTR)((ULONG_PTR)VerifierThunk->PristineRoutine + 2));
  5367. RealRoutine = *PointerRealRoutine;
  5368. if (*ImportThunk == RealRoutine) {
  5369. //
  5370. // Order is important here.
  5371. //
  5372. if (MiKernelVerifierOriginalCalls[ThunkCount] == NULL) {
  5373. MiKernelVerifierOriginalCalls[ThunkCount] = (PVOID)RealRoutine;
  5374. }
  5375. *ImportThunk = (ULONG_PTR)(VerifierThunk->NewRoutine);
  5376. break;
  5377. }
  5378. VerifierThunk += 1;
  5379. }
  5380. }
  5381. return;
  5382. }
  5383. #endif
  5384. //
  5385. // BEWARE: Various kernel macros were undefined above so we can pull in the
  5386. // real routines. This is needed because the real routines are exported for
  5387. // driver compatibility. This module has been carefully laid out so these
  5388. // macros are not referenced from that point to here and references go to the
  5389. // real routines.
  5390. //
  5391. // BE EXTREMELY CAREFUL IF YOU DECIDE TO ADD ROUTINES BELOW THIS POINT !
  5392. //