[NTOS:KE]

- Gracefully handle page faults during V86 code execution. This is a bit of a hack because with our limited use of V86 code it is unclear how a page fault can even occur.
CORE-12993 #resolve

svn path=/trunk/; revision=74305
This commit is contained in:
Thomas Faber 2017-04-14 11:18:22 +00:00
parent 8c82e4261d
commit 389bdb30ca
3 changed files with 63 additions and 4 deletions

View file

@ -480,6 +480,12 @@ VdmDispatchBop(
IN PKTRAP_FRAME TrapFrame
);
BOOLEAN
NTAPI
VdmDispatchPageFault(
_In_ PKTRAP_FRAME TrapFrame
);
BOOLEAN
FASTCALL
KiVdmOpcodePrefix(

View file

@ -1304,8 +1304,20 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
UNIMPLEMENTED_FATAL();
}
#endif
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
if (KiVdmTrap(TrapFrame))
{
DPRINT1("VDM PAGE FAULT at %lx:%lx for address %lx\n",
TrapFrame->SegCs, TrapFrame->Eip, Cr2);
if (VdmDispatchPageFault(TrapFrame))
{
/* Return and end VDM execution */
DPRINT1("VDM page fault with status 0x%lx resolved\n", Status);
KiEoiHelper(TrapFrame);
}
DPRINT1("VDM page fault with status 0x%lx NOT resolved\n", Status);
}
/* Either kernel or user trap (non VDM) so dispatch exception */
if (Status == STATUS_ACCESS_VIOLATION)

View file

@ -239,7 +239,7 @@ VdmpStartExecution(VOID)
KeLowerIrql(OldIrql);
return STATUS_INVALID_SYSTEM_SERVICE;
}
/* Now do the VDM Swap */
VdmSwapContext(VdmFrame, &VdmTib->MonitorContext, &VdmContext);
@ -269,7 +269,7 @@ VdmEndExecution(IN PKTRAP_FRAME TrapFrame,
/* Make a copy of the monitor context */
Context = VdmTib->MonitorContext;
/* Check if V86 mode was enabled or the trap was edited */
if ((Context.EFlags & EFLAGS_V86_MASK) || (Context.SegCs & FRAME_EDITED))
{
@ -291,7 +291,7 @@ VdmEndExecution(IN PKTRAP_FRAME TrapFrame,
/* Remove real IF flag */
VdmTib->VdmContext.EFlags &= ~EFLAGS_INTERRUPT_MASK;
}
/* Turn off VIP and VIF */
TrapFrame->EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
VdmTib->VdmContext.EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
@ -362,4 +362,45 @@ VdmDispatchBop(IN PKTRAP_FRAME TrapFrame)
return TRUE;
}
BOOLEAN
NTAPI
VdmDispatchPageFault(
_In_ PKTRAP_FRAME TrapFrame)
{
NTSTATUS Status;
PVDM_TIB VdmTib;
PAGED_CODE();
/* Get the VDM TIB so we can terminate V86 execution */
Status = VdmpGetVdmTib(&VdmTib);
if (!NT_SUCCESS(Status))
{
/* Not a proper VDM fault, keep looking */
DPRINT1("VdmDispatchPageFault: no VDM TIB, Vdm=%p\n", NtCurrentTeb()->Vdm);
return FALSE;
}
/* Must be coming from V86 code */
ASSERT(TrapFrame->EFlags & EFLAGS_V86_MASK);
_SEH2_TRY
{
/* Fill out a VDM Event */
VdmTib->EventInfo.Event = VdmMemAccess;
VdmTib->EventInfo.InstructionSize = 0;
/* End VDM Execution */
VdmEndExecution(TrapFrame, VdmTib);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
/* Consider the exception handled if we succeeded */
DPRINT1("VdmDispatchPageFault EFlags %lx exit with 0x%lx\n", TrapFrame->EFlags, Status);
return NT_SUCCESS(Status);
}