Author: sir_richard
Date: Tue Jan 19 09:20:12 2010
New Revision: 45142
URL: http://svn.reactos.org/svn/reactos?rev=45142&view=rev
Log:
[NTOS]: Implement "Edited Trap Frame" exit. This funky trick is actually how NT emulates longjmp/setjmp when doing an NtContinue: it allows arbitrary return with a new CS/ESP.
[NTOS]: Implement C version of KiServiceExit, the second system call exit routine. This one sets a new EAX value to be returned to the caller and is used by system calls.
[NTOS]: Implement NtContinue in C instead of ASM. Due to the changes above, this can now be done in C and use the new KiServiceExit.
Modified:
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/include/internal/trap_x.h
trunk/reactos/ntoskrnl/ke/i386/trap.s
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Tue Jan 19 09:20:12 2010
@@ -932,6 +932,14 @@
VOID
);
+NTSTATUS
+NTAPI
+KiContinue(
+ IN PCONTEXT Context,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame
+);
+
VOID
FASTCALL
KiServiceExit2(
Modified: trunk/reactos/ntoskrnl/include/internal/trap_x.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] Tue Jan 19 09:20:12 2010
@@ -322,3 +322,35 @@
: "%esp"
);
}
+
+FORCEINLINE
+VOID
+KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame)
+{
+ /* Regular interrupt exit */
+ __asm__ __volatile__
+ (
+ "movl %0, %%esp\n"
+ "movl %c[a](%%esp), %%eax\n"
+ "movl %c[b](%%esp), %%ebx\n"
+ "movl %c[c](%%esp), %%ecx\n"
+ "movl %c[d](%%esp), %%edx\n"
+ "movl %c[s](%%esp), %%esi\n"
+ "movl %c[i](%%esp), %%edi\n"
+ "movl %c[p](%%esp), %%ebp\n"
+ "addl $%c[e],%%esp\n"
+ "movl (%%esp), %%esp\n"
+ "iret\n"
+ :
+ : "r"(TrapFrame),
+ [a] "i"(KTRAP_FRAME_EAX),
+ [b] "i"(KTRAP_FRAME_EBX),
+ [c] "i"(KTRAP_FRAME_ECX),
+ [d] "i"(KTRAP_FRAME_EDX),
+ [s] "i"(KTRAP_FRAME_ESI),
+ [i] "i"(KTRAP_FRAME_EDI),
+ [p] "i"(KTRAP_FRAME_EBP),
+ [e] "i"(KTRAP_FRAME_ERROR_CODE) /* We *WANT* the error code since ESP is there! */
+ : "%esp"
+ );
+}
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?re…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Tue Jan 19 09:20:12 2010
@@ -523,52 +523,10 @@
.func NtContinue@8
_NtContinue@8:
-
- /* NOTE: We -must- be called by Zw* to have the right frame! */
- /* Push the stack frame */
- push ebp
-
- /* Get the current thread and restore its trap frame */
- mov ebx, PCR[KPCR_CURRENT_THREAD]
- mov edx, [ebp+KTRAP_FRAME_EDX]
- mov [ebx+KTHREAD_TRAP_FRAME], edx
-
- /* Set up stack frame */
- mov ebp, esp
-
- /* Save the parameters */
- mov eax, [ebp+0]
- mov ecx, [ebp+8]
-
- /* Call KiContinue */
- push eax
- push 0
- push ecx
- call _KiContinue@12
-
- /* Check if we failed (bad context record) */
- or eax, eax
- jnz Error
-
- /* Check if test alert was requested */
- cmp dword ptr [ebp+12], 0
- je DontTest
-
- /* Test alert for the thread */
- mov al, [ebx+KTHREAD_PREVIOUS_MODE]
- push eax
- call _KeTestAlertThread@4
-
-DontTest:
- /* Return to previous context */
- pop ebp
- mov esp, ebp
- jmp _KiServiceExit2
-
-Error:
- pop ebp
- mov esp, ebp
- jmp _KiServiceExit
+ /* Call C code */
+ mov ecx, [esp+4]
+ mov edx, [esp+8]
+ jmp @NtContinueHandler@8
.endfunc
/* HARDWARE TRAP HANDLERS ****************************************************/
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Tue Jan 19 09:20:12 2010
@@ -54,6 +54,9 @@
IN UCHAR Skip)
{
KTRAP_EXIT_SKIP_BITS SkipBits = { .Bits = Skip };
+ PULONG ReturnStack;
+
+ /* Debugging checks */
KiExitTrapDebugChecks(TrapFrame, SkipBits);
/* Restore the SEH handler chain */
@@ -81,12 +84,42 @@
/* Check if the trap frame was edited */
if (__builtin_expect(!(TrapFrame->SegCs & FRAME_EDITED), 0))
- {
- /* Not handled yet */
- UNIMPLEMENTED;
- KiDumpTrapFrame(TrapFrame);
- DbgBreakPoint();
- while (TRUE);
+ {
+ /*
+ * An edited trap frame happens when we need to modify CS and/or ESP but
+ * don't actually have a ring transition. This happens when a kernelmode
+ * caller wants to perform an NtContinue to another kernel address, such
+ * as in the case of SEH (basically, a longjmp), or to a user address.
+ *
+ * Therefore, the CPU never saved CS/ESP on the stack because we did not
+ * get a trap frame due to a ring transition (there was no interrupt).
+ * Even if we didn't want to restore CS to a new value, a problem occurs
+ * due to the fact a normal RET would not work if we restored ESP since
+ * RET would then try to read the result off the stack.
+ *
+ * The NT kernel solves this by adding 12 bytes of stack to the exiting
+ * trap frame, in which EFLAGS, CS, and EIP are stored, and then saving
+ * the ESP that's being requested into the ErrorCode field. It will then
+ * exit with an IRET. This fixes both issues, because it gives the stack
+ * some space where to hold the return address and then end up with the
+ * wanted stack, and it uses IRET which allows a new CS to be inputted.
+ *
+ */
+
+ /* Set CS that is requested */
+ TrapFrame->SegCs = TrapFrame->TempSegCs;
+
+ /* First make space on requested stack */
+ ReturnStack = (PULONG)(TrapFrame->TempEsp - 12);
+ TrapFrame->ErrCode = (ULONG_PTR)ReturnStack;
+
+ /* Now copy IRET frame */
+ ReturnStack[0] = TrapFrame->Eip;
+ ReturnStack[1] = TrapFrame->SegCs;
+ ReturnStack[2] = TrapFrame->EFlags;
+
+ /* Do special edited return */
+ KiEditedTrapReturn(TrapFrame);
}
/* Check if this is a user trap */
@@ -212,6 +245,24 @@
/* Now exit the trap for real */
KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT);
+}
+
+VOID
+FASTCALL
+KiServiceExit(IN PKTRAP_FRAME TrapFrame,
+ IN NTSTATUS Status)
+{
+ /* Disable interrupts until we return */
+ _disable();
+
+ /* Check for APC delivery */
+ KiCheckForApcDelivery(TrapFrame);
+
+ /* Copy the status into EAX */
+ TrapFrame->Eax = Status;
+
+ /* Now exit the trap for real */
+ KiExitTrap(TrapFrame, KTE_SKIP_SEG_BIT | KTE_SKIP_VOL_BIT);
}
VOID
@@ -1640,6 +1691,37 @@
KiDebugHandler(TrapFrame, TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
}
+VOID
+FASTCALL
+NtContinueHandler(IN PCONTEXT Context,
+ IN BOOLEAN TestAlert)
+{
+ PKTHREAD Thread;
+ NTSTATUS Status;
+ PKTRAP_FRAME TrapFrame;
+
+ /* Get trap frame and link previous one*/
+ Thread = KeGetCurrentThread();
+ TrapFrame = Thread->TrapFrame;
+ Thread->TrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
+
+ /* Continue from this point on */
+ Status = KiContinue(Context, NULL, TrapFrame);
+ if (NT_SUCCESS(Status))
+ {
+ /* Check if alert was requested */
+ if (TestAlert) KeTestAlertThread(Thread->PreviousMode);
+
+ /* Exit to new trap frame */
+ KiServiceExit2(TrapFrame);
+ }
+ else
+ {
+ /* Exit with an error */
+ KiServiceExit(TrapFrame, Status);
+ }
+}
+
/* HARDWARE INTERRUPTS ********************************************************/
/*
Author: tkreuzer
Date: Mon Jan 18 18:24:28 2010
New Revision: 45137
URL: http://svn.reactos.org/svn/reactos?rev=45137&view=rev
Log:
[NTOS]
Fix possible NULL pointer dereference. Spotted by Amine Khaldi.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/contmem.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/contmem.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/contmem.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/contmem.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/contmem.c [iso-8859-1] Mon Jan 18 18:24:28 2010
@@ -276,7 +276,7 @@
// Now get the PFN entry for this, and make sure it's the correct one
//
Pfn1 = MiGetPfnEntry(PageFrameIndex);
- if (Pfn1->u3.e1.StartOfAllocation == 0)
+ if ((!Pfn1) || (Pfn1->u3.e1.StartOfAllocation == 0))
{
//
// This probably means you did a free on an address that was in between