mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 22:55:41 +00:00
[NTOS:KE/x64] Handle user faults in KiGeneralProtectionFaultHandler
This commit is contained in:
parent
f659ac5201
commit
45f75d5d32
3 changed files with 198 additions and 15 deletions
|
@ -425,6 +425,184 @@ KiNpxNotAvailableFaultHandler(
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
BOOLEAN
|
||||||
|
KiIsPrivilegedInstruction(PUCHAR Ip, BOOLEAN Wow64)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Handle prefixes */
|
||||||
|
for (i = 0; i < 15; i++)
|
||||||
|
{
|
||||||
|
if (!Wow64)
|
||||||
|
{
|
||||||
|
/* Check for REX prefix */
|
||||||
|
if ((Ip[0] >= 0x40) && (Ip[0] <= 0x4F))
|
||||||
|
{
|
||||||
|
Ip++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Ip[0])
|
||||||
|
{
|
||||||
|
/* Check prefixes */
|
||||||
|
case 0x26: // ES
|
||||||
|
case 0x2E: // CS / null
|
||||||
|
case 0x36: // SS
|
||||||
|
case 0x3E: // DS
|
||||||
|
case 0x64: // FS
|
||||||
|
case 0x65: // GS
|
||||||
|
case 0x66: // OP
|
||||||
|
case 0x67: // ADDR
|
||||||
|
case 0xF0: // LOCK
|
||||||
|
case 0xF2: // REP
|
||||||
|
case 0xF3: // REP INS/OUTS
|
||||||
|
Ip++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 15)
|
||||||
|
{
|
||||||
|
/* Too many prefixes. Should only happen, when the code was concurrently modified. */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Ip[0])
|
||||||
|
{
|
||||||
|
case 0xF4: // HLT
|
||||||
|
case 0xFA: // CLI
|
||||||
|
case 0xFB: // STI
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case 0x0F:
|
||||||
|
{
|
||||||
|
switch (Ip[1])
|
||||||
|
{
|
||||||
|
case 0x06: // CLTS
|
||||||
|
case 0x07: // SYSRET
|
||||||
|
case 0x08: // INVD
|
||||||
|
case 0x09: // WBINVD
|
||||||
|
case 0x20: // MOV CR, XXX
|
||||||
|
case 0x21: // MOV DR, XXX
|
||||||
|
case 0x22: // MOV XXX, CR
|
||||||
|
case 0x23: // MOV YYY, DR
|
||||||
|
case 0x30: // WRMSR
|
||||||
|
case 0x32: // RDMSR
|
||||||
|
case 0x33: // RDPMC
|
||||||
|
case 0x35: // SYSEXIT
|
||||||
|
case 0x78: // VMREAD
|
||||||
|
case 0x79: // VMWRITE
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case 0x00:
|
||||||
|
{
|
||||||
|
/* Check MODRM Reg field */
|
||||||
|
switch ((Ip[2] >> 3) & 0x7)
|
||||||
|
{
|
||||||
|
case 2: // LLDT
|
||||||
|
case 3: // LTR
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x01:
|
||||||
|
{
|
||||||
|
switch (Ip[2])
|
||||||
|
{
|
||||||
|
case 0xC1: // VMCALL
|
||||||
|
case 0xC2: // VMLAUNCH
|
||||||
|
case 0xC3: // VMRESUME
|
||||||
|
case 0xC4: // VMXOFF
|
||||||
|
case 0xC8: // MONITOR
|
||||||
|
case 0xC9: // MWAIT
|
||||||
|
case 0xD1: // XSETBV
|
||||||
|
case 0xF8: // SWAPGS
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check MODRM Reg field */
|
||||||
|
switch ((Ip[2] >> 3) & 0x7)
|
||||||
|
{
|
||||||
|
case 2: // LGDT
|
||||||
|
case 3: // LIDT
|
||||||
|
case 6: // LMSW
|
||||||
|
case 7: // INVLPG / SWAPGS / RDTSCP
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x38:
|
||||||
|
{
|
||||||
|
switch (Ip[2])
|
||||||
|
{
|
||||||
|
case 0x80: // INVEPT
|
||||||
|
case 0x81: // INVVPID
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0xC7:
|
||||||
|
{
|
||||||
|
/* Check MODRM Reg field */
|
||||||
|
switch ((Ip[2] >> 3) & 0x7)
|
||||||
|
{
|
||||||
|
case 0x06: // VMPTRLD, VMCLEAR, VMXON
|
||||||
|
case 0x07: // VMPTRST
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
KiGeneralProtectionFaultUserMode(
|
||||||
|
_In_ PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
BOOLEAN Wow64 = TrapFrame->SegCs == KGDT64_R3_CMCODE;
|
||||||
|
PUCHAR InstructionPointer;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* We need to decode the instruction at RIP */
|
||||||
|
InstructionPointer = (PUCHAR)TrapFrame->Rip;
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
/* Probe the instruction address */
|
||||||
|
ProbeForRead(InstructionPointer, 64, 1);
|
||||||
|
|
||||||
|
/* Check if it's a privileged instruction */
|
||||||
|
if (KiIsPrivilegedInstruction(InstructionPointer, Wow64))
|
||||||
|
{
|
||||||
|
Status = STATUS_PRIVILEGED_INSTRUCTION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_ACCESS_VIOLATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -436,8 +614,7 @@ KiGeneralProtectionFaultHandler(
|
||||||
/* Check for user-mode GPF */
|
/* Check for user-mode GPF */
|
||||||
if (TrapFrame->SegCs & 3)
|
if (TrapFrame->SegCs & 3)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
return KiGeneralProtectionFaultUserMode(TrapFrame);
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for lazy segment load */
|
/* Check for lazy segment load */
|
||||||
|
@ -454,15 +631,6 @@ KiGeneralProtectionFaultHandler(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for nested exception */
|
|
||||||
if ((TrapFrame->Rip >= (ULONG64)KiGeneralProtectionFaultHandler) &&
|
|
||||||
(TrapFrame->Rip < (ULONG64)KiGeneralProtectionFaultHandler))
|
|
||||||
{
|
|
||||||
/* Not implemented */
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get Instruction Pointer */
|
/* Get Instruction Pointer */
|
||||||
Instructions = (PUCHAR)TrapFrame->Rip;
|
Instructions = (PUCHAR)TrapFrame->Rip;
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,7 @@ KiInvalidOpcodeKernel:
|
||||||
/* Kernel mode fault */
|
/* Kernel mode fault */
|
||||||
|
|
||||||
/* Dispatch the exception */
|
/* Dispatch the exception */
|
||||||
DispatchException STATUS_ILLEGAL_INSTRUCTION, 3, 0, 0, 0
|
DispatchException STATUS_ILLEGAL_INSTRUCTION, 0, 0, 0, 0
|
||||||
|
|
||||||
/* Return */
|
/* Return */
|
||||||
ExitTrap TF_SAVE_ALL
|
ExitTrap TF_SAVE_ALL
|
||||||
|
@ -385,8 +385,18 @@ FUNC KiGeneralProtectionFault
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jge KiGpfExit
|
jge KiGpfExit
|
||||||
|
|
||||||
/* Dispatch the exception */
|
/* Check for access violation */
|
||||||
DispatchException eax, 3, 0, 0, 0
|
cmp eax, STATUS_ACCESS_VIOLATION
|
||||||
|
je DispatchAccessViolation
|
||||||
|
|
||||||
|
/* Dispatch privileged instruction fault */
|
||||||
|
DispatchException eax, 0, 0, 0, 0
|
||||||
|
jmp KiGpfFatal
|
||||||
|
|
||||||
|
DispatchAccessViolation:
|
||||||
|
|
||||||
|
/* Dispatch access violation */
|
||||||
|
DispatchException eax, 2, 0, -1, 0
|
||||||
|
|
||||||
KiGpfFatal:
|
KiGpfFatal:
|
||||||
|
|
||||||
|
|
|
@ -701,9 +701,15 @@ RtlpUnwindInternal(
|
||||||
Note: this can happen after the first frame as the result of an exception */
|
Note: this can happen after the first frame as the result of an exception */
|
||||||
UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
|
UnwindContext.Rip = *(DWORD64*)UnwindContext.Rsp;
|
||||||
UnwindContext.Rsp += sizeof(DWORD64);
|
UnwindContext.Rsp += sizeof(DWORD64);
|
||||||
|
|
||||||
|
/* Copy the context back for the next iteration */
|
||||||
|
*ContextRecord = UnwindContext;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save Rip before the virtual unwind */
|
||||||
|
DispatcherContext.ControlPc = UnwindContext.Rip;
|
||||||
|
|
||||||
/* Do a virtual unwind to get the next frame */
|
/* Do a virtual unwind to get the next frame */
|
||||||
ExceptionRoutine = RtlVirtualUnwind(HandlerType,
|
ExceptionRoutine = RtlVirtualUnwind(HandlerType,
|
||||||
ImageBase,
|
ImageBase,
|
||||||
|
@ -749,7 +755,6 @@ RtlpUnwindInternal(
|
||||||
sizeof(DispatcherContext));
|
sizeof(DispatcherContext));
|
||||||
|
|
||||||
/* Set up the variable fields of the dispatcher context */
|
/* Set up the variable fields of the dispatcher context */
|
||||||
DispatcherContext.ControlPc = ContextRecord->Rip;
|
|
||||||
DispatcherContext.ImageBase = ImageBase;
|
DispatcherContext.ImageBase = ImageBase;
|
||||||
DispatcherContext.FunctionEntry = FunctionEntry;
|
DispatcherContext.FunctionEntry = FunctionEntry;
|
||||||
DispatcherContext.LanguageHandler = ExceptionRoutine;
|
DispatcherContext.LanguageHandler = ExceptionRoutine;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue