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

468 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. support.c
  5. Abstract:
  6. This module implements internal support for the verification code.
  7. Author:
  8. Silviu Calinoiu (SilviuC) 1-Mar-2001
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "verifier.h"
  13. #include "support.h"
  14. //
  15. // Security checks
  16. //
  17. VOID
  18. CheckObjectAttributes (
  19. POBJECT_ATTRIBUTES Object
  20. )
  21. {
  22. if (Object /* && Object->ObjectName */) {
  23. if (Object->ObjectName == NULL) {
  24. DbgPrint ("Object attributes @ %p with null name \n", Object);
  25. DbgBreakPoint ();
  26. }
  27. if (Object->SecurityDescriptor == NULL) {
  28. DbgPrint ("Object attributes @ %p with null security descriptor \n", Object);
  29. DbgBreakPoint ();
  30. }
  31. }
  32. }
  33. //
  34. // Handle management
  35. //
  36. LIST_ENTRY HandleList;
  37. RTL_CRITICAL_SECTION HandleLock;
  38. ULONG HandleBreakOnDelayed = 1;
  39. VOID
  40. HandleInitialize (
  41. )
  42. {
  43. InitializeListHead (&HandleList);
  44. RtlInitializeCriticalSection (&HandleLock);
  45. }
  46. PAVRF_HANDLE
  47. HandleFind (
  48. HANDLE Handle
  49. )
  50. {
  51. PLIST_ENTRY Current;
  52. PAVRF_HANDLE Entry;
  53. RtlEnterCriticalSection (&HandleLock);
  54. Current = HandleList.Flink;
  55. while (Current != &HandleList) {
  56. Entry = CONTAINING_RECORD (Current,
  57. AVRF_HANDLE,
  58. Links);
  59. Current = Current->Flink;
  60. if (Entry->Handle == Handle) {
  61. RtlLeaveCriticalSection (&HandleLock);
  62. return Entry;
  63. }
  64. }
  65. RtlLeaveCriticalSection (&HandleLock);
  66. return NULL;
  67. }
  68. PWSTR
  69. HandleName (
  70. PAVRF_HANDLE Handle
  71. )
  72. {
  73. if (Handle) {
  74. if (Handle->Name) {
  75. return Handle->Name;
  76. }
  77. else {
  78. if (Handle->Delayed) {
  79. return L"<noname:ntdll>";
  80. }
  81. else {
  82. return L"<noname>";
  83. }
  84. }
  85. }
  86. return L"<null>";
  87. }
  88. PAVRF_HANDLE
  89. HandleAdd (
  90. HANDLE Handle,
  91. ULONG Type,
  92. BOOLEAN Delayed,
  93. PWSTR Name,
  94. PVOID Context
  95. )
  96. {
  97. PLIST_ENTRY Current;
  98. PAVRF_HANDLE Entry;
  99. PWSTR NameCopy;
  100. ULONG Hash;
  101. if (HandleBreakOnDelayed && Delayed) {
  102. DbgPrint (" --- dumping ... %p \n", HandleList.Flink);
  103. HandleDump (NULL);
  104. DbgPrint ("AVRF: undetected handle \n");
  105. DbgBreakPoint ();
  106. }
  107. Entry = (PAVRF_HANDLE) RtlAllocateHeap (RtlProcessHeap(),
  108. 0,
  109. sizeof *Entry);
  110. if (Entry == NULL) {
  111. return NULL;
  112. }
  113. if (Name) {
  114. NameCopy = (PWSTR) RtlAllocateHeap (RtlProcessHeap(),
  115. 0,
  116. 2 * (wcslen(Name) + 1));
  117. if (NameCopy == NULL) {
  118. RtlFreeHeap (RtlProcessHeap(), 0, Entry);
  119. return NULL;
  120. }
  121. wcscpy (NameCopy, Name);
  122. }
  123. else {
  124. NameCopy = NULL;
  125. }
  126. RtlZeroMemory (Entry, sizeof *Entry);
  127. Entry->Handle = Handle;
  128. Entry->Type = Type;
  129. Entry->Delayed = Delayed ? 1 : 0;
  130. Entry->Context = Context;
  131. Entry->Name = NameCopy;
  132. RtlCaptureStackBackTrace (2,
  133. MAX_TRACE_DEPTH,
  134. Entry->Trace,
  135. &Hash);
  136. RtlEnterCriticalSection (&HandleLock);
  137. InsertHeadList (&HandleList,
  138. &(Entry->Links));
  139. RtlLeaveCriticalSection (&HandleLock);
  140. return Entry;
  141. }
  142. VOID
  143. HandleDelete (
  144. HANDLE Handle,
  145. PAVRF_HANDLE Entry
  146. )
  147. {
  148. RtlEnterCriticalSection (&HandleLock);
  149. RemoveEntryList (&(Entry->Links));
  150. RtlLeaveCriticalSection (&HandleLock);
  151. if (Entry->Name) {
  152. RtlFreeHeap (RtlProcessHeap(), 0, Entry->Name);
  153. }
  154. RtlFreeHeap (RtlProcessHeap(), 0, Entry);
  155. }
  156. VOID
  157. HandleDump (
  158. HANDLE Handle
  159. )
  160. {
  161. PLIST_ENTRY Current;
  162. PAVRF_HANDLE Entry;
  163. RtlEnterCriticalSection (&HandleLock);
  164. Current = HandleList.Flink;
  165. while (Current != &HandleList) {
  166. Entry = CONTAINING_RECORD (Current,
  167. AVRF_HANDLE,
  168. Links);
  169. Current = Current->Flink;
  170. if (Handle == NULL || Entry->Handle == Handle) {
  171. DbgPrint ("HNDL: %08X %04u `%ws' \n",
  172. HandleToUlong(Entry->Handle),
  173. Entry->Type,
  174. HandleName(Entry));
  175. }
  176. }
  177. RtlLeaveCriticalSection (&HandleLock);
  178. }
  179. //
  180. // Virtual space operations tracking.
  181. //
  182. typedef struct _VS_CALL {
  183. struct {
  184. ULONG Type : 4;
  185. ULONG Trace : 16;
  186. ULONG Thread : 12;
  187. };
  188. PVOID Address;
  189. SIZE_T Size;
  190. ULONG Operation;
  191. ULONG Protection;
  192. } VS_CALL, *PVS_CALL;
  193. #define NO_OF_VS_CALLS 8192
  194. VS_CALL VsCalls [NO_OF_VS_CALLS];
  195. LONG VsCallsIndex;
  196. VOID
  197. VsLogCall (
  198. VS_CALL_TYPE Type,
  199. PVOID Address,
  200. SIZE_T Size,
  201. ULONG Operation,
  202. ULONG Protection
  203. )
  204. {
  205. ULONG Index;
  206. ULONG Hash;
  207. Index = (ULONG)InterlockedIncrement (&VsCallsIndex);
  208. Index %= NO_OF_VS_CALLS;
  209. //RtlZeroMemory (&(VsCalls[Index]), sizeof (VS_CALL));
  210. VsCalls[Index].Address = Address;
  211. VsCalls[Index].Type = Type;
  212. VsCalls[Index].Trace = RtlLogStackBackTrace();
  213. VsCalls[Index].Thread = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
  214. VsCalls[Index].Size = Size;
  215. VsCalls[Index].Operation = Operation;
  216. VsCalls[Index].Protection = Protection;
  217. if (AVrfpProvider.VerifierDebug) {
  218. DbgPrint ("AVRF:VS: %01u (%04X): %p %p %X %X \n",
  219. Type,
  220. (ULONG)(VsCalls[Index].Trace),
  221. Address, Size, Operation, Protection);
  222. }
  223. }
  224. //
  225. // Heap operations tracking
  226. //
  227. typedef struct _HEAP_CALL {
  228. struct {
  229. ULONG Reserved : 4;
  230. ULONG Trace : 16;
  231. ULONG Thread : 12;
  232. };
  233. PVOID Address;
  234. SIZE_T Size;
  235. } HEAP_CALL, *PHEAP_CALL;
  236. #define NO_OF_HEAP_CALLS 8192
  237. HEAP_CALL HeapCalls [NO_OF_HEAP_CALLS];
  238. LONG HeapCallsIndex;
  239. VOID
  240. HeapLogCall (
  241. PVOID Address,
  242. SIZE_T Size
  243. )
  244. {
  245. ULONG Index;
  246. ULONG Hash;
  247. Index = (ULONG)InterlockedIncrement (&HeapCallsIndex);
  248. Index %= NO_OF_HEAP_CALLS;
  249. //RtlZeroMemory (&(HeapCalls[Index]), sizeof (HEAP_CALL));
  250. HeapCalls[Index].Address = Address;
  251. HeapCalls[Index].Trace = RtlLogStackBackTrace();
  252. HeapCalls[Index].Thread = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
  253. HeapCalls[Index].Size = Size;
  254. if (AVrfpProvider.VerifierDebug) {
  255. DbgPrint ("AVRF:HEAP: %04X (%04X): %p %p \n",
  256. (ULONG)(HeapCalls[Index].Thread),
  257. (ULONG)(HeapCalls[Index].Trace),
  258. Address, Size);
  259. }
  260. }
  261. VOID
  262. AVrfpDirtyThreadStack (
  263. )
  264. {
  265. PTEB Teb = NtCurrentTeb();
  266. ULONG_PTR StackStart;
  267. ULONG_PTR StackEnd;
  268. try {
  269. StackStart = (ULONG_PTR)(Teb->NtTib.StackLimit);
  270. //
  271. // ISSUE: SilviuC: we should dirty stacks on all architectures
  272. //
  273. #if defined(_X86_)
  274. _asm mov StackEnd, ESP;
  275. #else
  276. StackEnd = StackStart;
  277. #endif
  278. //
  279. // Limit stack dirtying to only 8K.
  280. //
  281. if (StackStart < StackEnd - 0x2000) {
  282. StackStart = StackEnd - 0x2000;
  283. }
  284. if (AVrfpProvider.VerifierDebug) {
  285. DbgPrint ("Dirtying stack range %p - %p for thread %p \n",
  286. StackStart, StackEnd, Teb->ClientId.UniqueThread);
  287. }
  288. while (StackStart < StackEnd) {
  289. *((PULONG)StackStart) = 0xBAD1BAD1;
  290. StackStart += sizeof(ULONG);
  291. }
  292. }
  293. except (EXCEPTION_EXECUTE_HANDLER) {
  294. // nothing
  295. }
  296. }
  297. //
  298. // Standard function used for hooked CreateThread.
  299. //
  300. ULONG
  301. AVrfpThreadFunctionExceptionFilter (
  302. ULONG ExceptionCode,
  303. PVOID ExceptionRecord
  304. )
  305. {
  306. VERIFIER_STOP (APPLICATION_VERIFIER_UNEXPECTED_EXCEPTION,
  307. "unexpected exception raised in thread function",
  308. ExceptionCode, "Exception code",
  309. ExceptionRecord, "Exception record (.exr on 1st word, .cxr on 2nd word)",
  310. 0, "",
  311. 0, "");
  312. return EXCEPTION_EXECUTE_HANDLER;
  313. }
  314. DWORD
  315. WINAPI
  316. AVrfpStandardThreadFunction (
  317. LPVOID Context
  318. )
  319. {
  320. PAVRF_THREAD_INFO Info = (PAVRF_THREAD_INFO)Context;
  321. DWORD Result;
  322. try {
  323. //
  324. // Call the real thing.
  325. //
  326. Result = (Info->Function)(Info->Parameter);
  327. }
  328. except (AVrfpThreadFunctionExceptionFilter (_exception_code(), _exception_info())) {
  329. //
  330. // Nothing.
  331. //
  332. }
  333. //
  334. // Perform all typical checks for a thread that has just finished.
  335. //
  336. RtlCheckForOrphanedCriticalSections (NtCurrentThread());
  337. AVrfpCheckThreadTermination ();
  338. RtlFreeHeap (RtlProcessHeap(), 0, Info);
  339. return Result;
  340. }
  341. VOID
  342. AVrfpCheckThreadTermination (
  343. VOID
  344. )
  345. {
  346. //
  347. // Nothing yet.
  348. //
  349. }