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.

692 lines
16 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. faults.c
  5. Abstract:
  6. This module implements fault injection support.
  7. Author:
  8. Silviu Calinoiu (SilviuC) 3-Dec-2001
  9. Revision History:
  10. 3-Dec-2001 (SilviuC): initial version.
  11. --*/
  12. #include "pch.h"
  13. #include "verifier.h"
  14. #include "support.h"
  15. #include "faults.h"
  16. ULONG AVrfpFaultSeed;
  17. ULONG AVrfpFaultProbability [CLS_MAXIMUM_INDEX];
  18. ULONG AVrfpFaultBreak [CLS_MAXIMUM_INDEX];
  19. ULONG AVrfpFaultTrue [CLS_MAXIMUM_INDEX];
  20. ULONG AVrfpFaultFalse [CLS_MAXIMUM_INDEX];
  21. //
  22. // Target ranges for fault injection.
  23. //
  24. #define MAXIMUM_TARGET_INDEX 128
  25. ULONG_PTR AVrfpFaultTargetStart [MAXIMUM_TARGET_INDEX];
  26. ULONG_PTR AVrfpFaultTargetEnd [MAXIMUM_TARGET_INDEX];
  27. ULONG AVrfpFaultTargetHits [MAXIMUM_TARGET_INDEX];
  28. ULONG AVrfpFaultTargetMaximumIndex;
  29. //
  30. // Exclusion ranges for fault injection.
  31. //
  32. #define MAXIMUM_EXCLUSION_INDEX 128
  33. ULONG_PTR AVrfpFaultExclusionStart [MAXIMUM_TARGET_INDEX];
  34. ULONG_PTR AVrfpFaultExclusionEnd [MAXIMUM_TARGET_INDEX];
  35. ULONG AVrfpFaultExclusionHits [MAXIMUM_TARGET_INDEX];
  36. ULONG AVrfpFaultExclusionMaximumIndex;
  37. //
  38. // Fault injection trace history.
  39. //
  40. #define NUMBER_OF_TRACES 128
  41. PVOID AVrfpFaultTrace[NUMBER_OF_TRACES][MAX_TRACE_DEPTH];
  42. ULONG AVrfpFaultNumberOfTraces = NUMBER_OF_TRACES;
  43. ULONG AVrfpFaultTraceSize = MAX_TRACE_DEPTH;
  44. ULONG AVrfpFaultTraceIndex;
  45. //
  46. // Period amnesty. The period of time when fault injection should
  47. // be avoided is written from debugger.
  48. //
  49. LARGE_INTEGER AVrfpFaultStartTime;
  50. ULONG AVrfpFaultPeriodTimeInMsecs;
  51. //
  52. // Lock used to synchronize some low frequency operations (e.g. exports
  53. // for target/exclusion range manipulation).
  54. //
  55. RTL_CRITICAL_SECTION AVrfpFaultInjectionLock;
  56. LOGICAL
  57. AVrfpIsAddressInTargetRange (
  58. ULONG_PTR Address
  59. );
  60. LOGICAL
  61. AVrfpIsAddressInExclusionRange (
  62. ULONG_PTR Address
  63. );
  64. VOID
  65. AVrfpLogFaultTrace (
  66. VOID
  67. );
  68. NTSTATUS
  69. AVrfpInitializeFaultInjectionSupport (
  70. VOID
  71. )
  72. {
  73. NTSTATUS Status;
  74. LARGE_INTEGER PerformanceCounter;
  75. Status = STATUS_SUCCESS;
  76. //
  77. // Initialize lock used for some fault injection operations.
  78. //
  79. Status = RtlInitializeCriticalSection (&AVrfpFaultInjectionLock);
  80. if (! NT_SUCCESS(Status)) {
  81. return Status;
  82. }
  83. //
  84. // Initialize the seed for the random generator.
  85. //
  86. NtQueryPerformanceCounter (&PerformanceCounter, NULL);
  87. AVrfpFaultSeed = PerformanceCounter.LowPart;
  88. NtQuerySystemTime (&AVrfpFaultStartTime);
  89. //
  90. // Touch the break triggers vector so that the compiler
  91. // does not optimize away the entire structure. Since it
  92. // is supposed to be modified only from debugger the compiler
  93. // considers that the array is not needed.
  94. //
  95. RtlZeroMemory (AVrfpBreak, sizeof AVrfpBreak);
  96. //
  97. // Same reason as above.
  98. //
  99. AVrfpFaultTargetMaximumIndex = MAXIMUM_TARGET_INDEX;
  100. RtlZeroMemory (AVrfpFaultTargetStart, sizeof AVrfpFaultTargetStart);
  101. RtlZeroMemory (AVrfpFaultTargetEnd, sizeof AVrfpFaultTargetEnd);
  102. RtlZeroMemory (AVrfpFaultTargetHits, sizeof AVrfpFaultTargetHits);
  103. AVrfpFaultTargetStart[0] = 0;
  104. AVrfpFaultTargetEnd[0] = ~((ULONG_PTR)0);
  105. AVrfpFaultExclusionMaximumIndex = MAXIMUM_EXCLUSION_INDEX;
  106. RtlZeroMemory (AVrfpFaultExclusionStart, sizeof AVrfpFaultExclusionStart);
  107. RtlZeroMemory (AVrfpFaultExclusionEnd, sizeof AVrfpFaultExclusionEnd);
  108. RtlZeroMemory (AVrfpFaultExclusionHits, sizeof AVrfpFaultExclusionHits);
  109. return Status;
  110. }
  111. LOGICAL
  112. AVrfpShouldFaultInject (
  113. ULONG Class,
  114. PVOID Caller
  115. )
  116. {
  117. ULONG Random;
  118. LARGE_INTEGER Time;
  119. LARGE_INTEGER Delta;
  120. //
  121. // No fault injection => return FALSE
  122. //
  123. if (AVrfpFaultProbability[Class] == 0) {
  124. return FALSE;
  125. }
  126. //
  127. // Check if some period amnesty was set. `AVrfpFaultPeriodTimeInMsecs' variable
  128. // is only read and reset to zero from verifier code. It is set to non null values
  129. // only from debugger extensions. Therefore to way it is used before without
  130. // serialization is ok even if after the `if' condition another thread resets it.
  131. //
  132. if (AVrfpFaultPeriodTimeInMsecs) {
  133. NtQuerySystemTime (&Time);
  134. Delta.QuadPart = (DWORDLONG)AVrfpFaultPeriodTimeInMsecs * 1000 * 10;
  135. if (Time.QuadPart - AVrfpFaultStartTime.QuadPart > Delta.QuadPart) {
  136. AVrfpFaultPeriodTimeInMsecs = 0;
  137. }
  138. else {
  139. return FALSE;
  140. }
  141. }
  142. //
  143. // If in exclusion range => return FALSE
  144. //
  145. if (AVrfpIsAddressInExclusionRange ((ULONG_PTR)Caller) == TRUE) {
  146. return FALSE;
  147. }
  148. //
  149. // Not in target range => return FALSE
  150. //
  151. if (AVrfpIsAddressInTargetRange ((ULONG_PTR)Caller) == FALSE) {
  152. return FALSE;
  153. }
  154. //
  155. // Operations above access only READ-ONLY data (it gets modified
  156. // only from debugger). From now on though we need synchronized
  157. // access.
  158. //
  159. Random = RtlRandom (&AVrfpFaultSeed);
  160. if (Random % 100 < AVrfpFaultProbability[Class]) {
  161. InterlockedIncrement((PLONG)(&(AVrfpFaultTrue[Class])));
  162. if (AVrfpFaultBreak[Class]) {
  163. DbgPrint ("AVRF: fault injecting call made from %p \n", Caller);
  164. DbgBreakPoint ();
  165. }
  166. AVrfpLogFaultTrace ();
  167. return TRUE;
  168. }
  169. else {
  170. InterlockedIncrement((PLONG)(&(AVrfpFaultFalse[Class])));
  171. return FALSE;
  172. }
  173. }
  174. LOGICAL
  175. AVrfpIsAddressInTargetRange (
  176. ULONG_PTR Address
  177. )
  178. {
  179. ULONG I;
  180. if (Address == 0) {
  181. return FALSE;
  182. }
  183. for (I = 0; I < AVrfpFaultTargetMaximumIndex; I += 1) {
  184. if (AVrfpFaultTargetEnd[I] != 0) {
  185. if (AVrfpFaultTargetStart[I] <= Address &&
  186. AVrfpFaultTargetEnd[I] > Address) {
  187. AVrfpFaultTargetHits[I] += 1;
  188. return TRUE;
  189. }
  190. }
  191. }
  192. return FALSE;
  193. }
  194. LOGICAL
  195. AVrfpIsAddressInExclusionRange (
  196. ULONG_PTR Address
  197. )
  198. {
  199. ULONG I;
  200. if (Address == 0) {
  201. return FALSE;
  202. }
  203. for (I = 0; I < AVrfpFaultExclusionMaximumIndex; I += 1) {
  204. if (AVrfpFaultExclusionEnd[I] != 0) {
  205. if (AVrfpFaultExclusionStart[I] <= Address &&
  206. AVrfpFaultExclusionEnd[I] > Address) {
  207. AVrfpFaultExclusionHits[I] += 1;
  208. return TRUE;
  209. }
  210. }
  211. }
  212. return FALSE;
  213. }
  214. VOID
  215. AVrfpLogFaultTrace (
  216. VOID
  217. )
  218. {
  219. ULONG Index;
  220. Index = (ULONG)InterlockedIncrement ((PLONG)(&AVrfpFaultTraceIndex));
  221. Index %= AVrfpFaultNumberOfTraces;
  222. RtlCaptureStackBackTrace (2,
  223. AVrfpFaultTraceSize,
  224. &(AVrfpFaultTrace[Index][0]),
  225. NULL);
  226. }
  227. /////////////////////////////////////////////////////////////////////
  228. ///////////////////////////////////////// Fault injection general SDK
  229. /////////////////////////////////////////////////////////////////////
  230. VOID
  231. VerifierSetFaultInjectionProbability (
  232. ULONG Class,
  233. ULONG Probability
  234. )
  235. /*++
  236. Routine Description:
  237. This routine set fault injection probability for a certain class of events
  238. (heap operations, registry operations, etc.).
  239. Arguments:
  240. Class - class of events for which fault injection probability is set. Constants
  241. are of type FAULT_INJECTION_CLASS_XXX.
  242. Probability - probability for fault injection.
  243. Return Value:
  244. None.
  245. --*/
  246. {
  247. //
  248. // Application verifier must be enabled.
  249. //
  250. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  251. return;
  252. }
  253. if (Class >= FAULT_INJECTION_INVALID_CLASS) {
  254. DbgPrint ("AVRF:FINJ: invalid fault injection class %X \n", Class);
  255. DbgBreakPoint ();
  256. return;
  257. }
  258. RtlEnterCriticalSection (&AVrfpFaultInjectionLock);
  259. AVrfpFaultProbability [Class] = Probability;
  260. RtlLeaveCriticalSection (&AVrfpFaultInjectionLock);
  261. }
  262. /////////////////////////////////////////////////////////////////////
  263. ///////////////////////// Target/exclusion fault injection ranges SDK
  264. /////////////////////////////////////////////////////////////////////
  265. ULONG
  266. VerifierEnableFaultInjectionTargetRange (
  267. PVOID StartAddress,
  268. PVOID EndAddress
  269. )
  270. /*++
  271. Routine Description:
  272. This routine establishes at runtime a fault injection target range. If successful
  273. it will return a range index that can be used later to disable the range.
  274. Arguments:
  275. StartAddress - start address of the target range.
  276. EndAddress - end address of the target range.
  277. Return Value:
  278. A range index >0 if succesful. Zero otherwise.
  279. --*/
  280. {
  281. ULONG Ri;
  282. ULONG FinalIndex;
  283. //
  284. // Application verifier must be enabled.
  285. //
  286. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  287. return 0;
  288. }
  289. FinalIndex = 0;
  290. RtlEnterCriticalSection (&AVrfpFaultInjectionLock);
  291. if (AVrfpFaultTargetStart[0] == 0 &&
  292. AVrfpFaultTargetEnd[0] == ~((ULONG_PTR)0)) {
  293. AVrfpFaultTargetStart[0] = (ULONG_PTR)StartAddress;
  294. AVrfpFaultTargetEnd[0] = (ULONG_PTR)EndAddress;
  295. AVrfpFaultTargetHits[0] = 0;
  296. FinalIndex = 1;
  297. }
  298. else {
  299. for (Ri = 0; Ri < AVrfpFaultTargetMaximumIndex; Ri += 1) {
  300. if (AVrfpFaultTargetEnd[Ri] == 0) {
  301. AVrfpFaultTargetStart[Ri] = (ULONG_PTR)StartAddress;
  302. AVrfpFaultTargetEnd[Ri] = (ULONG_PTR)EndAddress;
  303. AVrfpFaultTargetHits[Ri] = 0;
  304. FinalIndex = Ri + 1;
  305. break;
  306. }
  307. }
  308. }
  309. RtlLeaveCriticalSection (&AVrfpFaultInjectionLock);
  310. return FinalIndex;
  311. }
  312. VOID
  313. VerifierDisableFaultInjectionTargetRange (
  314. ULONG RangeIndex
  315. )
  316. /*++
  317. Routine Description:
  318. This routine disables the target range specified by the RangeIndex.
  319. If the RangeIndex is zero then all target ranges will be disabled.
  320. The function breaks in the debugger (even in free builds) if the
  321. range index is invalid.
  322. Arguments:
  323. RangeIndex - index of range to disable or zero if all need to be disabled.
  324. Return Value:
  325. None.
  326. --*/
  327. {
  328. ULONG Ri;
  329. LOGICAL FoundOne;
  330. //
  331. // Application verifier must be enabled.
  332. //
  333. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  334. return;
  335. }
  336. RtlEnterCriticalSection (&AVrfpFaultInjectionLock);
  337. if (RangeIndex == 0) {
  338. //
  339. // Disable all target ranges.
  340. //
  341. for (Ri = 0; Ri < AVrfpFaultTargetMaximumIndex; Ri += 1) {
  342. AVrfpFaultTargetStart[Ri] = 0;
  343. AVrfpFaultTargetEnd[Ri] = 0;
  344. AVrfpFaultTargetHits[Ri] = 0;
  345. }
  346. AVrfpFaultTargetStart[0] = 0;
  347. AVrfpFaultTargetEnd[0] = ~((ULONG_PTR)0);
  348. AVrfpFaultTargetHits[0] = 0;
  349. }
  350. else {
  351. //
  352. // disable target range `RangeIndex - 1'.
  353. //
  354. RangeIndex -= 1;
  355. if (RangeIndex >= AVrfpFaultTargetMaximumIndex) {
  356. DbgPrint ("AVRF:FINJ: invalid target range index %X \n", RangeIndex);
  357. DbgBreakPoint ();
  358. goto Exit;
  359. }
  360. if (AVrfpFaultTargetEnd[RangeIndex] == 0) {
  361. DbgPrint ("AVRF:FINJ: disabling empty target range at index %X \n", RangeIndex);
  362. DbgBreakPoint ();
  363. goto Exit;
  364. }
  365. AVrfpFaultTargetStart[RangeIndex] = 0;
  366. AVrfpFaultTargetEnd[RangeIndex] = 0;
  367. AVrfpFaultTargetHits[RangeIndex] = 0;
  368. //
  369. // If we do not have any target ranges active then establish the default
  370. // target range that spans the entire virtual space.
  371. //
  372. FoundOne = FALSE;
  373. for (Ri = 0; Ri < AVrfpFaultTargetMaximumIndex; Ri += 1) {
  374. if (AVrfpFaultTargetEnd[Ri] != 0) {
  375. FoundOne = TRUE;
  376. break;
  377. }
  378. }
  379. if (! FoundOne) {
  380. AVrfpFaultTargetStart[0] = 0;
  381. AVrfpFaultTargetEnd[0] = ~((ULONG_PTR)0);
  382. AVrfpFaultTargetHits[0] = 0;
  383. }
  384. }
  385. Exit:
  386. RtlLeaveCriticalSection (&AVrfpFaultInjectionLock);
  387. }
  388. ULONG
  389. VerifierEnableFaultInjectionExclusionRange (
  390. PVOID StartAddress,
  391. PVOID EndAddress
  392. )
  393. /*++
  394. Routine Description:
  395. This routine establishes at runtime a fault injection exclusion range. If successful
  396. it will return a range index that can be used later to disable the range.
  397. Arguments:
  398. StartAddress - start address of the exclusion range.
  399. EndAddress - end address of the exclusion range.
  400. Return Value:
  401. A range index >0 if succesful. Zero otherwise.
  402. --*/
  403. {
  404. ULONG Ri;
  405. ULONG FinalIndex;
  406. //
  407. // Application verifier must be enabled.
  408. //
  409. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  410. return 0;
  411. }
  412. FinalIndex = 0;
  413. RtlEnterCriticalSection (&AVrfpFaultInjectionLock);
  414. for (Ri = 0; Ri < AVrfpFaultExclusionMaximumIndex; Ri += 1) {
  415. if (AVrfpFaultExclusionEnd[Ri] == 0) {
  416. AVrfpFaultExclusionStart[Ri] = (ULONG_PTR)StartAddress;
  417. AVrfpFaultExclusionEnd[Ri] = (ULONG_PTR)EndAddress;
  418. AVrfpFaultExclusionHits[Ri] = 0;
  419. FinalIndex = Ri + 1;
  420. break;
  421. }
  422. }
  423. RtlLeaveCriticalSection (&AVrfpFaultInjectionLock);
  424. return FinalIndex;
  425. }
  426. VOID
  427. VerifierDisableFaultInjectionExclusionRange (
  428. ULONG RangeIndex
  429. )
  430. /*++
  431. Routine Description:
  432. This routine disables the exclusion range specified by the RangeIndex.
  433. If the RangeIndex is zero then all exclusion ranges will be disabled.
  434. The function breaks in the debugger (even in free builds) if the
  435. range index is invalid.
  436. Arguments:
  437. RangeIndex - index of range to disable or zero if all need to be disabled.
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. ULONG Ri;
  443. //
  444. // Application verifier must be enabled.
  445. //
  446. if ((NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) == 0) {
  447. return;
  448. }
  449. RtlEnterCriticalSection (&AVrfpFaultInjectionLock);
  450. if (RangeIndex == 0) {
  451. //
  452. // Disable all exclusion ranges.
  453. //
  454. for (Ri = 0; Ri < AVrfpFaultExclusionMaximumIndex; Ri += 1) {
  455. AVrfpFaultExclusionStart[Ri] = 0;
  456. AVrfpFaultExclusionEnd[Ri] = 0;
  457. AVrfpFaultExclusionHits[Ri] = 0;
  458. }
  459. }
  460. else {
  461. //
  462. // disable exclusion range `RangeIndex - 1'.
  463. //
  464. RangeIndex -= 1;
  465. if (RangeIndex >= AVrfpFaultExclusionMaximumIndex) {
  466. DbgPrint ("AVRF:FINJ: invalid exclusion range index %X \n", RangeIndex);
  467. DbgBreakPoint ();
  468. goto Exit;
  469. }
  470. if (AVrfpFaultExclusionEnd[RangeIndex] == 0) {
  471. DbgPrint ("AVRF:FINJ: disabling empty exclusion range at index %X \n", RangeIndex);
  472. DbgBreakPoint ();
  473. goto Exit;
  474. }
  475. AVrfpFaultExclusionStart[RangeIndex] = 0;
  476. AVrfpFaultExclusionEnd[RangeIndex] = 0;
  477. AVrfpFaultExclusionHits[RangeIndex] = 0;
  478. }
  479. Exit:
  480. RtlLeaveCriticalSection (&AVrfpFaultInjectionLock);
  481. }