* Increase total system call count in KPCR for performance counter.
* Increase per-systemcall call count in the KiServiceTable if it was
specified, for performance counters.
* Add sanity checks to system call handler to detect:
- User-mode system calls at > PASSIVE
- User-mode system call return at > PASSIVE
- Return to user-mode with Kernel APCs disabled.
* These features are on DBG only.
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
--- trunk/reactos/ntoskrnl/ke/i386/syscall.S 2006-01-16 21:14:32 UTC
(rev 20921)
+++ trunk/reactos/ntoskrnl/ke/i386/syscall.S 2006-01-16 21:41:19 UTC
(rev 20922)
@@ -7,6 +7,8 @@
#include <asm.h>
#include <internal/i386/asmmacro.S>
+#define APC_INDEX_MISMATCH 1
+#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
.globl _KiServiceExit
.globl _KiServiceExit2
@@ -322,7 +324,18 @@
#endif
NotWin32K:
+ /* Increase total syscall count */
+ inc dword ptr fs:[KPCR_SYSTEM_CALLS]
+
+#ifdef DBG
+ /* Increase per-syscall count */
+ mov ecx, [edi+4]
+ jecxz NoCountTable
+ inc dword ptr [ecx+eax*4]
+#endif
+
/* Users's current stack frame pointer is source */
+NoCountTable:
mov esi, edx
/* Allocate room for argument list from kernel stack */
@@ -346,6 +359,14 @@
rep movsd
#ifdef DBG
+
+ /* Make sure this isn't a user-mode call at elevated IRQL */
+ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+ jz SkipCheck
+ call _KeGetCurrentIrql@0
+ or al, al
+ jnz InvalidIrql
+
/*
* The following lines are for the benefit of GDB. It will see the
return
* address of the "call ebx" below, find the last label before it
and
@@ -355,6 +376,7 @@
* stack backtrace. Since we do want to backtrace into usermode,
let's
* make GDB happy and create a standard prolog.
*/
+SkipCheck:
KiSystemService:
push ebp
mov ebp,esp
@@ -364,6 +386,30 @@
/* Do the System Call */
call ebx
+#ifdef DBG
+ /* Make sure the user-mode call didn't return at elevated IRQL */
+ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+ jz SkipCheck2
+ mov esi, eax /* We need to save the syscall's return
val */
+ call _KeGetCurrentIrql@0
+ or al, al
+ jnz InvalidIrql
+ mov eax, esi /* Restore it */
+
+ /* Get our temporary current thread pointer for sanity check */
+ mov ecx, fs:[KPCR_CURRENT_THREAD]
+
+ /* Make sure that we are not attached and that APCs are not
disabled */
+ mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
+ or dl, dl
+ jnz InvalidIndex
+ mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
+ or edx, edx
+ jnz InvalidIndex
+#endif
+
+SkipCheck2:
+
/* Deallocate the kernel stack frame */
mov esp, ebp
@@ -540,6 +586,39 @@
sti
sysexit
+#ifdef DBG
+InvalidIrql:
+ /* Save current IRQL */
+ push fs:[KPCR_IRQL]
+
+ /* Set us at passive */
+ mov dword ptr fs:[KPCR_IRQL], 0
+ cli
+
+ /* Bugcheck */
+ push 0
+ push 0
+ push eax
+ push ebx
+ push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
+ call _KeBugCheckEx@20
+
+InvalidIndex:
+
+ /* Get the index and APC state */
+ movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
+ mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
+
+ /* Bugcheck */
+ push 0
+ push edx
+ push eax
+ push ebx
+ push APC_INDEX_MISMATCH
+ call _KeBugCheckEx@20
+ ret
+#endif
+
V86_Exit:
/* Move to EDX position */
add esp, KTRAP_FRAME_EDX