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

/*++
Copyright (c) 1992-1993 Microsoft Corporation
Module Name:
dbgctrl.c
Abstract:
This module implements the NtDebugControl service
Author:
Chuck Lenzmeier (chuckl) 2-Dec-1992
Environment:
Kernel mode only.
Revision History:
--*/
#include "exp.h"
#pragma hdrstop
#include "kdp.h"
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE, NtSystemDebugControl)
#endif
NTSTATUS
NtSystemDebugControl (
IN SYSDBG_COMMAND Command,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
OUT PULONG ReturnLength OPTIONAL
)
/*++
Routine Description:
This function controls the system debugger.
Arguments:
Command - The command to be executed. One of the following:
SysDbgQueryTraceInformation
SysDbgSetTracepoint
SysDbgSetSpecialCall
SysDbgClearSpecialCalls
SysDbgQuerySpecialCalls
InputBuffer - A pointer to a buffer describing the input data for
the request, if any. The structure of this buffer varies
depending upon Command.
InputBufferLength - The length in bytes of InputBuffer.
OutputBuffer - A pointer to a buffer that is to receive the output
data for the request, if any. The structure of this buffer
varies depending upon Command.
OutputBufferLength - The length in bytes of OutputBuffer.
ReturnLength - A optional pointer to a ULONG that is to receive the
output data length for the request.
Return Value:
Returns one of the following status codes:
STATUS_SUCCESS - normal, successful completion.
STATUS_INVALID_INFO_CLASS - The Command parameter did not
specify a valid value.
STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
Parameters buffer was not correct.
STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
or a pointer within the Parameters buffer specified an
invalid address.
STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
for this request to complete.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG length = 0;
KPROCESSOR_MODE PreviousMode;
PVOID LockedBuffer = NULL;
PVOID LockVariable = NULL;
PreviousMode = KeGetPreviousMode();
if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
return STATUS_ACCESS_DENIED;
}
//
// Operate within a try block in order to catch errors.
//
try {
//
// Probe input and output buffers, if previous mode is not
// kernel.
//
if ( PreviousMode != KernelMode ) {
if ( InputBufferLength != 0 ) {
ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
}
if ( OutputBufferLength != 0 ) {
ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
}
if ( ARGUMENT_PRESENT(ReturnLength) ) {
ProbeForWriteUlong( ReturnLength );
}
}
//
// Switch on the command code.
//
switch ( Command ) {
#if i386
case SysDbgQueryTraceInformation:
status = KdGetTraceInformation(
OutputBuffer,
OutputBufferLength,
&length
);
break;
case SysDbgSetTracepoint:
if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
KdSetInternalBreakpoint( InputBuffer );
break;
case SysDbgSetSpecialCall:
if ( InputBufferLength != sizeof(PVOID) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}
KdSetSpecialCall( InputBuffer, NULL );
break;
case SysDbgClearSpecialCalls:
KdClearSpecialCalls( );
break;
case SysDbgQuerySpecialCalls:
status = KdQuerySpecialCalls(
OutputBuffer,
OutputBufferLength,
&length
);
break;
#endif
case SysDbgBreakPoint:
if (KdDebuggerEnabled) {
DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
} else {
status = STATUS_UNSUCCESSFUL;
}
break;
case SysDbgQueryVersion:
if (OutputBufferLength != sizeof(DBGKD_GET_VERSION64)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
KdpSysGetVersion((PDBGKD_GET_VERSION64)OutputBuffer);
status = STATUS_SUCCESS;
break;
case SysDbgReadVirtual:
if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_VIRTUAL Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_VIRTUAL)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoWriteAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpCopyMemoryChunks((ULONG_PTR)Cmd.Address,
LockedBuffer,
Cmd.Request,
0,
0,
&length);
}
break;
case SysDbgWriteVirtual:
if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_VIRTUAL Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_VIRTUAL)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoReadAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpCopyMemoryChunks((ULONG_PTR)Cmd.Address,
LockedBuffer,
Cmd.Request,
0,
MMDBG_COPY_WRITE,
&length);
}
break;
case SysDbgReadPhysical:
if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_PHYSICAL Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_PHYSICAL)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoWriteAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpCopyMemoryChunks(Cmd.Address.QuadPart,
LockedBuffer,
Cmd.Request,
0,
MMDBG_COPY_PHYSICAL,
&length);
}
break;
case SysDbgWritePhysical:
if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_PHYSICAL Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_PHYSICAL)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoReadAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpCopyMemoryChunks(Cmd.Address.QuadPart,
LockedBuffer,
Cmd.Request,
0,
MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL,
&length);
}
break;
case SysDbgReadControlSpace:
if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_CONTROL_SPACE Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_CONTROL_SPACE)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoWriteAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpSysReadControlSpace(Cmd.Processor,
Cmd.Address,
LockedBuffer,
Cmd.Request,
&length);
}
break;
case SysDbgWriteControlSpace:
if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_CONTROL_SPACE Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_CONTROL_SPACE)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoReadAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpSysWriteControlSpace(Cmd.Processor,
Cmd.Address,
LockedBuffer,
Cmd.Request,
&length);
}
break;
case SysDbgReadIoSpace:
if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_IO_SPACE Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_IO_SPACE)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoWriteAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpSysReadIoSpace(Cmd.InterfaceType,
Cmd.BusNumber,
Cmd.AddressSpace,
Cmd.Address,
LockedBuffer,
Cmd.Request,
&length);
}
break;
case SysDbgWriteIoSpace:
if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_IO_SPACE Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_IO_SPACE)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoReadAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpSysWriteIoSpace(Cmd.InterfaceType,
Cmd.BusNumber,
Cmd.AddressSpace,
Cmd.Address,
LockedBuffer,
Cmd.Request,
&length);
}
break;
case SysDbgReadMsr:
if (InputBufferLength != sizeof(SYSDBG_MSR)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
status = KdpSysReadMsr(Cmd->Msr, &Cmd->Data);
}
break;
case SysDbgWriteMsr:
if (InputBufferLength != sizeof(SYSDBG_MSR)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
status = KdpSysWriteMsr(Cmd->Msr, &Cmd->Data);
}
break;
case SysDbgReadBusData:
if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_BUS_DATA Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_BUS_DATA)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoWriteAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpSysReadBusData(Cmd.BusDataType,
Cmd.BusNumber,
Cmd.SlotNumber,
Cmd.Address,
LockedBuffer,
Cmd.Request,
&length);
}
break;
case SysDbgWriteBusData:
if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
{
SYSDBG_BUS_DATA Cmd;
//
// Capture the user information so a malicious app cannot
// change it on us after we validate it.
//
Cmd = *(PSYSDBG_BUS_DATA)InputBuffer;
if (Cmd.Request == 0) {
status = STATUS_ACCESS_VIOLATION;
break;
}
status = ExLockUserBuffer(Cmd.Buffer,
Cmd.Request,
PreviousMode,
IoReadAccess,
&LockedBuffer,
&LockVariable);
if (!NT_SUCCESS(status)) {
break;
}
status = KdpSysWriteBusData(Cmd.BusDataType,
Cmd.BusNumber,
Cmd.SlotNumber,
Cmd.Address,
LockedBuffer,
Cmd.Request,
&length);
}
break;
case SysDbgCheckLowMemory:
status = KdpSysCheckLowMemory(0);
break;
case SysDbgEnableKernelDebugger:
status = KdEnableDebugger();
break;
case SysDbgDisableKernelDebugger:
status = KdDisableDebugger();
break;
case SysDbgGetAutoKdEnable:
if (OutputBufferLength != sizeof(BOOLEAN)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
*(PBOOLEAN)OutputBuffer = KdAutoEnableOnEvent;
status = STATUS_SUCCESS;
break;
case SysDbgSetAutoKdEnable:
if (InputBufferLength != sizeof(BOOLEAN)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
if (KdPitchDebugger) {
status = STATUS_ACCESS_DENIED;
} else {
KdAutoEnableOnEvent = *(PBOOLEAN)InputBuffer;
status = STATUS_SUCCESS;
}
break;
case SysDbgGetPrintBufferSize:
if (OutputBufferLength != sizeof(ULONG)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
if (KdPitchDebugger) {
*(PULONG)OutputBuffer = 0;
} else {
*(PULONG)OutputBuffer = KdPrintBufferSize;
}
status = STATUS_SUCCESS;
break;
case SysDbgSetPrintBufferSize:
if (InputBufferLength != sizeof(ULONG)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
status = KdSetDbgPrintBufferSize(*(PULONG)InputBuffer);
break;
case SysDbgGetKdUmExceptionEnable:
if (OutputBufferLength != sizeof(BOOLEAN)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
// Reverse sense of flag from enable-um-exceptions
// to ignore-um-exceptions.
*(PBOOLEAN)OutputBuffer = KdIgnoreUmExceptions ? FALSE : TRUE;
status = STATUS_SUCCESS;
break;
case SysDbgSetKdUmExceptionEnable:
if (InputBufferLength != sizeof(BOOLEAN)) {
return STATUS_INFO_LENGTH_MISMATCH;
}
if (KdPitchDebugger) {
status = STATUS_ACCESS_DENIED;
} else {
// Reverse sense of flag from enable-um-exceptions
// to ignore-um-exceptions.
KdIgnoreUmExceptions = *(PBOOLEAN)InputBuffer ? FALSE : TRUE;
status = STATUS_SUCCESS;
}
break;
default:
//
// Invalid Command.
//
status = STATUS_INVALID_INFO_CLASS;
}
if ( ARGUMENT_PRESENT(ReturnLength) ) {
*ReturnLength = length;
}
}
except ( EXCEPTION_EXECUTE_HANDLER ) {
status = GetExceptionCode();
}
if (LockedBuffer) {
ExUnlockUserBuffer(LockVariable);
}
return status;
} // NtSystemDebugControl