Alexandre Julliard : ntdll: Check for invalid %gs value in 32-bit code.
Alexandre Julliard
julliard at winehq.org
Tue Feb 12 13:58:12 CST 2013
Module: wine
Branch: master
Commit: 64ddb263d25dfceeeae8457a0131f1a2af292383
URL: http://source.winehq.org/git/wine.git/?a=commit;h=64ddb263d25dfceeeae8457a0131f1a2af292383
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Feb 12 15:21:15 2013 +0100
ntdll: Check for invalid %gs value in 32-bit code.
Suggested by Alessandro Pignotti.
---
dlls/ntdll/signal_i386.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 18fe3da..05ede34 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1507,6 +1507,47 @@ static inline DWORD is_privileged_instr( CONTEXT *context )
}
}
+/***********************************************************************
+ * check_invalid_gs
+ *
+ * Check for fault caused by invalid %gs value (some copy protection schemes mess with it).
+ */
+static inline BOOL check_invalid_gs( CONTEXT *context )
+{
+ unsigned int prefix_count = 0;
+ const BYTE *instr = (BYTE *)context->Eip;
+ WORD system_gs = ntdll_get_thread_data()->gs;
+
+ if (context->SegGs == system_gs) return FALSE;
+ if (!wine_ldt_is_system( context->SegCs )) return FALSE;
+ /* only handle faults in system libraries */
+ if (virtual_is_valid_code_address( instr, 1 )) return FALSE;
+
+ for (;;) switch(*instr)
+ {
+ /* instruction prefixes */
+ case 0x2e: /* %cs: */
+ case 0x36: /* %ss: */
+ case 0x3e: /* %ds: */
+ case 0x26: /* %es: */
+ case 0x64: /* %fs: */
+ case 0x66: /* opcode size */
+ case 0x67: /* addr size */
+ case 0xf0: /* lock */
+ case 0xf2: /* repne */
+ case 0xf3: /* repe */
+ if (++prefix_count >= 15) return FALSE;
+ instr++;
+ continue;
+ case 0x65: /* %gs: */
+ TRACE( "%04x/%04x at %p, fixing up\n", context->SegGs, system_gs, instr );
+ context->SegGs = system_gs;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
#include "pshpack1.h"
struct atl_thunk
@@ -1716,6 +1757,8 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
{
if (rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT && check_atl_thunk( rec, context ))
goto done;
+ if (rec->ExceptionInformation[1] == 0xffffffff && check_invalid_gs( context ))
+ goto done;
if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
rec->ExceptionInformation[0] )))
goto done;
More information about the wine-cvs
mailing list