if (ContextFlags & CONTEXT_INTEGER)
{
TrapFrame->Rax = Context->Rax;
- TrapFrame->Rbx = Context->Rbx;
TrapFrame->Rcx = Context->Rcx;
TrapFrame->Rdx = Context->Rdx;
- TrapFrame->Rsi = Context->Rsi;
- TrapFrame->Rdi = Context->Rdi;
TrapFrame->Rbp = Context->Rbp;
TrapFrame->R8 = Context->R8;
TrapFrame->R9 = Context->R9;
TrapFrame->R11 = Context->R11;
if (ExceptionFrame)
{
+ ExceptionFrame->Rbx = Context->Rbx;
+ ExceptionFrame->Rsi = Context->Rsi;
+ ExceptionFrame->Rdi = Context->Rdi;
ExceptionFrame->R12 = Context->R12;
ExceptionFrame->R13 = Context->R13;
ExceptionFrame->R14 = Context->R14;
}
/* Handle floating point registers */
- if ((ContextFlags & CONTEXT_FLOATING_POINT) &&
- (Context->SegCs & MODE_MASK))
+ if (ContextFlags & CONTEXT_FLOATING_POINT)
{
+ TrapFrame->MxCsr = Context->MxCsr;
TrapFrame->Xmm0 = Context->Xmm0;
TrapFrame->Xmm1 = Context->Xmm1;
TrapFrame->Xmm2 = Context->Xmm2;
/* Handle control registers */
if (ContextFlags & CONTEXT_CONTROL)
{
- /* Check if this was a Kernel Trap */
- if (Context->SegCs == KGDT64_R0_CODE)
+ /* RIP, RSP, EFLAGS */
+ TrapFrame->Rip = Context->Rip;
+ TrapFrame->Rsp = Context->Rsp;
+ TrapFrame->EFlags = Context->EFlags;
+
+ if ((Context->SegCs & MODE_MASK) == KernelMode)
{
/* Set valid selectors */
TrapFrame->SegCs = KGDT64_R0_CODE;
TrapFrame->SegSs = KGDT64_R0_DATA;
+
+ /* Set valid EFLAGS */
+ TrapFrame->EFlags &= (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK);
}
else
{
/* Copy selectors */
TrapFrame->SegCs = Context->SegCs;
+ if (TrapFrame->SegCs != (KGDT64_R3_CODE | RPL_MASK))
+ {
+ TrapFrame->SegCs = (KGDT64_R3_CMCODE | RPL_MASK);
+ }
+
TrapFrame->SegSs = Context->SegSs;
- }
- /* RIP, RSP, EFLAGS */
- TrapFrame->Rip = Context->Rip;
- TrapFrame->Rsp = Context->Rsp;
- TrapFrame->EFlags = Context->EFlags;
+ /* Set valid EFLAGS */
+ TrapFrame->EFlags &= EFLAGS_USER_SANITIZE;
+ TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
+ }
}
/* Handle segment selectors */
if (ContextFlags & CONTEXT_SEGMENTS)
{
/* Check if this was a Kernel Trap */
- if (Context->SegCs == KGDT64_R0_CODE)
+ if ((Context->SegCs & MODE_MASK) == KernelMode)
{
/* Set valid selectors */
TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
TrapFrame->Dr3 = Context->Dr3;
TrapFrame->Dr6 = Context->Dr6;
TrapFrame->Dr7 = Context->Dr7;
+
+ if ((Context->SegCs & MODE_MASK) != KernelMode)
+ {
+ if (TrapFrame->Dr0 > (ULONG64)MmHighestUserAddress)
+ TrapFrame->Dr0 = 0;
+ if (TrapFrame->Dr1 > (ULONG64)MmHighestUserAddress)
+ TrapFrame->Dr1 = 0;
+ if (TrapFrame->Dr2 > (ULONG64)MmHighestUserAddress)
+ TrapFrame->Dr2 = 0;
+ if (TrapFrame->Dr3 > (ULONG64)MmHighestUserAddress)
+ TrapFrame->Dr3 = 0;
+ }
}
/* Restore IRQL */
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context)
{
+ ULONG ContextFlags;
KIRQL OldIrql;
/* Do this at APC_LEVEL */
OldIrql = KeGetCurrentIrql();
if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
+ /* Make sure we have an amd64 context, then remove the flag */
+ ContextFlags = Context->ContextFlags;
+ ASSERT(ContextFlags & CONTEXT_AMD64);
+ ContextFlags &= ~CONTEXT_AMD64;
+
/* Handle integer registers */
- if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+ if (ContextFlags & CONTEXT_INTEGER)
{
Context->Rax = TrapFrame->Rax;
- Context->Rbx = TrapFrame->Rbx;
Context->Rcx = TrapFrame->Rcx;
Context->Rdx = TrapFrame->Rdx;
- Context->Rsi = TrapFrame->Rsi;
- Context->Rdi = TrapFrame->Rdi;
Context->Rbp = TrapFrame->Rbp;
Context->R8 = TrapFrame->R8;
Context->R9 = TrapFrame->R9;
if (ExceptionFrame)
{
+ Context->Rbx = ExceptionFrame->Rbx;
+ Context->Rsi = ExceptionFrame->Rsi;
+ Context->Rdi = ExceptionFrame->Rdi;
Context->R12 = ExceptionFrame->R12;
Context->R13 = ExceptionFrame->R13;
Context->R14 = ExceptionFrame->R14;
}
/* Handle floating point registers */
- if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
- CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK))
+ if (ContextFlags & CONTEXT_FLOATING_POINT)
{
+ Context->MxCsr = TrapFrame->MxCsr;
Context->Xmm0 = TrapFrame->Xmm0;
Context->Xmm1 = TrapFrame->Xmm1;
Context->Xmm2 = TrapFrame->Xmm2;
}
/* Handle control registers */
- if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+ if (ContextFlags & CONTEXT_CONTROL)
{
/* Check if this was a Kernel Trap */
- if (TrapFrame->SegCs == KGDT64_R0_CODE)
+ if ((TrapFrame->SegCs & MODE_MASK) == KernelMode)
{
/* Set valid selectors */
Context->SegCs = KGDT64_R0_CODE;
}
/* Handle segment selectors */
- if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+ if (ContextFlags & CONTEXT_SEGMENTS)
{
/* Check if this was a Kernel Trap */
- if (TrapFrame->SegCs == KGDT64_R0_CODE)
+ if ((TrapFrame->SegCs & MODE_MASK) == KernelMode)
{
/* Set valid selectors */
Context->SegDs = KGDT64_R3_DATA | RPL_MASK;
}
/* Handle debug registers */
- if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
- CONTEXT_DEBUG_REGISTERS)
+ if (ContextFlags & CONTEXT_DEBUG_REGISTERS)
{
/* Copy the debug registers */
Context->Dr0 = TrapFrame->Dr0;
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
+VOID
+RtlSetUnwindContext(
+ _In_ PCONTEXT Context,
+ _In_ DWORD64 TargetFrame);
+
+VOID
+KiSetTrapContextInternal(
+ _Out_ PKTRAP_FRAME TrapFrame,
+ _In_ PCONTEXT Context,
+ _In_ KPROCESSOR_MODE RequestorMode)
+{
+ ULONG64 TargetFrame;
+
+ /* Save the volatile register context in the trap frame */
+ KeContextToTrapFrame(Context,
+ NULL,
+ TrapFrame,
+ Context->ContextFlags,
+ RequestorMode);
+
+ /* The target frame is MAX_SYSCALL_PARAM_SIZE bytes before the trap frame */
+ TargetFrame = (ULONG64)TrapFrame - MAX_SYSCALL_PARAM_SIZE ;
+
+ /* Set the nonvolatiles on the stack */
+ RtlSetUnwindContext(Context, TargetFrame);
+}