From d2ba2fdc171008a6464911e20c3df7716bf0e30c Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 31 Aug 2006 04:10:33 +0000 Subject: [PATCH] - Implement more parts of the GPF Handler. - Add support for lazy loading. - QEMU + -kernel-qemu seems to work now. - Hack away the Win32k bug that's been there for ages (copy to user-mode from kernel-mode failing due to probe due to incorrect previous mode). It's not the right fix, but nobody seems to be willing to fix it, and it doesn't make anything less stable, sicne the actually copy is in SEH anyway. It opens a security vuln. (wow, not like we have 15000) in exchange for fixing dozens of win32k bugs and failures. svn path=/trunk/; revision=23832 --- reactos/lib/rtl/i386/zeromemory_asm.s | 61 ------------------ reactos/ntoskrnl/KrnlFun.c | 1 - reactos/ntoskrnl/ke/i386/trap.s | 69 ++++++++++++++++++--- reactos/subsystems/win32/win32k/misc/copy.c | 4 +- 4 files changed, 64 insertions(+), 71 deletions(-) delete mode 100644 reactos/lib/rtl/i386/zeromemory_asm.s diff --git a/reactos/lib/rtl/i386/zeromemory_asm.s b/reactos/lib/rtl/i386/zeromemory_asm.s deleted file mode 100644 index 79ef77793c4..00000000000 --- a/reactos/lib/rtl/i386/zeromemory_asm.s +++ /dev/null @@ -1,61 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: zeromemory_asm.S - * PURPOSE: Memory functions - * PROGRAMMERS: Patrick Baggett (baggett.patrick@gmail.com) - * Alex Ionescu (alex@relsoft.net) - * Magnus Olsen (magnusolsen@greatlord.com) - */ - -.intel_syntax noprefix - -/* GLOBALS ****************************************************************/ - -.globl _RtlZeroMemory@8 // (no bug) (max optimze code) - -/* FUNCTIONS ***************************************************************/ - -_RtlZeroMemory@8: - mov ecx,dword [esp + 8 ] // Length - cmp ecx,0// if (Length==0) goto .zero - je 3f - - pushad // Save all register on the stack - mov edi, dword [esp + (4 + 32)] // Destination - xor eax,eax // ZeroFillByte = 0 - -// code for take four byte each time it loop - mov ebx,ecx // temp_Length = Length - shr ecx,2// Length = Length / sizeof(ULONG) - jz 1f // if (Length==0) goto .1byte - - shl ecx,2// Length = Length * sizeof(ULONG) - sub ebx,ecx // temp_Length = temp_Length - Length// - jz 2f // if (temp_Length==0) goto .4byte - -// move 4byte and 1byte - shr ecx,2// Length = Length / sizeof(ULONG) - cld // clear d flag - rep stosd// while (Length!=0) { (ULONG *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 } - mov ecx,ebx // Length = temp_Length - rep stosb// while (Length!=0) { (UCHAR *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 } - popad // restore register - ret 8 // return - -// move 1byte -1: - mov ecx,dword [esp + (12 +32) ] // Length - cld // clear d flag - rep stosb// while (Length!=0) { (UCHAR *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 } - popad // restore register - ret 8 // return - -// move 4bytes -2: - shr ecx,2// Length = Length / sizeof(ULONG) - cld // clear d flag - rep stosd// while (Length!=0) { (ULONG *) Destination[Length-1]=ZeroFillByte// Legnth = Legnth - 1 } - popad // restore register -3: - ret 8 // return diff --git a/reactos/ntoskrnl/KrnlFun.c b/reactos/ntoskrnl/KrnlFun.c index 4bfe1eb4522..1c71debf330 100644 --- a/reactos/ntoskrnl/KrnlFun.c +++ b/reactos/ntoskrnl/KrnlFun.c @@ -28,7 +28,6 @@ // - Get rid of KiRosPrintAddress and use KiDumpParameterImages instead. // - Sanitize some context fields during conversions. // - Implement stack fault and segment fault handlers. -// - Implement kernel-mode GPF handler, possibly fixing below: // - 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. // - Add DR macro/save and VM macro/save. diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index 3f3a39ede50..20db7e996f6 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -1215,7 +1215,6 @@ _KiTrap13: /* Otherwise, something is very wrong, raise an exception */ sti - jmp $ mov ebx, [ebp+KTRAP_FRAME_EIP] mov esi, -1 mov eax, STATUS_ACCESS_VIOLATION @@ -1329,21 +1328,77 @@ NotCsGpf: test dword ptr [edx+4], RPL_MASK jz UserModeGpf - /* FIXME: Handle IRET back to user-mode */ + /* Setup trap frame to copy */ + mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4 + lea edx, [ebp+KTRAP_FRAME_ERROR_CODE] + +TrapCopy: + + /* Copy each field */ + mov eax, [edx] + mov [edx+12], eax + sub edx, 4 + loop TrapCopy + + /* Enable interrupts and adjust stack */ + sti + add esp, 12 + add ebp, 12 + + /* Setup exception record */ + mov ebx, [ebp+KTRAP_FRAME_EIP] + mov esi, [ebp+KTRAP_FRAME_ERROR_CODE] + and esi, 0xFFFF + mov eax, STATUS_ACCESS_VIOLATION + jmp _DispatchTwoParam + +MsrCheck: + + /* FIXME: Handle RDMSR/WRMSR */ int 3 jmp $ NotIretGpf: - /* FIXME: Handle RDMSR/WRMSR and lazy load */ - int 3 - jmp $ + /* Check if this was an MSR opcode */ + cmp al, 0xF + jz MsrCheck + + /* Check if DS is Ring 3 */ + cmp word ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK + jz CheckEs + + /* Otherwise, fix it up */ + mov dword ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK + jmp ExitGpfTrap + +CheckEs: + + /* Check if ES is Ring 3 */ + cmp word ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK + jz UserModeGpf + + /* Otherwise, fix it up */ + mov dword ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK + jmp ExitGpfTrap SegPopGpf: - /* Handle segment POP fault */ + /* Sanity check */ + lea eax, [ebp+KTRAP_FRAME_ESP] + cmp edx, eax + jz HandleSegPop int 3 - jmp $ + + /* Handle segment POP fault by setting it to 0 */ +HandleSegPop: + xor eax, eax + mov dword ptr [edx], eax + +ExitGpfTrap: + + /* Do a trap exit */ + TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoNotRestoreSegments, DoRestoreVolatiles, DoRestoreEverything UserModeGpf: diff --git a/reactos/subsystems/win32/win32k/misc/copy.c b/reactos/subsystems/win32/win32k/misc/copy.c index 288c2dcc7d6..bfa2568db4d 100644 --- a/reactos/subsystems/win32/win32k/misc/copy.c +++ b/reactos/subsystems/win32/win32k/misc/copy.c @@ -4,7 +4,7 @@ NTSTATUS _MmCopyFromCaller( PVOID Target, PVOID Source, UINT Bytes ) { NTSTATUS Status = STATUS_SUCCESS; _SEH_TRY { - ProbeForRead(Source,Bytes,1); + //ProbeForRead(Source,Bytes,1); RtlCopyMemory(Target,Source,Bytes); } _SEH_HANDLE { Status = _SEH_GetExceptionCode(); @@ -17,7 +17,7 @@ NTSTATUS _MmCopyToCaller( PVOID Target, PVOID Source, UINT Bytes ) { NTSTATUS Status = STATUS_SUCCESS; _SEH_TRY { - ProbeForWrite(Target,Bytes,1); + //ProbeForWrite(Target,Bytes,1); RtlCopyMemory(Target,Source,Bytes); } _SEH_HANDLE { Status = _SEH_GetExceptionCode();