Hi again, I've quickly implemented the aforementioned idea of fixing the segment in the segfault handler when needed. I'm attaching my proposed patch.
Alessandro Il giorno mer, 30/01/2013 alle 16.44 +0100, Alessandro Pignotti ha scritto: > Hi everyone, > > I'm trying to get a specific game which employs a seemingly custom > protection scheme to work. The DRM does various bad things as usual, but > a very bad one is manipulating to GS segment selector and setting it to > a NULL segment. The GS segment is used by libc though in various ways > (stack protection and syscall support, and probably others). > > I managed to get the activation procedure to go further and further by > enclosing each offending syscall using the following 2 macros. > > #define SAFE_GS_START \ > do { \ > wine_set_gs(ntdll_get_thread_data()->gs); \ > do > > #define SAFE_GS_END \ > while(0); \ > } while(0) > > Still, this method is very cumbersome since system calls happens in many > places even outside of ntdll. Fixing the GS is also needed to support > sigsetjmp which is used by wine's exception handling. > > I'd like to ask for feedback about what would be a sane way of > supporting this application. A possible solution would be to modify > wine's segfault handler to check if the instruction has a GS prefix > (0x65 IIRC) and try to execute the instruction again after fixing the > GS. > > Please keep me in CC since I'm not subscribed to the ML. > > Regards, > Alessandro Pignotti
>From 35d5b875c7ca63845ddb68f1036f58d31ff4957e Mon Sep 17 00:00:00 2001 From: Alessandro Pignotti <a.pigno...@sssup.it> Date: Wed, 30 Jan 2013 17:09:15 +0100 Subject: [PATCH] Restore the GS selector when crashing (if needed) --- dlls/ntdll/signal_i386.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 4a83a70..8e9e46b 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -1863,6 +1863,14 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) return; } + /* special handling for segment faults of the GS segment */ + unsigned char* opcode=(unsigned char*)EIP_sig(context); + if (get_trap_code(context) == TRAP_x86_PROTFLT && *opcode==0x65) + { + GS_sig(context)=ntdll_get_thread_data()->gs; + return; + } + rec = setup_exception_record( context, stack, fs, gs, raise_segv_exception ); if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return; -- 1.7.10.4