Leaked source code of windows server 2003
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.

7512 lines
205 KiB

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