mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[NTOSKRNL]
When a user mode debugger has single stepping enabled and steps over a sysenter instruction, you are obviously not supposed to enter the kernel debugger on the syscall entry handler. But exactly this happened on reactos. This was because the sysenter instruction doesn't disable single stepping, so we need to handle this special case manually in the single stepping handler (which we didn't). We now check if the single step comes from KiFastCallEntry and when it does, disable single stepping in the current (nested) trap frame and return back to a secondary fast call entry. The 2nd entrypoint will make sure to re-enable the single step flag in EFLAGS before returning to usermode. To make this actually work, the asm entry stub itself needs to handle saving of eflags, so some trap frame modification from KiFastCallEntryHandler was moved into the asm stub. Since the amount of asm instructions is rather small (10 instructions, pretty straight forward) I moved everything from KiSystemServiceHandler to the asm stub and killed KiFastCallEntryHandler entirely, calling KiSystemServiceHandler instead. Now stepping over a sysenter instruction works with OllyDbg without breaking into the kernel debugger. CORE-8057 #resolve svn path=/trunk/; revision=63420
This commit is contained in:
parent
ccd49a5b8a
commit
df7e3fde89
4 changed files with 53 additions and 45 deletions
|
@ -463,6 +463,5 @@ CONSTANT(EXCEPTION_EXECUTE_HANDLER),
|
|||
CONSTANT(STATUS_CALLBACK_POP_STACK),
|
||||
CONSTANT(CONTEXT_ALIGNED_SIZE),
|
||||
CONSTANT(PROCESSOR_FEATURE_FXSR),
|
||||
|
||||
|
||||
CONSTANT(KUSER_SHARED_SYSCALL_RET),
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ MACRO(KiEnterTrap, Flags)
|
|||
if (Flags AND KI_FAST_SYSTEM_CALL)
|
||||
|
||||
/* SYSENTER requires us to build a complete ring transition trap frame */
|
||||
FrameSize = KTRAP_FRAME_V86_ES
|
||||
FrameSize = KTRAP_FRAME_EIP
|
||||
|
||||
/* Fixup fs. cx is free to clobber */
|
||||
mov cx, KGDT_R0_PCR
|
||||
|
@ -95,6 +95,13 @@ MACRO(KiEnterTrap, Flags)
|
|||
/* Get a stack pointer */
|
||||
mov esp, [ecx + KTSS_ESP0]
|
||||
|
||||
/* Set up a fake hardware trap frame */
|
||||
push KGDT_R3_DATA or RPL_MASK
|
||||
push edx
|
||||
pushfd
|
||||
push KGDT_R3_CODE or RPL_MASK
|
||||
push dword ptr ds:[KUSER_SHARED_SYSCALL_RET]
|
||||
|
||||
elseif (Flags AND KI_SOFTWARE_TRAP)
|
||||
|
||||
/* Software traps need a complete non-ring transition trap frame */
|
||||
|
@ -183,7 +190,19 @@ set_sane_segs:
|
|||
mov es, ax
|
||||
|
||||
/* Fast system calls have fs already fixed */
|
||||
if (NOT (Flags AND KI_FAST_SYSTEM_CALL))
|
||||
if (Flags AND KI_FAST_SYSTEM_CALL)
|
||||
|
||||
/* Enable interrupts and set a sane FS value */
|
||||
or dword ptr [esp + KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
|
||||
mov dword ptr [esp + KTRAP_FRAME_FS], KGDT_R3_TEB or RPL_MASK
|
||||
|
||||
/* Set sane active EFLAGS */
|
||||
push 2
|
||||
popfd
|
||||
|
||||
/* Point edx to the usermode parameters */
|
||||
add edx, 8
|
||||
else
|
||||
/* Otherwise fix fs now */
|
||||
mov ax, KGDT_R0_PCR
|
||||
mov fs, ax
|
||||
|
|
|
@ -142,14 +142,20 @@ PUBLIC _KiSystemService
|
|||
KiCallHandler @KiSystemServiceHandler@8
|
||||
.ENDP
|
||||
|
||||
EXTERN @KiFastCallEntryHandler@8:PROC
|
||||
PUBLIC _KiFastCallEntry
|
||||
.PROC _KiFastCallEntry
|
||||
FPO 0, 0, 0, 0, 1, FRAME_TRAP
|
||||
KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
|
||||
KiCallHandler @KiFastCallEntryHandler@8
|
||||
KiCallHandler @KiSystemServiceHandler@8
|
||||
.ENDP
|
||||
|
||||
PUBLIC _KiFastCallEntryWithSingleStep
|
||||
.PROC _KiFastCallEntryWithSingleStep
|
||||
FPO 0, 0, 0, 0, 1, FRAME_TRAP
|
||||
KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
|
||||
or dword ptr [ecx + KTRAP_FRAME_EFLAGS], EFLAGS_TF
|
||||
KiCallHandler @KiSystemServiceHandler@8
|
||||
.ENDP
|
||||
|
||||
PUBLIC _KiEndUnexpectedRange@0
|
||||
_KiEndUnexpectedRange@0:
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
VOID KiFastCallEntry(VOID);
|
||||
VOID KiFastCallEntryWithSingleStep(VOID);
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
UCHAR KiTrapPrefixTable[] =
|
||||
|
@ -421,6 +424,19 @@ KiTrap01Handler(IN PKTRAP_FRAME TrapFrame)
|
|||
/* Check for VDM trap */
|
||||
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
|
||||
|
||||
/* Check if this was a single step after sysenter */
|
||||
if (TrapFrame->Eip == (ULONG)KiFastCallEntry)
|
||||
{
|
||||
/* Disable single stepping */
|
||||
TrapFrame->EFlags &= ~EFLAGS_TF;
|
||||
|
||||
/* Re-enter at the alternative sysenter entry point */
|
||||
TrapFrame->Eip = (ULONG)KiFastCallEntryWithSingleStep;
|
||||
|
||||
/* End this trap */
|
||||
KiEoiHelper(TrapFrame);
|
||||
}
|
||||
|
||||
/* Enable interrupts if the trap came from user-mode */
|
||||
if (KiUserTrap(TrapFrame)) _enable();
|
||||
|
||||
|
@ -1521,11 +1537,11 @@ KiDbgPostServiceHook(ULONG SystemCallNumber, ULONG_PTR Result)
|
|||
return Result;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
DECLSPEC_NORETURN
|
||||
VOID
|
||||
KiSystemCall(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PVOID Arguments)
|
||||
FASTCALL
|
||||
KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PVOID Arguments)
|
||||
{
|
||||
PKTHREAD Thread;
|
||||
PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
|
||||
|
@ -1658,38 +1674,6 @@ ExitCall:
|
|||
KiServiceExit(TrapFrame, Result);
|
||||
}
|
||||
|
||||
DECLSPEC_NORETURN
|
||||
VOID
|
||||
FASTCALL
|
||||
KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PVOID Arguments)
|
||||
{
|
||||
/* Call the shared handler (inline) */
|
||||
KiSystemCall(TrapFrame, Arguments);
|
||||
}
|
||||
|
||||
DECLSPEC_NORETURN
|
||||
VOID
|
||||
FASTCALL
|
||||
KiFastCallEntryHandler(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PVOID Arguments)
|
||||
{
|
||||
/* Set up a fake INT Stack and enable interrupts */
|
||||
TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
|
||||
TrapFrame->HardwareEsp = (ULONG_PTR)Arguments;
|
||||
TrapFrame->EFlags = __readeflags() | EFLAGS_INTERRUPT_MASK;
|
||||
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
|
||||
TrapFrame->Eip = SharedUserData->SystemCallReturn;
|
||||
TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
|
||||
__writeeflags(0x2);
|
||||
|
||||
/* Arguments are actually 2 frames down (because of the double indirection) */
|
||||
Arguments = (PVOID)(TrapFrame->HardwareEsp + 8);
|
||||
|
||||
/* Call the shared handler (inline) */
|
||||
KiSystemCall(TrapFrame, Arguments);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue