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.

732 lines
23 KiB

  1. /*++
  2. Copyright (c) 1992-1993 Microsoft Corporation
  3. Module Name:
  4. dbgctrl.c
  5. Abstract:
  6. This module implements the NtDebugControl service
  7. Author:
  8. Chuck Lenzmeier (chuckl) 2-Dec-1992
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "exp.h"
  14. #pragma hdrstop
  15. #include "kdp.h"
  16. #if defined(ALLOC_PRAGMA)
  17. #pragma alloc_text(PAGE, NtSystemDebugControl)
  18. #endif
  19. NTSTATUS
  20. NtSystemDebugControl (
  21. IN SYSDBG_COMMAND Command,
  22. IN PVOID InputBuffer,
  23. IN ULONG InputBufferLength,
  24. OUT PVOID OutputBuffer,
  25. IN ULONG OutputBufferLength,
  26. OUT PULONG ReturnLength OPTIONAL
  27. )
  28. /*++
  29. Routine Description:
  30. This function controls the system debugger.
  31. Arguments:
  32. Command - The command to be executed. One of the following:
  33. SysDbgQueryTraceInformation
  34. SysDbgSetTracepoint
  35. SysDbgSetSpecialCall
  36. SysDbgClearSpecialCalls
  37. SysDbgQuerySpecialCalls
  38. InputBuffer - A pointer to a buffer describing the input data for
  39. the request, if any. The structure of this buffer varies
  40. depending upon Command.
  41. InputBufferLength - The length in bytes of InputBuffer.
  42. OutputBuffer - A pointer to a buffer that is to receive the output
  43. data for the request, if any. The structure of this buffer
  44. varies depending upon Command.
  45. OutputBufferLength - The length in bytes of OutputBuffer.
  46. ReturnLength - A optional pointer to a ULONG that is to receive the
  47. output data length for the request.
  48. Return Value:
  49. Returns one of the following status codes:
  50. STATUS_SUCCESS - normal, successful completion.
  51. STATUS_INVALID_INFO_CLASS - The Command parameter did not
  52. specify a valid value.
  53. STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
  54. Parameters buffer was not correct.
  55. STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
  56. or a pointer within the Parameters buffer specified an
  57. invalid address.
  58. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  59. for this request to complete.
  60. --*/
  61. {
  62. NTSTATUS status = STATUS_SUCCESS;
  63. ULONG length = 0;
  64. KPROCESSOR_MODE PreviousMode;
  65. PVOID LockedBuffer = NULL;
  66. PVOID LockVariable = NULL;
  67. PreviousMode = KeGetPreviousMode();
  68. if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
  69. return STATUS_ACCESS_DENIED;
  70. }
  71. //
  72. // Operate within a try block in order to catch errors.
  73. //
  74. try {
  75. //
  76. // Probe input and output buffers, if previous mode is not
  77. // kernel.
  78. //
  79. if ( PreviousMode != KernelMode ) {
  80. if ( InputBufferLength != 0 ) {
  81. ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
  82. }
  83. if ( OutputBufferLength != 0 ) {
  84. ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
  85. }
  86. if ( ARGUMENT_PRESENT(ReturnLength) ) {
  87. ProbeForWriteUlong( ReturnLength );
  88. }
  89. }
  90. //
  91. // Switch on the command code.
  92. //
  93. switch ( Command ) {
  94. #if i386
  95. case SysDbgQueryTraceInformation:
  96. status = KdGetTraceInformation(
  97. OutputBuffer,
  98. OutputBufferLength,
  99. &length
  100. );
  101. break;
  102. case SysDbgSetTracepoint:
  103. if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
  104. return STATUS_INFO_LENGTH_MISMATCH;
  105. }
  106. KdSetInternalBreakpoint( InputBuffer );
  107. break;
  108. case SysDbgSetSpecialCall:
  109. if ( InputBufferLength != sizeof(PVOID) ) {
  110. return STATUS_INFO_LENGTH_MISMATCH;
  111. }
  112. KdSetSpecialCall( InputBuffer, NULL );
  113. break;
  114. case SysDbgClearSpecialCalls:
  115. KdClearSpecialCalls( );
  116. break;
  117. case SysDbgQuerySpecialCalls:
  118. status = KdQuerySpecialCalls(
  119. OutputBuffer,
  120. OutputBufferLength,
  121. &length
  122. );
  123. break;
  124. #endif
  125. case SysDbgBreakPoint:
  126. if (KdDebuggerEnabled) {
  127. DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
  128. } else {
  129. status = STATUS_UNSUCCESSFUL;
  130. }
  131. break;
  132. case SysDbgQueryVersion:
  133. if (OutputBufferLength != sizeof(DBGKD_GET_VERSION64)) {
  134. return STATUS_INFO_LENGTH_MISMATCH;
  135. }
  136. KdpSysGetVersion((PDBGKD_GET_VERSION64)OutputBuffer);
  137. status = STATUS_SUCCESS;
  138. break;
  139. case SysDbgReadVirtual:
  140. if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
  141. return STATUS_INFO_LENGTH_MISMATCH;
  142. }
  143. {
  144. SYSDBG_VIRTUAL Cmd;
  145. //
  146. // Capture the user information so a malicious app cannot
  147. // change it on us after we validate it.
  148. //
  149. Cmd = *(PSYSDBG_VIRTUAL)InputBuffer;
  150. if (Cmd.Request == 0) {
  151. status = STATUS_ACCESS_VIOLATION;
  152. break;
  153. }
  154. status = ExLockUserBuffer(Cmd.Buffer,
  155. Cmd.Request,
  156. PreviousMode,
  157. IoWriteAccess,
  158. &LockedBuffer,
  159. &LockVariable);
  160. if (!NT_SUCCESS(status)) {
  161. break;
  162. }
  163. status = KdpCopyMemoryChunks((ULONG_PTR)Cmd.Address,
  164. LockedBuffer,
  165. Cmd.Request,
  166. 0,
  167. 0,
  168. &length);
  169. }
  170. break;
  171. case SysDbgWriteVirtual:
  172. if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
  173. return STATUS_INFO_LENGTH_MISMATCH;
  174. }
  175. {
  176. SYSDBG_VIRTUAL Cmd;
  177. //
  178. // Capture the user information so a malicious app cannot
  179. // change it on us after we validate it.
  180. //
  181. Cmd = *(PSYSDBG_VIRTUAL)InputBuffer;
  182. if (Cmd.Request == 0) {
  183. status = STATUS_ACCESS_VIOLATION;
  184. break;
  185. }
  186. status = ExLockUserBuffer(Cmd.Buffer,
  187. Cmd.Request,
  188. PreviousMode,
  189. IoReadAccess,
  190. &LockedBuffer,
  191. &LockVariable);
  192. if (!NT_SUCCESS(status)) {
  193. break;
  194. }
  195. status = KdpCopyMemoryChunks((ULONG_PTR)Cmd.Address,
  196. LockedBuffer,
  197. Cmd.Request,
  198. 0,
  199. MMDBG_COPY_WRITE,
  200. &length);
  201. }
  202. break;
  203. case SysDbgReadPhysical:
  204. if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
  205. return STATUS_INFO_LENGTH_MISMATCH;
  206. }
  207. {
  208. SYSDBG_PHYSICAL Cmd;
  209. //
  210. // Capture the user information so a malicious app cannot
  211. // change it on us after we validate it.
  212. //
  213. Cmd = *(PSYSDBG_PHYSICAL)InputBuffer;
  214. if (Cmd.Request == 0) {
  215. status = STATUS_ACCESS_VIOLATION;
  216. break;
  217. }
  218. status = ExLockUserBuffer(Cmd.Buffer,
  219. Cmd.Request,
  220. PreviousMode,
  221. IoWriteAccess,
  222. &LockedBuffer,
  223. &LockVariable);
  224. if (!NT_SUCCESS(status)) {
  225. break;
  226. }
  227. status = KdpCopyMemoryChunks(Cmd.Address.QuadPart,
  228. LockedBuffer,
  229. Cmd.Request,
  230. 0,
  231. MMDBG_COPY_PHYSICAL,
  232. &length);
  233. }
  234. break;
  235. case SysDbgWritePhysical:
  236. if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
  237. return STATUS_INFO_LENGTH_MISMATCH;
  238. }
  239. {
  240. SYSDBG_PHYSICAL Cmd;
  241. //
  242. // Capture the user information so a malicious app cannot
  243. // change it on us after we validate it.
  244. //
  245. Cmd = *(PSYSDBG_PHYSICAL)InputBuffer;
  246. if (Cmd.Request == 0) {
  247. status = STATUS_ACCESS_VIOLATION;
  248. break;
  249. }
  250. status = ExLockUserBuffer(Cmd.Buffer,
  251. Cmd.Request,
  252. PreviousMode,
  253. IoReadAccess,
  254. &LockedBuffer,
  255. &LockVariable);
  256. if (!NT_SUCCESS(status)) {
  257. break;
  258. }
  259. status = KdpCopyMemoryChunks(Cmd.Address.QuadPart,
  260. LockedBuffer,
  261. Cmd.Request,
  262. 0,
  263. MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL,
  264. &length);
  265. }
  266. break;
  267. case SysDbgReadControlSpace:
  268. if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
  269. return STATUS_INFO_LENGTH_MISMATCH;
  270. }
  271. {
  272. SYSDBG_CONTROL_SPACE Cmd;
  273. //
  274. // Capture the user information so a malicious app cannot
  275. // change it on us after we validate it.
  276. //
  277. Cmd = *(PSYSDBG_CONTROL_SPACE)InputBuffer;
  278. if (Cmd.Request == 0) {
  279. status = STATUS_ACCESS_VIOLATION;
  280. break;
  281. }
  282. status = ExLockUserBuffer(Cmd.Buffer,
  283. Cmd.Request,
  284. PreviousMode,
  285. IoWriteAccess,
  286. &LockedBuffer,
  287. &LockVariable);
  288. if (!NT_SUCCESS(status)) {
  289. break;
  290. }
  291. status = KdpSysReadControlSpace(Cmd.Processor,
  292. Cmd.Address,
  293. LockedBuffer,
  294. Cmd.Request,
  295. &length);
  296. }
  297. break;
  298. case SysDbgWriteControlSpace:
  299. if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
  300. return STATUS_INFO_LENGTH_MISMATCH;
  301. }
  302. {
  303. SYSDBG_CONTROL_SPACE Cmd;
  304. //
  305. // Capture the user information so a malicious app cannot
  306. // change it on us after we validate it.
  307. //
  308. Cmd = *(PSYSDBG_CONTROL_SPACE)InputBuffer;
  309. if (Cmd.Request == 0) {
  310. status = STATUS_ACCESS_VIOLATION;
  311. break;
  312. }
  313. status = ExLockUserBuffer(Cmd.Buffer,
  314. Cmd.Request,
  315. PreviousMode,
  316. IoReadAccess,
  317. &LockedBuffer,
  318. &LockVariable);
  319. if (!NT_SUCCESS(status)) {
  320. break;
  321. }
  322. status = KdpSysWriteControlSpace(Cmd.Processor,
  323. Cmd.Address,
  324. LockedBuffer,
  325. Cmd.Request,
  326. &length);
  327. }
  328. break;
  329. case SysDbgReadIoSpace:
  330. if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
  331. return STATUS_INFO_LENGTH_MISMATCH;
  332. }
  333. {
  334. SYSDBG_IO_SPACE Cmd;
  335. //
  336. // Capture the user information so a malicious app cannot
  337. // change it on us after we validate it.
  338. //
  339. Cmd = *(PSYSDBG_IO_SPACE)InputBuffer;
  340. if (Cmd.Request == 0) {
  341. status = STATUS_ACCESS_VIOLATION;
  342. break;
  343. }
  344. status = ExLockUserBuffer(Cmd.Buffer,
  345. Cmd.Request,
  346. PreviousMode,
  347. IoWriteAccess,
  348. &LockedBuffer,
  349. &LockVariable);
  350. if (!NT_SUCCESS(status)) {
  351. break;
  352. }
  353. status = KdpSysReadIoSpace(Cmd.InterfaceType,
  354. Cmd.BusNumber,
  355. Cmd.AddressSpace,
  356. Cmd.Address,
  357. LockedBuffer,
  358. Cmd.Request,
  359. &length);
  360. }
  361. break;
  362. case SysDbgWriteIoSpace:
  363. if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
  364. return STATUS_INFO_LENGTH_MISMATCH;
  365. }
  366. {
  367. SYSDBG_IO_SPACE Cmd;
  368. //
  369. // Capture the user information so a malicious app cannot
  370. // change it on us after we validate it.
  371. //
  372. Cmd = *(PSYSDBG_IO_SPACE)InputBuffer;
  373. if (Cmd.Request == 0) {
  374. status = STATUS_ACCESS_VIOLATION;
  375. break;
  376. }
  377. status = ExLockUserBuffer(Cmd.Buffer,
  378. Cmd.Request,
  379. PreviousMode,
  380. IoReadAccess,
  381. &LockedBuffer,
  382. &LockVariable);
  383. if (!NT_SUCCESS(status)) {
  384. break;
  385. }
  386. status = KdpSysWriteIoSpace(Cmd.InterfaceType,
  387. Cmd.BusNumber,
  388. Cmd.AddressSpace,
  389. Cmd.Address,
  390. LockedBuffer,
  391. Cmd.Request,
  392. &length);
  393. }
  394. break;
  395. case SysDbgReadMsr:
  396. if (InputBufferLength != sizeof(SYSDBG_MSR)) {
  397. return STATUS_INFO_LENGTH_MISMATCH;
  398. }
  399. {
  400. PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
  401. status = KdpSysReadMsr(Cmd->Msr, &Cmd->Data);
  402. }
  403. break;
  404. case SysDbgWriteMsr:
  405. if (InputBufferLength != sizeof(SYSDBG_MSR)) {
  406. return STATUS_INFO_LENGTH_MISMATCH;
  407. }
  408. {
  409. PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
  410. status = KdpSysWriteMsr(Cmd->Msr, &Cmd->Data);
  411. }
  412. break;
  413. case SysDbgReadBusData:
  414. if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
  415. return STATUS_INFO_LENGTH_MISMATCH;
  416. }
  417. {
  418. SYSDBG_BUS_DATA Cmd;
  419. //
  420. // Capture the user information so a malicious app cannot
  421. // change it on us after we validate it.
  422. //
  423. Cmd = *(PSYSDBG_BUS_DATA)InputBuffer;
  424. if (Cmd.Request == 0) {
  425. status = STATUS_ACCESS_VIOLATION;
  426. break;
  427. }
  428. status = ExLockUserBuffer(Cmd.Buffer,
  429. Cmd.Request,
  430. PreviousMode,
  431. IoWriteAccess,
  432. &LockedBuffer,
  433. &LockVariable);
  434. if (!NT_SUCCESS(status)) {
  435. break;
  436. }
  437. status = KdpSysReadBusData(Cmd.BusDataType,
  438. Cmd.BusNumber,
  439. Cmd.SlotNumber,
  440. Cmd.Address,
  441. LockedBuffer,
  442. Cmd.Request,
  443. &length);
  444. }
  445. break;
  446. case SysDbgWriteBusData:
  447. if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
  448. return STATUS_INFO_LENGTH_MISMATCH;
  449. }
  450. {
  451. SYSDBG_BUS_DATA Cmd;
  452. //
  453. // Capture the user information so a malicious app cannot
  454. // change it on us after we validate it.
  455. //
  456. Cmd = *(PSYSDBG_BUS_DATA)InputBuffer;
  457. if (Cmd.Request == 0) {
  458. status = STATUS_ACCESS_VIOLATION;
  459. break;
  460. }
  461. status = ExLockUserBuffer(Cmd.Buffer,
  462. Cmd.Request,
  463. PreviousMode,
  464. IoReadAccess,
  465. &LockedBuffer,
  466. &LockVariable);
  467. if (!NT_SUCCESS(status)) {
  468. break;
  469. }
  470. status = KdpSysWriteBusData(Cmd.BusDataType,
  471. Cmd.BusNumber,
  472. Cmd.SlotNumber,
  473. Cmd.Address,
  474. LockedBuffer,
  475. Cmd.Request,
  476. &length);
  477. }
  478. break;
  479. case SysDbgCheckLowMemory:
  480. status = KdpSysCheckLowMemory(0);
  481. break;
  482. case SysDbgEnableKernelDebugger:
  483. status = KdEnableDebugger();
  484. break;
  485. case SysDbgDisableKernelDebugger:
  486. status = KdDisableDebugger();
  487. break;
  488. case SysDbgGetAutoKdEnable:
  489. if (OutputBufferLength != sizeof(BOOLEAN)) {
  490. return STATUS_INFO_LENGTH_MISMATCH;
  491. }
  492. *(PBOOLEAN)OutputBuffer = KdAutoEnableOnEvent;
  493. status = STATUS_SUCCESS;
  494. break;
  495. case SysDbgSetAutoKdEnable:
  496. if (InputBufferLength != sizeof(BOOLEAN)) {
  497. return STATUS_INFO_LENGTH_MISMATCH;
  498. }
  499. if (KdPitchDebugger) {
  500. status = STATUS_ACCESS_DENIED;
  501. } else {
  502. KdAutoEnableOnEvent = *(PBOOLEAN)InputBuffer;
  503. status = STATUS_SUCCESS;
  504. }
  505. break;
  506. case SysDbgGetPrintBufferSize:
  507. if (OutputBufferLength != sizeof(ULONG)) {
  508. return STATUS_INFO_LENGTH_MISMATCH;
  509. }
  510. if (KdPitchDebugger) {
  511. *(PULONG)OutputBuffer = 0;
  512. } else {
  513. *(PULONG)OutputBuffer = KdPrintBufferSize;
  514. }
  515. status = STATUS_SUCCESS;
  516. break;
  517. case SysDbgSetPrintBufferSize:
  518. if (InputBufferLength != sizeof(ULONG)) {
  519. return STATUS_INFO_LENGTH_MISMATCH;
  520. }
  521. status = KdSetDbgPrintBufferSize(*(PULONG)InputBuffer);
  522. break;
  523. case SysDbgGetKdUmExceptionEnable:
  524. if (OutputBufferLength != sizeof(BOOLEAN)) {
  525. return STATUS_INFO_LENGTH_MISMATCH;
  526. }
  527. // Reverse sense of flag from enable-um-exceptions
  528. // to ignore-um-exceptions.
  529. *(PBOOLEAN)OutputBuffer = KdIgnoreUmExceptions ? FALSE : TRUE;
  530. status = STATUS_SUCCESS;
  531. break;
  532. case SysDbgSetKdUmExceptionEnable:
  533. if (InputBufferLength != sizeof(BOOLEAN)) {
  534. return STATUS_INFO_LENGTH_MISMATCH;
  535. }
  536. if (KdPitchDebugger) {
  537. status = STATUS_ACCESS_DENIED;
  538. } else {
  539. // Reverse sense of flag from enable-um-exceptions
  540. // to ignore-um-exceptions.
  541. KdIgnoreUmExceptions = *(PBOOLEAN)InputBuffer ? FALSE : TRUE;
  542. status = STATUS_SUCCESS;
  543. }
  544. break;
  545. default:
  546. //
  547. // Invalid Command.
  548. //
  549. status = STATUS_INVALID_INFO_CLASS;
  550. }
  551. if ( ARGUMENT_PRESENT(ReturnLength) ) {
  552. *ReturnLength = length;
  553. }
  554. }
  555. except ( EXCEPTION_EXECUTE_HANDLER ) {
  556. status = GetExceptionCode();
  557. }
  558. if (LockedBuffer) {
  559. ExUnlockUserBuffer(LockVariable);
  560. }
  561. return status;
  562. } // NtSystemDebugControl