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