- Fix IN/OUT privileged instruction fault (we don't yet handle HLT/CLI/STI other prefixes but the framework is there).

- Enable back proper VMWARE detection.
- Fix namepointer setup in DbgkCreateThread.
- Skip the first entry when doing fake module load messages.
- Fix which handle count is read in DbgkCloseObject.
- Set the right flags for the debug event thread instead of random flags inside the debug event itself when parsing in DbgkpSetProcessDebugPort.
- Add debug event in the temporary list to be woken, if rundown couldn't be acquired.
- Properly validate continue statues allowed in NtDebugContinue.
- Properly support timeout in NtWaitForDebugEvent.
- Properly do backout in NtWaitForDebugEvent.
- Disable LPC debug messages accidentally enabled, and add a small hack to better find the cause of the LPC shutdown bug.

svn path=/trunk/; revision=25572
This commit is contained in:
Alex Ionescu 2007-01-21 22:43:32 +00:00
parent 285cc65a82
commit 05e22f2f64
8 changed files with 243 additions and 70 deletions

View file

@ -1010,7 +1010,7 @@ WinMain(HINSTANCE hInstance,
{
PVOID ExceptionHandler;
//int Version;
int Version;
WCHAR *lc;
hAppInstance = hInstance;
@ -1024,9 +1024,9 @@ WinMain(HINSTANCE hInstance,
return 1;
}
//if(!DetectVMware(&Version))
if(!DetectVMware(&Version))
{
//return 1;
return 1;
}
/* unregister the handler */

View file

@ -499,6 +499,7 @@ Author:
#define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_IN_PAGE_ERROR 0xC0000006
#define STATUS_GUARD_PAGE_VIOLATION 0x80000001
#define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096
#define STATUS_STACK_OVERFLOW 0xC00000FD
#define KI_EXCEPTION_ACCESS_VIOLATION 0x10000004
#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C

View file

@ -8,9 +8,6 @@
// Do NOT ask when it will be fixed.
// Failure to respect this will *ACHIEVE NOTHING*.
//
// Ke1:
// - Implement Privileged Instruction Handler in Umode GPF.
//
// Ex:
// - Use pushlocks for handle implementation.
//

View file

@ -238,15 +238,13 @@ DbgkCreateThread(PVOID StartAddress)
if (Teb)
{
/* Copy the system library name and link to it */
#if 0
wcsncpy(Teb->StaticUnicodeBuffer,
L"ntdll.dll",
sizeof(Teb->StaticUnicodeBuffer) / sizeof(WCHAR));
#endif
Teb->Tib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer;
/* Return it in the debug event as well */
LoadDll->NamePointer = Teb->Tib.ArbitraryUserPointer;
LoadDll->NamePointer = &Teb->Tib.ArbitraryUserPointer;
}
/* Get a handle */

View file

@ -221,13 +221,9 @@ DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message,
PsGetCurrentProcess()->CreateReported = TRUE;
/* Send the LPC command */
#if 0
Status = LpcRequestWaitReplyPort(Port,
(PPORT_MESSAGE)Message,
(PPORT_MESSAGE)&Buffer[0]);
#else
Status = STATUS_UNSUCCESSFUL;
#endif
/* Flush the instruction cache */
ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
@ -486,6 +482,15 @@ DbgkpPostFakeModuleMessages(IN PEPROCESS Process,
i = 0;
while ((NextEntry != ListHead) && (i < 500))
{
/* Skip the first entry */
if (!i)
{
/* Go to the next module */
NextEntry = NextEntry->Flink;
i++;
continue;
}
/* Get the entry */
LdrEntry = CONTAINING_RECORD(NextEntry,
LDR_DATA_TABLE_ENTRY,
@ -724,7 +729,7 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process,
/* Get the next thread */
ThisThread = PsGetNextProcessThread(Process, ThisThread);
OldThread = pLastThread;
} while(ThisThread);
} while (ThisThread);
/* Check the API status */
if (!NT_SUCCESS(Status))
@ -1075,7 +1080,7 @@ DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL,
OwnerProcess, DebugObject);
/* If this isn't the last handle, do nothing */
if (HandleCount > 1) return;
if (SystemHandleCount > 1) return;
/* Otherwise, lock the debug object */
ExAcquireFastMutex(&DebugObject->Mutex);
@ -1293,8 +1298,12 @@ ThreadScan:
/* Check if we couldn't acquire rundown for it */
if (DebugEvent->Flags & 0x10)
{
/* Set busy flag */
InterlockedOr((PLONG)&DebugEvent->Flags, 0x100);
/* Set the skip termination flag */
PspSetCrossThreadFlag(EventThread, CT_SKIP_CREATION_MSG_BIT);
/* Insert it into the temp list */
RemoveEntryList(&DebugEvent->EventList);
InsertTailList(&TempList, &DebugEvent->EventList);
}
else
{
@ -1312,15 +1321,15 @@ ThreadScan:
/* Clear the backout thread */
DebugEvent->BackoutThread = NULL;
/* Set flag */
InterlockedOr((PLONG)&DebugEvent->Flags, 0x80);
/* Set skip flag */
PspSetCrossThreadFlag(EventThread, CT_SKIP_CREATION_MSG_BIT);
}
}
else
{
/* FIXME: TODO */
DPRINT1("Unhandled dbgk path!\n");
KEBUGCHECK(0);
/* Insert it into the temp list */
RemoveEntryList(&DebugEvent->EventList);
InsertTailList(&TempList, &DebugEvent->EventList);
}
/* Check if the lock is held */
@ -1346,11 +1355,14 @@ ThreadScan:
if (LastThread) ObDereferenceObject(LastThread);
/* Loop our temporary list */
NextEntry = TempList.Flink;
while (NextEntry != &TempList)
while (!IsListEmpty(&TempList))
{
/* FIXME: TODO */
KEBUGCHECK(0);
/* Remove the event */
NextEntry = RemoveHeadList(&TempList);
DebugEvent = CONTAINING_RECORD (NextEntry, DEBUG_EVENT, EventList);
/* Wake it */
DbgkpWakeTarget(DebugEvent);
}
/* Check if we got here through success and mark the PEB, then return */
@ -1520,9 +1532,8 @@ NtDebugContinue(IN HANDLE DebugHandle,
/* Make sure that the status is valid */
if ((ContinueStatus != DBG_CONTINUE) &&
(ContinueStatus != DBG_EXCEPTION_HANDLED) &&
(ContinueStatus != DBG_EXCEPTION_NOT_HANDLED) &&
(ContinueStatus != DBG_REPLY_LATER) &&
(ContinueStatus != DBG_UNABLE_TO_PROVIDE_HANDLE) &&
(ContinueStatus != DBG_TERMINATE_THREAD) &&
(ContinueStatus != DBG_TERMINATE_PROCESS))
{
@ -1820,30 +1831,41 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
DBGUI_WAIT_STATE_CHANGE WaitStateChange;
NTSTATUS Status = STATUS_SUCCESS;
PDEBUG_EVENT DebugEvent, DebugEvent2;
PLIST_ENTRY ListHead, NextEntry;
PLIST_ENTRY ListHead, NextEntry, NextEntry2;
PAGED_CODE();
DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);
/* Clear the initial wait state change structure */
RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
/* Check if the call was from user mode */
if (PreviousMode != KernelMode)
{
/* Protect probe in SEH */
_SEH_TRY
{
/* Check if we came with a timeout */
if (Timeout)
{
/* Make a copy on the stack */
SafeTimeOut = ProbeForReadLargeInteger(Timeout);
Timeout = &SafeTimeOut;
/* Check if the call was from user mode */
if (PreviousMode != KernelMode)
{
/* Probe it */
ProbeForReadLargeInteger(Timeout);
}
/* Make a local copy */
SafeTimeOut = *Timeout;
Timeout = &SafeTimeOut;
/* Query the current time */
KeQuerySystemTime(&StartTime);
}
/* Check if the call was from user mode */
if (PreviousMode != KernelMode)
{
/* Probe the state change structure */
ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
}
}
_SEH_HANDLE
{
/* Get the exception code */
@ -1852,10 +1874,6 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
/* Query the current time */
KeQuerySystemTime(&StartTime);
}
/* Get the debug object */
Status = ObReferenceObjectByHandle(DebugHandle,
DEBUG_OBJECT_WAIT_STATE_CHANGE,
@ -1870,13 +1888,13 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
Thread = NULL;
/* Wait on the debug object given to us */
while (TRUE)
{
Status = KeWaitForSingleObject(DebugObject,
Executive,
PreviousMode,
Alertable,
Timeout);
while (TRUE)
{
if (!NT_SUCCESS(Status) ||
(Status == STATUS_TIMEOUT) ||
(Status == STATUS_ALERTED) ||
@ -1917,10 +1935,11 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
GotEvent = TRUE;
/* Loop the list internally */
while (&DebugEvent->EventList != NextEntry)
NextEntry2 = DebugObject->EventList.Flink;
while (NextEntry2 != NextEntry)
{
/* Get the debug event */
DebugEvent2 = CONTAINING_RECORD(NextEntry,
DebugEvent2 = CONTAINING_RECORD(NextEntry2,
DEBUG_EVENT,
EventList);
@ -1936,7 +1955,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
}
/* Move to the next entry */
NextEntry = NextEntry->Flink;
NextEntry2 = NextEntry2->Flink;
}
/* Check if we still have a valid event */
@ -1962,14 +1981,15 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
/* Set flag */
DebugEvent->Flags |= 1;
Status = STATUS_SUCCESS;
}
else
{
/* Unsignal the event */
DebugObject->EventsPresent.Header.SignalState = 0;
Status = STATUS_SUCCESS;
KeClearEvent(&DebugObject->EventsPresent);
}
/* Set success */
Status = STATUS_SUCCESS;
}
/* Release the mutex */
@ -1980,13 +2000,22 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
if (!GotEvent)
{
/* Check if we can wait again */
if (!SafeTimeOut.QuadPart)
if (SafeTimeOut.QuadPart < 0)
{
/* Query the new time */
KeQuerySystemTime(&NewTime);
/* Substract times */
/* FIXME: TODO */
SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
StartTime = NewTime;
/* Check if we've timed out */
if (SafeTimeOut.QuadPart > 0)
{
/* We have, break out of the loop */
Status = STATUS_TIMEOUT;
break;
}
}
}
else

View file

@ -93,6 +93,33 @@ _UnexpectedMsg:
_UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
_KiTrapPrefixTable:
.byte 0xF2 /* REP */
.byte 0xF3 /* REP INS/OUTS */
.byte 0x67 /* ADDR */
.byte 0xF0 /* LOCK */
.byte 0x66 /* OP */
.byte 0x2E /* SEG */
.byte 0x3E /* DS */
.byte 0x26 /* ES */
.byte 0x64 /* FS */
.byte 0x65 /* GS */
.byte 0x36 /* SS */
_KiTrapIoTable:
.byte 0xE4 /* IN */
.byte 0xE5 /* IN */
.byte 0xEC /* IN */
.byte 0xED /* IN */
.byte 0x6C /* INS */
.byte 0x6D /* INS */
.byte 0xE6 /* OUT */
.byte 0xE7 /* OUT */
.byte 0xEE /* OUT */
.byte 0xEF /* OUT */
.byte 0x6E /* OUTS */
.byte 0x6F /* OUTS */
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
.text
@ -1426,6 +1453,29 @@ _KiTrap12:
jmp _KiSystemFatalException
.endfunc
.func KiTrapExceptHandler
_KiTrapExceptHandler:
/* Setup SEH handler frame */
mov esp, [esp+8]
pop fs:[KPCR_EXCEPTION_LIST]
add esp, 4
pop ebp
/* Check if the fault came from user mode */
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jnz SetException
/* Kernel fault, bugcheck */
push ebp
push 0
push 0
push 0
push 0
push KMODE_EXCEPTION_NOT_HANDLED
call _KeBugCheckWithTf@24
.endfunc
.func KiTrap13
Dr_kitd: DR_TRAP_FIXUP
V86_kitd: V86_TRAP_FIXUP
@ -1630,6 +1680,7 @@ SegPopGpf:
lea eax, [ebp+KTRAP_FRAME_ESP]
cmp edx, eax
jz HandleSegPop
int 3
/* Handle segment POP fault by setting it to 0 */
HandleSegPop:
@ -1668,7 +1719,7 @@ HandleSegPop2:
/* Update EIP (will be updated below again) */
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
HandleBop4:
HandleEsPop:
/* Clear the segment, update EIP and ESP */
mov dword ptr [edx], 0
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
@ -1680,15 +1731,23 @@ CheckVdmGpf:
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz CheckPrivilegedInstruction
/* Bring interrupts back */
sti
/* Check what kind of instruction this is */
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
/* FIXME: Check for BOP4 */
/* Check if this is POP FS */
/* Check if this is POP ES */
mov edx, ebp
add edx, KTRAP_FRAME_FS
add edx, KTRAP_FRAME_ES
cmp al, 0x07
jz HandleEsPop
/* Check if this is POP FS */
add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
cmp ax, 0xA10F
jz HandleSegPop2
@ -1698,16 +1757,102 @@ CheckVdmGpf:
jz HandleSegPop2
CheckPrivilegedInstruction:
/* Bring interrupts back */
sti
/* Setup a SEH handler */
push ebp
push offset _KiTrapExceptHandler
push fs:[KPCR_EXCEPTION_LIST]
mov fs:[KPCR_EXCEPTION_LIST], esp
/* Get EIP */
mov esi, [ebp+KTRAP_FRAME_EIP]
/* Setup loop count */
mov ecx, 15
InstLoop:
/* Save loop count */
push ecx
/* Get the instruction */
lods byte ptr [esi]
/* Now lookup in the prefix table */
mov ecx, 11
mov edi, offset _KiTrapPrefixTable
repnz scasb
/* Restore loop count */
pop ecx
/* If it's not a prefix byte, check other instructions */
jnz NotPrefixByte
/* FIXME */
UNHANDLED_PATH
NotPrefixByte:
/* FIXME: Check if it's a HLT */
/* Check if the instruction has two bytes */
cmp al, 0xF
jne CheckRing3Io
/* FIXME */
UNHANDLED_PATH
CheckRing3Io:
/* Get EFLAGS and IOPL */
mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
and ebx, 0x3000
shr ebx, 12
/* Check the CS's RPL mask */
mov ecx, [ebp+KTRAP_FRAME_CS]
and ecx, RPL_MASK
cmp ebx, ecx
jge NotIoViolation
CheckPrivilegedInstruction2:
/* FIXME */
UNHANDLED_PATH
/* Check if this is a CLI or STI */
cmp al, 0xFA
je IsPrivInstruction
cmp al, 0xFB
je IsPrivInstruction
/* Setup I/O table lookup */
mov ecx, 13
mov edi, offset _KiTrapIoTable
/* Loopup in the table */
repnz scasb
jnz NotIoViolation
/* FIXME: Check IOPM!!! */
IsPrivInstruction:
/* Cleanup the SEH frame */
pop fs:[KPCR_EXCEPTION_LIST]
add esp, 8
/* Setup the exception */
mov ebx, [ebp+KTRAP_FRAME_EIP]
mov eax, STATUS_PRIVILEGED_INSTRUCTION
jmp _DispatchNoParam
NotIoViolation:
/* Cleanup the SEH frame */
pop fs:[KPCR_EXCEPTION_LIST]
add esp, 8
SetException:
/* FIXME */
UNHANDLED_PATH
/* Setup the exception */
mov ebx, [ebp+KTRAP_FRAME_EIP]
mov esi, -1
mov eax, STATUS_ACCESS_VIOLATION
jmp _DispatchTwoParam
DispatchV86Gpf:
/* FIXME */

View file

@ -57,7 +57,7 @@ LpcpFreeToPortZone(IN PLPCP_MESSAGE Message,
PETHREAD Thread = NULL;
BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2;
PAGED_CODE();
LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags);
DPRINT1("Message: %p. Flags: %lx\n", Message, Flags);
/* Acquire the lock if not already */
if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
@ -342,6 +342,9 @@ LpcpDeletePort(IN PVOID ObjectBody)
/* Send it */
for (;;)
{
/* FIXME: HACK OF D00m */
break;
/* Send the message */
if (LpcRequestPort(Port,
&ClientDiedMsg.h) != STATUS_NO_MEMORY) break;

View file

@ -18,7 +18,7 @@ POBJECT_TYPE LpcPortObjectType;
ULONG LpcpMaxMessageSize;
PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
KGUARDED_MUTEX LpcpLock;
ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG;
ULONG LpcpTraceLevel = 0;
ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1;
static GENERIC_MAPPING LpcpPortMapping =