- Use MmUserProbeAddress in the system call handler to verify the parametes we got from user-mode are valid and return STATUS_ACCESS_VIOLATION if the check fails.

- Handle failure after PsConvertToGuiThread and return STATUS_INVALID_SYSTEM_SERVICE and/or FALSE and/or -1 on failure.
- Made MCE/XMMI interrupts unexpected on-boot.
- Removed KiTrapUnknown and used KiTrap0F (15) instead, which is the generic unexpected handler.

svn path=/trunk/; revision=20942
This commit is contained in:
Alex Ionescu 2006-01-17 22:41:39 +00:00
parent 419e7bb9d5
commit 12d35a7b84
2 changed files with 86 additions and 72 deletions

View file

@ -357,10 +357,12 @@ Author:
// NTSTATUS and Bugcheck Codes // NTSTATUS and Bugcheck Codes
// //
#ifdef __ASM__ #ifdef __ASM__
#define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C #define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258 #define STATUS_NO_CALLBACK_ACTIVE 0xC0000258
#define APC_INDEX_MISMATCH 1 #define APC_INDEX_MISMATCH 0x01
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A #define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
#define UNEXPECTED_KERNEL_MODE_TRAP 0x7F
#endif #endif
// //

View file

@ -16,8 +16,6 @@
* FIXMEs: * FIXMEs:
* - Figure out why ES/DS gets messed up in VMWare, when doing KiServiceExit only, * - Figure out why ES/DS gets messed up in VMWare, when doing KiServiceExit only,
* and only when called from user-mode, and returning to user-mode. * and only when called from user-mode, and returning to user-mode.
* - Use MmProbe when copying arguments to syscall.
* - Handle failure after PsConvertToGuiThread.
* - Figure out what the DEBUGEIP hack is for and how it can be moved away. * - Figure out what the DEBUGEIP hack is for and how it can be moved away.
* - Add DR macro/save and VM macro/save. * - Add DR macro/save and VM macro/save.
* - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion. * - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion.
@ -43,22 +41,22 @@ idt _KiTrap11, INT_32_DPL0 /* INT 0B: Segment Not Present (#NP) */
idt _KiTrap12, INT_32_DPL0 /* INT 0C: Stack Fault Exception (#SS) */ idt _KiTrap12, INT_32_DPL0 /* INT 0C: Stack Fault Exception (#SS) */
idt _KiTrap13, INT_32_DPL0 /* INT 0D: General Protection (#GP) */ idt _KiTrap13, INT_32_DPL0 /* INT 0D: General Protection (#GP) */
idt _KiTrap14, INT_32_DPL0 /* INT 0E: Page-Fault Exception (#PF) */ idt _KiTrap14, INT_32_DPL0 /* INT 0E: Page-Fault Exception (#PF) */
idt _KiTrap15, INT_32_DPL0 /* INT 0F: RESERVED */ idt _KiTrap15, INT_32_DPL0 /* INT 0F: RESERVED [FIXME: HBIRR HACK] */
idt _KiTrap16, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF) */ idt _KiTrap16, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF) */
idt _KiTrap17, INT_32_DPL0 /* INT 11: Align Check Exception (#AC) */ idt _KiTrap17, INT_32_DPL0 /* INT 11: Align Check Exception (#AC) */
idt _KiTrap18, INT_32_DPL0 /* INT 12: Machine Check Exception (#MC)*/ idt _KiTrap0F, INT_32_DPL0 /* INT 12: Machine Check Exception (#MC)*/
idt _KiTrap19, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF) */ idt _KiTrap0F, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF) */
.rept 22 .rept 22
idt _KiTrapUnknown, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS */ idt _KiTrap0F, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS */
.endr .endr
idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler */ idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler */
idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback Return */ idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback Return */
idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */ idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */
idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */ idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */
idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */ idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */
idt _KiTrapUnknown, INT_32_DPL0 /* INT 2F: RESERVED */ idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */
.rept 220 .rept 220
idt _KiTrapUnknown, INT_32_DPL0 /* INT 30-FF: UNDEFINED INTERRUPTS */ idt _KiTrap0F, INT_32_DPL0 /* INT 30-FF: UNDEFINED INTERRUPTS */
.endr .endr
/* System call entrypoints: */ /* System call entrypoints: */
@ -271,33 +269,28 @@ NoCountTable:
/* Allocate space on our stack */ /* Allocate space on our stack */
sub esp, ecx sub esp, ecx
/* /* Set the size of the arguments and the destination */
* Copy the arguments from the user stack to our stack
* FIXME: This needs to be probed with MmSystemRangeStart
*/
shr ecx, 2 shr ecx, 2
mov edi, esp mov edi, esp
/* Make sure we're within the User Probe Address */
cmp esi, _MmUserProbeAddress
jnb AccessViolation
CopyParams:
/* Copy the parameters */
rep movsd rep movsd
#ifdef DBG #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 * 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 * address of the "call ebx" below, find the last label before it and
* thinks that that's the start of the function. It will then check to see * thinks that that's the start of the function. It will then check to see
* if it starts with a standard function prolog (push ebp, mov ebp,esp). * if it starts with a standard function prolog (push ebp, mov ebp,esp1).
* When that standard function prolog is not found, it will stop the * When that standard function prolog is not found, it will stop the
* stack backtrace. Since we do want to backtrace into usermode, let's * stack backtrace. Since we do want to backtrace into usermode, let's
* make GDB happy and create a standard prolog. * make GDB happy and create a standard prolog.
*/ */
SkipCheck:
KiSystemService: KiSystemService:
push ebp push ebp
mov ebp,esp mov ebp,esp
@ -307,10 +300,11 @@ KiSystemService:
/* Do the System Call */ /* Do the System Call */
call ebx call ebx
AfterSysCall:
#ifdef DBG #ifdef DBG
/* Make sure the user-mode call didn't return at elevated IRQL */ /* Make sure the user-mode call didn't return at elevated IRQL */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz SkipCheck2 jz SkipCheck
mov esi, eax /* We need to save the syscall's return val */ mov esi, eax /* We need to save the syscall's return val */
call _KeGetCurrentIrql@0 call _KeGetCurrentIrql@0
or al, al or al, al
@ -329,7 +323,7 @@ KiSystemService:
jnz InvalidIndex jnz InvalidIndex
#endif #endif
SkipCheck2: SkipCheck:
/* Deallocate the kernel stack frame */ /* Deallocate the kernel stack frame */
mov esp, ebp mov esp, ebp
@ -363,7 +357,7 @@ _KiServiceExit:
KiBBTUnexpectedRange: KiBBTUnexpectedRange:
/* If this isn't a Win32K call, fail */ /* If this isn't a Win32K call, fail */
cmp ecx, 0x10 cmp ecx, SERVICE_TABLE_TEST
jne InvalidCall jne InvalidCall
/* Set up Win32K Table */ /* Set up Win32K Table */
@ -371,7 +365,10 @@ KiBBTUnexpectedRange:
push ebx push ebx
call _PsConvertToGuiThread@0 call _PsConvertToGuiThread@0
/* FIXME: Handle failure */ /* Check return code */
or eax, eax
/* Restore registers */
pop eax pop eax
pop edx pop edx
@ -379,8 +376,34 @@ KiBBTUnexpectedRange:
mov ebp, esp mov ebp, esp
mov [esi+KTHREAD_TRAP_FRAME], ebp mov [esi+KTHREAD_TRAP_FRAME], ebp
/* Try the Call again */ /* Try the Call again, if we suceeded */
jmp SharedCode jz SharedCode
/*
* The Shadow Table should have a special byte table which tells us
* whether we should return FALSE, -1 or STATUS_INVALID_SYSTEM_SERVICE.
*/
/* Get the table limit and base */
lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
/* Get the table address and add our index into the array */
lea edx, [edx+ecx*4]
and eax, SERVICE_NUMBER_MASK
add edx, eax
/* Find out what we should return */
movsx eax, byte ptr [edx]
or eax, eax
/* Return either 0 or -1, we've set it in EAX */
jle KeReturnFromSystemCall
/* Set STATUS_INVALID_SYSTEM_SERVICE */
mov eax, STATUS_INVALID_SYSTEM_SERVICE
jmp KeReturnFromSystemCall
InvalidCall: InvalidCall:
@ -388,6 +411,18 @@ InvalidCall:
mov eax, STATUS_INVALID_SYSTEM_SERVICE mov eax, STATUS_INVALID_SYSTEM_SERVICE
jmp KeReturnFromSystemCall jmp KeReturnFromSystemCall
AccessViolation:
/* Check if this came from kernel-mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
/* It's fine, go ahead with it */
jz CopyParams
/* Caller sent invalid parameters, fail here */
mov eax, STATUS_ACCESS_VIOLATION
jmp AfterSysCall
BadStack: BadStack:
/* Restore ESP0 stack */ /* Restore ESP0 stack */
@ -974,57 +1009,34 @@ _KiTrap17:
jne _Kei386EoiHelper@0 jne _Kei386EoiHelper@0
jmp _KiV86Complete jmp _KiV86Complete
_KiTrap18: _KiTrap0F:
/* Push error code */ /* Push error code */
push 0 push 0
/* Enter trap */ /* Enter trap */
TRAP_PROLOG(18) TRAP_PROLOG(15)
sti
/* Call the C exception handler */ /* Raise a fatal exception */
push 18 mov eax, 15
jmp _KiSystemFatalException
.func KiSystemFatalException
_KiSystemFatalException:
/* Push the trap frame */
push ebp push ebp
call _KiTrapHandler
add esp, 8
/* Check for v86 recovery */ /* Push empty parameters */
cmp eax, 1 push 0
push 0
/* Return to caller */
jne _Kei386EoiHelper@0
jmp _KiV86Complete
_KiTrap19:
/* Push error code */
push 0 push 0
/* Enter trap */ /* Push trap number and bugcheck code */
TRAP_PROLOG(19) push eax
push UNEXPECTED_KERNEL_MODE_TRAP
call _KeBugCheckWithTf@24
ret
.endfunc
/* Call the C exception handler */
push 19
push ebp
call _KiTrapHandler
add esp, 8
/* Check for v86 recovery */
cmp eax, 1
/* Return to caller */
jne _Kei386EoiHelper@0
jmp _KiV86Complete
_KiTrapUnknown:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(255)
/* Check for v86 recovery */
cmp eax, 1
/* Return to caller */
jne _Kei386EoiHelper@0
jmp _KiV86Complete