Skip to content

Instantly share code, notes, and snippets.

@awesie
Last active April 28, 2020 17:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save awesie/13bb500acc565214b2bf2b639145a92e to your computer and use it in GitHub Desktop.
Save awesie/13bb500acc565214b2bf2b639145a92e to your computer and use it in GitHub Desktop.
Includes patches for 47198 and 45667.
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 67a785e..8e00d62 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -437,6 +437,8 @@ static wine_signal_handler handlers[256];
extern void DECLSPEC_NORETURN __wine_syscall_dispatcher( void );
extern NTSTATUS WINAPI __syscall_NtGetContextThread( HANDLE handle, CONTEXT *context );
+static int wine_cs;
+
/* convert from straight ASCII to Unicode without depending on the current codepage */
static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
{
@@ -885,7 +887,7 @@ static inline void * SIGNALFUNC init_handler( const ucontext_t *sigcontext, WORD
}
#endif
- if (!wine_ldt_is_system(CS_sig(sigcontext)) ||
+ if ((CS_sig(sigcontext) != wine_cs && !wine_ldt_is_system(CS_sig(sigcontext))) ||
!wine_ldt_is_system(SS_sig(sigcontext))) /* 16-bit mode */
{
/*
@@ -1576,7 +1578,7 @@ static inline DWORD is_privileged_instr( CONTEXT *context )
const BYTE *instr;
unsigned int prefix_count = 0;
- if (!wine_ldt_is_system( context->SegCs )) return 0;
+ if (context->SegCs != wine_cs && !wine_ldt_is_system( context->SegCs )) return 0;
instr = (BYTE *)context->Eip;
for (;;) switch(*instr)
@@ -1674,7 +1676,7 @@ static inline BOOL check_invalid_gs( CONTEXT *context )
WORD system_gs = x86_thread_data()->gs;
if (context->SegGs == system_gs) return FALSE;
- if (!wine_ldt_is_system( context->SegCs )) return FALSE;
+ if (context->SegCs != wine_cs && !wine_ldt_is_system( context->SegCs )) return 0;
/* only handle faults in system libraries */
if (virtual_is_valid_code_address( instr, 1 )) return FALSE;
@@ -1916,7 +1918,7 @@ static EXCEPTION_RECORD *setup_exception_record( ucontext_t *sigcontext, void *s
EIP_sig(sigcontext) = (DWORD)func;
/* clear single-step, direction, and align check flag */
EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
- CS_sig(sigcontext) = wine_get_cs();
+ CS_sig(sigcontext) = wine_cs;
DS_sig(sigcontext) = wine_get_ds();
ES_sig(sigcontext) = wine_get_es();
FS_sig(sigcontext) = wine_get_fs();
@@ -2394,6 +2396,32 @@ static void ldt_unlock(void)
else RtlLeaveCriticalSection( &ldt_section );
}
+#include <sys/mman.h>
+void signal_init_cs(void)
+{
+ static const BYTE int80_ret[] = { 0xcd, 0x80, 0xc3 };
+ void *sysinfo;
+ LDT_ENTRY entry;
+
+ if (!wine_cs)
+ {
+ wine_cs = wine_ldt_alloc_entries( 1 );
+
+ /* Overwrite VDSO to use int $0x80 instead of sysenter. */
+ asm ("mov %%gs:0x10, %0" : "=r" (sysinfo));
+ mprotect( (void *)((INT_PTR)sysinfo & ~0xfff), 0x1000, PROT_READ | PROT_EXEC | PROT_WRITE );
+ memcpy( sysinfo, int80_ret, sizeof(int80_ret));
+ mprotect( (void *)((INT_PTR)sysinfo & ~0xfff), 0x1000, PROT_READ | PROT_EXEC );
+ }
+
+ wine_ldt_set_base( &entry, 0 );
+ wine_ldt_set_limit( &entry, (UINT_PTR)-1 );
+ wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT );
+ wine_ldt_set_entry( wine_cs, &entry );
+
+ wine_set_cs( wine_cs );
+}
+
/**********************************************************************
* signal_alloc_thread
@@ -2433,6 +2461,7 @@ NTSTATUS signal_alloc_thread( TEB **teb )
status = STATUS_TOO_MANY_THREADS;
}
}
+
return status;
}
@@ -2479,6 +2508,8 @@ void signal_init_thread( TEB *teb )
wine_ldt_init_fs( thread_data->fs, &fs_entry );
thread_data->gs = wine_get_gs();
+ signal_init_cs();
+
#ifdef __GNUC__
__asm__ volatile ("fninit; fldcw %0" : : "m" (fpu_cw));
#else
diff --git a/include/wine/library.h b/include/wine/library.h
index 7395a11..56e7490 100644
--- a/include/wine/library.h
+++ b/include/wine/library.h
@@ -192,6 +192,7 @@ __DEFINE_SET_SEG(fs)
__DEFINE_SET_SEG(gs)
#undef __DEFINE_GET_SEG
#undef __DEFINE_SET_SEG
+extern void wine_set_cs(unsigned int);
#endif /* __i386__ */
diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c
index 3e7369f..66dec6c 100644
--- a/libs/wine/ldt.c
+++ b/libs/wine/ldt.c
@@ -460,6 +460,10 @@ __ASM_GLOBAL_FUNC( wine_get_es, "movw %es,%ax\n\tret" )
__ASM_GLOBAL_FUNC( wine_get_fs, "movw %fs,%ax\n\tret" )
__ASM_GLOBAL_FUNC( wine_get_gs, "movw %gs,%ax\n\tret" )
__ASM_GLOBAL_FUNC( wine_get_ss, "movw %ss,%ax\n\tret" )
+__ASM_GLOBAL_FUNC( wine_set_cs, "movl 4(%esp),%eax\n\t"
+ "xchg 0(%esp),%eax\n\t"
+ "push %eax\n\t"
+ "retf" )
__ASM_GLOBAL_FUNC( wine_set_fs, "movl 4(%esp),%eax\n\tmovw %ax,%fs\n\tret" )
__ASM_GLOBAL_FUNC( wine_set_gs, "movl 4(%esp),%eax\n\tmovw %ax,%gs\n\tret" )
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
index 72ffed8..c41f567 100644
--- a/libs/wine/wine.map
+++ b/libs/wine/wine.map
@@ -114,6 +114,7 @@ WINE_1.0
wine_mmap_remove_reserved_area;
wine_pthread_get_functions;
wine_pthread_set_functions;
+ wine_set_cs;
wine_set_fs;
wine_set_gs;
wine_switch_to_stack;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment