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.

616 lines
16 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. vfgeneric.c
  5. Abstract:
  6. This module handles generic Irp verification.
  7. Author:
  8. Adrian J. Oney (adriao) 20-Apr-1998
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. AdriaO 06/15/2000 - Seperated out from ntos\io\flunkirp.c
  13. --*/
  14. #include "vfdef.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(INIT, VfGenericInit)
  17. #pragma alloc_text(PAGEVRFY, VfGenericDumpIrpStack)
  18. #pragma alloc_text(PAGEVRFY, VfGenericVerifyNewRequest)
  19. #pragma alloc_text(PAGEVRFY, VfGenericVerifyIrpStackDownward)
  20. #pragma alloc_text(PAGEVRFY, VfGenericVerifyIrpStackUpward)
  21. #pragma alloc_text(PAGEVRFY, VfGenericIsValidIrpStatus)
  22. #pragma alloc_text(PAGEVRFY, VfGenericIsNewRequest)
  23. #pragma alloc_text(PAGEVRFY, VfGenericVerifyNewIrp)
  24. #pragma alloc_text(PAGEVRFY, VfGenericVerifyFinalIrpStack)
  25. #endif
  26. #ifdef ALLOC_DATA_PRAGMA
  27. #pragma const_seg("PAGEVRFC")
  28. #endif
  29. const PCHAR IrpMajorNames[] = {
  30. "IRP_MJ_CREATE", // 0x00
  31. "IRP_MJ_CREATE_NAMED_PIPE", // 0x01
  32. "IRP_MJ_CLOSE", // 0x02
  33. "IRP_MJ_READ", // 0x03
  34. "IRP_MJ_WRITE", // 0x04
  35. "IRP_MJ_QUERY_INFORMATION", // 0x05
  36. "IRP_MJ_SET_INFORMATION", // 0x06
  37. "IRP_MJ_QUERY_EA", // 0x07
  38. "IRP_MJ_SET_EA", // 0x08
  39. "IRP_MJ_FLUSH_BUFFERS", // 0x09
  40. "IRP_MJ_QUERY_VOLUME_INFORMATION", // 0x0a
  41. "IRP_MJ_SET_VOLUME_INFORMATION", // 0x0b
  42. "IRP_MJ_DIRECTORY_CONTROL", // 0x0c
  43. "IRP_MJ_FILE_SYSTEM_CONTROL", // 0x0d
  44. "IRP_MJ_DEVICE_CONTROL", // 0x0e
  45. "IRP_MJ_INTERNAL_DEVICE_CONTROL", // 0x0f
  46. "IRP_MJ_SHUTDOWN", // 0x10
  47. "IRP_MJ_LOCK_CONTROL", // 0x11
  48. "IRP_MJ_CLEANUP", // 0x12
  49. "IRP_MJ_CREATE_MAILSLOT", // 0x13
  50. "IRP_MJ_QUERY_SECURITY", // 0x14
  51. "IRP_MJ_SET_SECURITY", // 0x15
  52. "IRP_MJ_POWER", // 0x16
  53. "IRP_MJ_SYSTEM_CONTROL", // 0x17
  54. "IRP_MJ_DEVICE_CHANGE", // 0x18
  55. "IRP_MJ_QUERY_QUOTA", // 0x19
  56. "IRP_MJ_SET_QUOTA", // 0x1a
  57. "IRP_MJ_PNP", // 0x1b
  58. NULL
  59. };
  60. #define MAX_NAMED_MAJOR_IRPS 0x1b
  61. #ifdef ALLOC_DATA_PRAGMA
  62. #pragma const_seg()
  63. #endif // ALLOC_DATA_PRAGMA
  64. VOID
  65. VfGenericInit(
  66. VOID
  67. )
  68. {
  69. VfMajorRegisterHandlers(
  70. IRP_MJ_ALL_MAJORS,
  71. VfGenericDumpIrpStack,
  72. VfGenericVerifyNewRequest,
  73. VfGenericVerifyIrpStackDownward,
  74. VfGenericVerifyIrpStackUpward,
  75. NULL,
  76. NULL,
  77. VfGenericIsValidIrpStatus,
  78. VfGenericIsNewRequest,
  79. VfGenericVerifyNewIrp,
  80. VfGenericVerifyFinalIrpStack,
  81. NULL
  82. );
  83. }
  84. VOID
  85. FASTCALL
  86. VfGenericDumpIrpStack(
  87. IN PIO_STACK_LOCATION IrpSp
  88. )
  89. {
  90. if ((IrpSp->MajorFunction==IRP_MJ_INTERNAL_DEVICE_CONTROL)&&(IrpSp->MinorFunction == IRP_MN_SCSI_CLASS)) {
  91. DbgPrint("IRP_MJ_SCSI");
  92. } else if (IrpSp->MajorFunction<=MAX_NAMED_MAJOR_IRPS) {
  93. DbgPrint(IrpMajorNames[IrpSp->MajorFunction]);
  94. } else if (IrpSp->MajorFunction==0xFF) {
  95. DbgPrint("IRP_MJ_BOGUS");
  96. } else {
  97. DbgPrint("IRP_MJ_??");
  98. }
  99. }
  100. VOID
  101. FASTCALL
  102. VfGenericVerifyNewRequest(
  103. IN PIOV_REQUEST_PACKET IovPacket,
  104. IN PDEVICE_OBJECT DeviceObject,
  105. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  106. IN PIO_STACK_LOCATION IrpSp,
  107. IN PIOV_STACK_LOCATION StackLocationData,
  108. IN PVOID CallerAddress OPTIONAL
  109. )
  110. {
  111. UNREFERENCED_PARAMETER (DeviceObject);
  112. UNREFERENCED_PARAMETER (IrpLastSp);
  113. UNREFERENCED_PARAMETER (StackLocationData);
  114. if (!VfSettingsIsOptionEnabled(IovPacket->VerifierSettings, VERIFIER_OPTION_PROTECT_RESERVED_IRPS)) {
  115. return;
  116. }
  117. if ((IovPacket->Flags&TRACKFLAG_IO_ALLOCATED)&&
  118. (!(IovPacket->Flags&TRACKFLAG_WATERMARKED))) {
  119. if (VfMajorIsSystemRestrictedIrp(IrpSp)) {
  120. //
  121. // We've caught somebody initiating an IRP they shouldn't be sending!
  122. //
  123. WDM_FAIL_ROUTINE((
  124. DCERROR_RESTRICTED_IRP,
  125. DCPARAM_IRP + DCPARAM_ROUTINE,
  126. CallerAddress,
  127. IovPacket->TrackedIrp
  128. ));
  129. }
  130. }
  131. }
  132. VOID
  133. FASTCALL
  134. VfGenericVerifyIrpStackDownward(
  135. IN PIOV_REQUEST_PACKET IovPacket,
  136. IN PDEVICE_OBJECT DeviceObject,
  137. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  138. IN PIO_STACK_LOCATION IrpSp,
  139. IN PIOV_STACK_LOCATION RequestHeadLocationData,
  140. IN PIOV_STACK_LOCATION StackLocationData,
  141. IN PVOID CallerAddress OPTIONAL
  142. )
  143. {
  144. PIRP irp = IovPacket->TrackedIrp;
  145. NTSTATUS currentStatus, lastStatus;
  146. BOOLEAN newRequest, statusChanged, infoChanged, firstRequest;
  147. PIOV_SESSION_DATA iovSessionData;
  148. UNREFERENCED_PARAMETER (DeviceObject);
  149. UNREFERENCED_PARAMETER (StackLocationData);
  150. currentStatus = irp->IoStatus.Status;
  151. lastStatus = RequestHeadLocationData->LastStatusBlock.Status;
  152. statusChanged = (BOOLEAN)(currentStatus != lastStatus);
  153. infoChanged = (BOOLEAN)(irp->IoStatus.Information != RequestHeadLocationData->LastStatusBlock.Information);
  154. firstRequest = (BOOLEAN)((RequestHeadLocationData->Flags&STACKFLAG_FIRST_REQUEST) != 0);
  155. iovSessionData = VfPacketGetCurrentSessionData(IovPacket);
  156. //
  157. // Do we have a "new" function to process?
  158. //
  159. newRequest = VfMajorIsNewRequest(IrpLastSp, IrpSp);
  160. //
  161. // Verify IRQL's are legal
  162. //
  163. switch(IrpSp->MajorFunction) {
  164. case IRP_MJ_POWER:
  165. case IRP_MJ_READ:
  166. case IRP_MJ_WRITE:
  167. case IRP_MJ_DEVICE_CONTROL:
  168. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  169. break;
  170. default:
  171. if (iovSessionData->ForwardMethod != FORWARDED_TO_NEXT_DO) {
  172. break;
  173. }
  174. if ((IovPacket->DepartureIrql >= DISPATCH_LEVEL) &&
  175. (!(IovPacket->Flags & TRACKFLAG_PASSED_AT_BAD_IRQL))) {
  176. WDM_FAIL_ROUTINE((
  177. DCERROR_DISPATCH_CALLED_AT_BAD_IRQL,
  178. DCPARAM_IRP + DCPARAM_ROUTINE,
  179. CallerAddress,
  180. irp
  181. ));
  182. IovPacket->Flags |= TRACKFLAG_PASSED_AT_BAD_IRQL;
  183. }
  184. }
  185. //
  186. // The following is only executed if we are not a new IRP...
  187. //
  188. if (IrpLastSp == NULL) {
  189. return;
  190. }
  191. //
  192. // Let's verify bogus IRPs haven't been touched...
  193. //
  194. if ((IovPacket->Flags&TRACKFLAG_BOGUS) &&
  195. (!(RequestHeadLocationData->Flags&STACKFLAG_BOGUS_IRP_TOUCHED))) {
  196. if (newRequest && (!firstRequest)) {
  197. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  198. WDM_FAIL_ROUTINE((
  199. DCERROR_BOGUS_FUNC_TRASHED,
  200. DCPARAM_IRP + DCPARAM_ROUTINE,
  201. CallerAddress,
  202. irp
  203. ));
  204. }
  205. if (statusChanged) {
  206. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  207. if (IrpSp->MinorFunction == 0xFF) {
  208. WDM_FAIL_ROUTINE((
  209. DCERROR_BOGUS_MINOR_STATUS_TRASHED,
  210. DCPARAM_IRP + DCPARAM_ROUTINE,
  211. CallerAddress,
  212. irp
  213. ));
  214. } else {
  215. WDM_FAIL_ROUTINE((
  216. DCERROR_BOGUS_STATUS_TRASHED,
  217. DCPARAM_IRP + DCPARAM_ROUTINE,
  218. CallerAddress,
  219. irp
  220. ));
  221. }
  222. }
  223. if (infoChanged) {
  224. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  225. WDM_FAIL_ROUTINE((
  226. DCERROR_BOGUS_INFO_TRASHED,
  227. DCPARAM_IRP + DCPARAM_ROUTINE,
  228. CallerAddress,
  229. irp
  230. ));
  231. }
  232. }
  233. if (!VfMajorIsValidIrpStatus(IrpSp, currentStatus)) {
  234. WDM_FAIL_ROUTINE((
  235. DCERROR_INVALID_STATUS,
  236. DCPARAM_IRP + DCPARAM_ROUTINE,
  237. CallerAddress,
  238. irp
  239. ));
  240. }
  241. }
  242. VOID
  243. FASTCALL
  244. VfGenericVerifyIrpStackUpward(
  245. IN PIOV_REQUEST_PACKET IovPacket,
  246. IN PIO_STACK_LOCATION IrpSp,
  247. IN PIOV_STACK_LOCATION RequestHeadLocationData,
  248. IN PIOV_STACK_LOCATION StackLocationData,
  249. IN BOOLEAN IsNewlyCompleted,
  250. IN BOOLEAN RequestFinalized
  251. )
  252. {
  253. PIRP irp;
  254. NTSTATUS currentStatus;
  255. BOOLEAN statusChanged, infoChanged;
  256. PVOID routine;
  257. UNREFERENCED_PARAMETER (IsNewlyCompleted);
  258. UNREFERENCED_PARAMETER (RequestFinalized);
  259. irp = IovPacket->TrackedIrp;
  260. currentStatus = irp->IoStatus.Status;
  261. //
  262. // Who'd we call for this one?
  263. //
  264. routine = StackLocationData->LastDispatch;
  265. ASSERT(routine) ;
  266. //
  267. // Did they touch something stupid?
  268. //
  269. if ((IovPacket->Flags&TRACKFLAG_BOGUS) &&
  270. (!(RequestHeadLocationData->Flags&STACKFLAG_BOGUS_IRP_TOUCHED))) {
  271. statusChanged = (BOOLEAN)(currentStatus != RequestHeadLocationData->LastStatusBlock.Status);
  272. if (statusChanged) {
  273. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  274. if (IrpSp->MinorFunction == 0xFF) {
  275. WDM_FAIL_ROUTINE((
  276. DCERROR_BOGUS_MINOR_STATUS_TRASHED,
  277. DCPARAM_IRP + DCPARAM_ROUTINE,
  278. routine,
  279. irp
  280. ));
  281. } else {
  282. WDM_FAIL_ROUTINE((
  283. DCERROR_BOGUS_STATUS_TRASHED,
  284. DCPARAM_IRP + DCPARAM_ROUTINE,
  285. routine,
  286. irp
  287. ));
  288. }
  289. }
  290. infoChanged = (BOOLEAN)(irp->IoStatus.Information != RequestHeadLocationData->LastStatusBlock.Information);
  291. if (infoChanged) {
  292. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  293. WDM_FAIL_ROUTINE((
  294. DCERROR_BOGUS_INFO_TRASHED,
  295. DCPARAM_IRP + DCPARAM_ROUTINE,
  296. routine,
  297. irp
  298. ));
  299. }
  300. }
  301. if (!VfMajorIsValidIrpStatus(IrpSp, currentStatus)) {
  302. WDM_FAIL_ROUTINE(
  303. (DCERROR_INVALID_STATUS, DCPARAM_IRP + DCPARAM_ROUTINE, routine, irp)
  304. );
  305. }
  306. //
  307. // Check for leaked Cancel routines.
  308. //
  309. if (irp->CancelRoutine) {
  310. if (VfSettingsIsOptionEnabled(IovPacket->VerifierSettings, VERIFIER_OPTION_VERIFY_CANCEL_LOGIC)) {
  311. WDM_FAIL_ROUTINE((
  312. DCERROR_CANCELROUTINE_AFTER_COMPLETION,
  313. DCPARAM_IRP + DCPARAM_ROUTINE,
  314. routine,
  315. irp
  316. ));
  317. }
  318. }
  319. }
  320. BOOLEAN
  321. FASTCALL
  322. VfGenericIsValidIrpStatus(
  323. IN PIO_STACK_LOCATION IrpSp,
  324. IN NTSTATUS Status
  325. )
  326. /*++
  327. Description:
  328. As per the title, this function determines whether an IRP status is
  329. valid or probably random trash. See NTStatus.h for info on how status
  330. codes break down...
  331. Returns:
  332. TRUE iff IRP status looks to be valid. FALSE otherwise.
  333. --*/
  334. {
  335. ULONG severity;
  336. ULONG customer;
  337. ULONG reserved;
  338. ULONG facility;
  339. ULONG code;
  340. ULONG lanManClass;
  341. UNREFERENCED_PARAMETER (IrpSp);
  342. severity = (((ULONG)Status) >> 30)&3;
  343. customer = (((ULONG)Status) >> 29)&1;
  344. reserved = (((ULONG)Status) >> 28)&1;
  345. facility = (((ULONG)Status) >> 16)&0xFFF;
  346. code = (((ULONG)Status) & 0xFFFF);
  347. //
  348. // If reserved set, definitely bogus...
  349. //
  350. if (reserved) {
  351. return FALSE;
  352. }
  353. //
  354. // Is this a microsoft defined return code? If not, do no checking.
  355. //
  356. if (customer) {
  357. return TRUE;
  358. }
  359. //
  360. // ADRIAO N.B. 10/04/1999 -
  361. // The current methodology for doling out error codes appears to be
  362. // fairly chaotic. The primary kernel mode status codes are defined in
  363. // ntstatus.h. However, rtl\generr.c should also be consulted to see which
  364. // error codes can bubble up to user mode. Many OLE error codes from
  365. // winerror.h are now being used within the kernel itself.
  366. //
  367. if (facility < 0x20) {
  368. //
  369. // Facilities under 20 are currently legal.
  370. //
  371. switch(severity) {
  372. case STATUS_SEVERITY_SUCCESS: return (BOOLEAN)(code < 0x200);
  373. case STATUS_SEVERITY_INFORMATIONAL:
  374. //
  375. // ADRIAO N.B. 06/27/2000
  376. // This test could be tighter (a little over 0x50)
  377. //
  378. return (BOOLEAN)(code < 0x400);
  379. case STATUS_SEVERITY_WARNING: return (BOOLEAN)(code < 0x400);
  380. case STATUS_SEVERITY_ERROR: break;
  381. }
  382. //
  383. // Why the heck does WOW use such an odd error code?
  384. //
  385. return (BOOLEAN)((code < 0x400)||(code == 0x9898));
  386. } else if (facility == 0x98) {
  387. //
  388. // This is the lan manager service. In the case on Lan Man, the code
  389. // field is further subdivided into a class field.
  390. //
  391. lanManClass = code >> 12;
  392. code &= 0xFFF;
  393. //
  394. // Do no testing here.
  395. //
  396. return TRUE;
  397. } else {
  398. //
  399. // Not known, probably bogus.
  400. //
  401. return FALSE;
  402. }
  403. }
  404. BOOLEAN
  405. FASTCALL
  406. VfGenericIsNewRequest(
  407. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  408. IN PIO_STACK_LOCATION IrpSp
  409. )
  410. /*++
  411. Description:
  412. Determines whether the two Irp stacks refer to the same "request",
  413. ie starting the same device, etc. This is used to detect whether an IRP
  414. has been simply forwarded or rather the IRP has been reused to initiate
  415. a new request.
  416. Arguments:
  417. The two IRP stacks to compare.
  418. N.B. - the device object is not currently part of those IRP stacks.
  419. Return Value:
  420. TRUE if the stacks represent the same request, FALSE otherwise.
  421. --*/
  422. {
  423. return (BOOLEAN)((IrpLastSp==NULL)||
  424. (IrpSp->MajorFunction != IrpLastSp->MajorFunction) ||
  425. (IrpSp->MinorFunction != IrpLastSp->MinorFunction));
  426. }
  427. VOID
  428. FASTCALL
  429. VfGenericVerifyNewIrp(
  430. IN PIOV_REQUEST_PACKET IovPacket,
  431. IN PIRP Irp,
  432. IN PIO_STACK_LOCATION IrpSp,
  433. IN PIOV_STACK_LOCATION StackLocationData,
  434. IN PVOID CallerAddress OPTIONAL
  435. )
  436. {
  437. LONG index;
  438. PIO_STACK_LOCATION irpSp;
  439. BOOLEAN queuesApc;
  440. UNREFERENCED_PARAMETER (IrpSp);
  441. UNREFERENCED_PARAMETER (StackLocationData);
  442. if (Irp->UserIosb || Irp->UserEvent) {
  443. //
  444. // We have an IRP with user buffer data. This kind of IRP must be
  445. // initiated at PASSIVE_LEVEL lest the APC that signals the event gets
  446. // held up by fast mutex.
  447. //
  448. queuesApc = (BOOLEAN)
  449. (!((Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION)) &&
  450. (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION))));
  451. if (queuesApc) {
  452. //
  453. // The caller may be using the UserIosb for storage, and may really
  454. // free the IRP in a completion routine. Look for one now.
  455. //
  456. irpSp = IoGetNextIrpStackLocation(Irp);
  457. for(index = Irp->CurrentLocation-1;
  458. index <= Irp->StackCount;
  459. index++) {
  460. if (irpSp->CompletionRoutine != NULL) {
  461. queuesApc = FALSE;
  462. break;
  463. }
  464. irpSp++;
  465. }
  466. }
  467. if (queuesApc && (IovPacket->DepartureIrql > PASSIVE_LEVEL)) {
  468. WDM_FAIL_ROUTINE((
  469. DCERROR_DISPATCH_CALLED_AT_BAD_IRQL,
  470. DCPARAM_IRP + DCPARAM_ROUTINE,
  471. CallerAddress,
  472. Irp
  473. ));
  474. }
  475. }
  476. }
  477. VOID
  478. FASTCALL
  479. VfGenericVerifyFinalIrpStack(
  480. IN PIOV_REQUEST_PACKET IovPacket,
  481. IN PIO_STACK_LOCATION IrpSp
  482. )
  483. {
  484. UNREFERENCED_PARAMETER (IovPacket);
  485. UNREFERENCED_PARAMETER (IrpSp);
  486. ASSERT(!IovPacket->RefTrackingCount);
  487. }