EXP [NTOS] Try to improve the situation about KiServiceExit things

Do not convert back from CONTEXT after DbgkForwardException, because that resets the breakpoint address in the trap frame to AT the int 3, which will cause an infinite loop of break points to happen (e.g. in ntdll_winetest info)
This commit is contained in:
Timo Kreuzer 2022-12-15 20:58:32 +01:00
parent 048db88043
commit d1517f9df3
2 changed files with 38 additions and 18 deletions

View file

@ -93,7 +93,7 @@ KeInitExceptions(VOID)
}
static
VOID
BOOLEAN
KiDispatchExceptionToUser(
IN PKTRAP_FRAME TrapFrame,
IN PCONTEXT Context,
@ -144,35 +144,35 @@ KiDispatchExceptionToUser(
EXCEPTION_EXECUTE_HANDLER)
{
// FIXME: handle stack overflow
//__debugbreak();
/* Nothing we can do here */
_disable();
_SEH2_YIELD(return);
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
/* Now set the two params for the user-mode dispatcher */
TrapFrame->Rcx = (ULONG64)&UserStack->ExceptionRecord;
TrapFrame->Rdx = (ULONG64)&UserStack->Context;
Context->Rcx = (ULONG64)&UserStack->ExceptionRecord;
Context->Rdx = (ULONG64)&UserStack->Context;
/* Set new Stack Pointer */
TrapFrame->Rsp = UserRsp;
Context->Rsp = UserRsp;
/* Force correct segments */
TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK;
TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK;
Context->SegCs = KGDT64_R3_CODE | RPL_MASK;
Context->SegDs = KGDT64_R3_DATA | RPL_MASK;
Context->SegEs = KGDT64_R3_DATA | RPL_MASK;
Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
Context->SegGs = KGDT64_R3_DATA | RPL_MASK;
Context->SegSs = KGDT64_R3_DATA | RPL_MASK;
/* Set RIP to the User-mode Dispatcher */
TrapFrame->Rip = (ULONG64)KeUserExceptionDispatcher;
Context->Rip = (ULONG64)KeUserExceptionDispatcher;
_disable();
/* Exit to usermode */
KiServiceExit2(TrapFrame);
return TRUE;
}
static
@ -361,10 +361,14 @@ KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
/* Forward exception to user mode debugger */
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
/* Forward exception to user mode (does not return, if successful) */
KiDispatchExceptionToUser(TrapFrame, &Context, ExceptionRecord);
/* Forward exception to user mode */
if (KiDispatchExceptionToUser(TrapFrame, &Context, ExceptionRecord))
{
goto Handled;
}
/* Failed to dispatch, fall through for second chance handling */
//__debugbreak();
}
/* Try second chance */
@ -409,6 +413,7 @@ NTAPI
KeRaiseUserException(IN NTSTATUS ExceptionCode)
{
UNIMPLEMENTED;
//__debugbreak();
return STATUS_UNSUCCESSFUL;
}

View file

@ -900,13 +900,20 @@ no_user_apc_pending:
/*!
* VOID
* DECLSPEC_NORETURN
* KiServiceExit(IN PKTRAP_FRAME TrapFrame, IN NTSTATUS Status));
* KiServiceExit(
* _In_ PKTRAP_FRAME TrapFrame@<rcx>,
* _In_ NTSTATUS Status@<edx>);
*
* Returns from a systemcall to user mode.
* Non-volatile registers will not be set.
* USed by KiUserModeCallout (x64), NtRaiseException, NtContinue
*/
PUBLIC KiServiceExit
.PROC KiServiceExit
.endprolog
lea rsp, [rcx - MAX_SYSCALL_PARAM_SIZE]
mov rax, rdx
jmp KiSystemServiceExit
.ENDP
@ -915,7 +922,10 @@ PUBLIC KiServiceExit
/*!
* VOID
* DECLSPEC_NORETURN
* KiServiceExit2(IN PKTRAP_FRAME TrapFrame);
* KiServiceExit2(
* _In_ PKTRAP_FRAME TrapFrame@<rcx>);
*
* Returns from
*/
PUBLIC KiServiceExit2
.PROC KiServiceExit2
@ -926,6 +936,11 @@ PUBLIC KiServiceExit2
mov rsp, rcx
.ENDP
/*
* Internal function. Exits to user-mode with rsp pointing to the trap frame.
* All non-volatile register context must be set up already.
* Used by KiInitializeContextThread to set up the init path for a new thread.
*/
PUBLIC KiServiceExit3
.PROC KiServiceExit3
.PUSHFRAME