mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
ntdll-WRITECOPY: Fix some additional issues, disable this patch by default since it might trigger additional Wine bugs.
This commit is contained in:
parent
7f43d57d01
commit
e273769702
@ -742,21 +742,28 @@ ntdll-Pipe_SpecialCharacters.ok:
|
||||
# Patchset ntdll-WRITECOPY
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Change WRITECOPY memory protection to WRITE on first write. [rev 2, by Michael Müller]
|
||||
# | * Change WRITECOPY memory protection to WRITE on first write. [rev 3, by Michael Müller]
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#29384] Voobly expects correct handling of WRITECOPY memory protection
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/tests/virtual.c, dlls/ntdll/loader.c, dlls/ntdll/ntdll_misc.h, dlls/ntdll/signal_arm.c,
|
||||
# | dlls/ntdll/signal_arm64.c, dlls/ntdll/signal_i386.c, dlls/ntdll/signal_powerpc.c, dlls/ntdll/signal_x86_64.c,
|
||||
# | dlls/ntdll/thread.c, dlls/ntdll/virtual.c
|
||||
# | * dlls/advapi32/crypt.c, dlls/kernel32/tests/virtual.c, dlls/ntdll/loader.c, dlls/ntdll/ntdll_misc.h, dlls/ntdll/server.c,
|
||||
# | dlls/ntdll/signal_arm.c, dlls/ntdll/signal_arm64.c, dlls/ntdll/signal_i386.c, dlls/ntdll/signal_powerpc.c,
|
||||
# | dlls/ntdll/signal_x86_64.c, dlls/ntdll/thread.c, dlls/ntdll/virtual.c
|
||||
# |
|
||||
.INTERMEDIATE: ntdll-WRITECOPY.ok
|
||||
ntdll-WRITECOPY.ok:
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0001-ntdll-Change-WRITECOPY-memory-protection-to-WRITE-on.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0001-ntdll-Trigger-write-watches-before-passing-userdata-.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0002-advapi-Trigger-write-watches-before-passing-userdata.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0003-ntdll-Fix-handling-of-page-fault-if-a-guard-page-and.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0004-ntdll-Avoid-race-condition-if-two-threads-trigger-a-.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0005-ntdll-Wait-until-builtin-dlls-are-unloaded-before-re.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0006-ntdll-Setup-a-temporary-signal-handler-during-proces.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0007-ntdll-Properly-handle-PAGE_WRITECOPY-protection.patch)
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0008-ntdll-Only-enable-true-WRITECOPY-protection-when-a-s.patch)
|
||||
@( \
|
||||
echo '+ { "ntdll-WRITECOPY", "Michael Müller", "Change WRITECOPY memory protection to WRITE on first write. [rev 2]" },'; \
|
||||
echo '+ { "ntdll-WRITECOPY", "Michael Müller", "Change WRITECOPY memory protection to WRITE on first write. [rev 3]" },'; \
|
||||
) > ntdll-WRITECOPY.ok
|
||||
|
||||
# Patchset ntdll-loader_EntryPoint
|
||||
|
@ -1,276 +0,0 @@
|
||||
From fd0671380f0770d071dfc203034e58b6e6f86aff Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Wed, 1 Oct 2014 00:43:05 +0200
|
||||
Subject: ntdll: Change WRITECOPY memory protection to WRITE on first write
|
||||
access.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 12 ++---------
|
||||
dlls/ntdll/loader.c | 2 +-
|
||||
dlls/ntdll/ntdll_misc.h | 1 +
|
||||
dlls/ntdll/signal_arm.c | 6 ++++++
|
||||
dlls/ntdll/signal_arm64.c | 6 ++++++
|
||||
dlls/ntdll/signal_i386.c | 47 +++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/signal_powerpc.c | 6 ++++++
|
||||
dlls/ntdll/signal_x86_64.c | 6 ++++++
|
||||
dlls/ntdll/thread.c | 1 +
|
||||
dlls/ntdll/virtual.c | 26 ++++++++++++++++--------
|
||||
10 files changed, 94 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 0955d30..5b81e38 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -2038,11 +2038,7 @@ todo_wine
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = VirtualQuery(base, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed %d\n", GetLastError());
|
||||
- /* FIXME: remove the condition below once Wine is fixed */
|
||||
- if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
|
||||
- todo_wine ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
|
||||
- else
|
||||
- ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
|
||||
+ ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2056,11 +2052,7 @@ todo_wine
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
|
||||
ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
|
||||
- /* FIXME: remove the condition below once Wine is fixed */
|
||||
- if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
|
||||
- todo_wine ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
|
||||
- else
|
||||
- ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
|
||||
+ ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
|
||||
}
|
||||
|
||||
UnmapViewOfFile(base);
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 18ae29c..f0fb1f2 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -2641,8 +2641,8 @@ static void free_modref( WINE_MODREF *wm )
|
||||
|
||||
free_tls_slot( &wm->ldr );
|
||||
RtlReleaseActivationContext( wm->ldr.ActivationContext );
|
||||
- NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
|
||||
if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
|
||||
+ NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
|
||||
if (cached_modref == wm) cached_modref = NULL;
|
||||
RtlFreeUnicodeString( &wm->ldr.FullDllName );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, wm->deps );
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 4370084..53e6b55 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -67,6 +67,7 @@ extern NTSTATUS signal_alloc_thread( TEB **teb ) DECLSPEC_HIDDEN;
|
||||
extern void signal_free_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||
extern void signal_init_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||
extern void signal_init_process(void) DECLSPEC_HIDDEN;
|
||||
+extern void signal_init_early(void) DECLSPEC_HIDDEN;
|
||||
extern void version_init( const WCHAR *appname ) DECLSPEC_HIDDEN;
|
||||
extern void debug_init(void) DECLSPEC_HIDDEN;
|
||||
extern HANDLE thread_init(void) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
|
||||
index e3ae7bd..1d79b3d 100644
|
||||
--- a/dlls/ntdll/signal_arm.c
|
||||
+++ b/dlls/ntdll/signal_arm.c
|
||||
@@ -930,6 +930,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* __wine_enter_vm86 (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
|
||||
index 8c8f7af..483bc85 100644
|
||||
--- a/dlls/ntdll/signal_arm64.c
|
||||
+++ b/dlls/ntdll/signal_arm64.c
|
||||
@@ -791,6 +791,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* __wine_enter_vm86 (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
|
||||
index 12aa5a4..d24e3bf 100644
|
||||
--- a/dlls/ntdll/signal_i386.c
|
||||
+++ b/dlls/ntdll/signal_i386.c
|
||||
@@ -1949,6 +1949,30 @@ static void usr2_handler( int signal, siginfo_t *siginfo, void *sigcontext )
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
+ * segv_handler_early
|
||||
+ *
|
||||
+ * Handler for SIGSEGV and related errors. Used only during the initialization
|
||||
+ * of the process to handle virtual faults.
|
||||
+ */
|
||||
+static void segv_handler_early( int signal, siginfo_t *siginfo, void *sigcontext )
|
||||
+{
|
||||
+ WORD fs, gs;
|
||||
+ ucontext_t *context = sigcontext;
|
||||
+ init_handler( sigcontext, &fs, &gs );
|
||||
+
|
||||
+ switch(get_trap_code(context))
|
||||
+ {
|
||||
+ case TRAP_x86_PAGEFLT: /* Page fault */
|
||||
+ if (!virtual_handle_fault( siginfo->si_addr, (get_error_code(context) >> 1) & 0x09 ))
|
||||
+ return;
|
||||
+ /* fall-through */
|
||||
+ default:
|
||||
+ WINE_ERR( "Got unexpected trap %d during process initialization\n", get_trap_code(context) );
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**********************************************************************
|
||||
* segv_handler
|
||||
*
|
||||
* Handler for SIGSEGV and related errors.
|
||||
@@ -2371,6 +2395,29 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+ struct sigaction sig_act;
|
||||
+
|
||||
+ sig_act.sa_mask = server_block_set;
|
||||
+ sig_act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||
+#ifdef SA_ONSTACK
|
||||
+ sig_act.sa_flags |= SA_ONSTACK;
|
||||
+#endif
|
||||
+#ifdef __ANDROID__
|
||||
+ sig_act.sa_flags |= SA_RESTORER;
|
||||
+ sig_act.sa_restorer = rt_sigreturn;
|
||||
+#endif
|
||||
+ sig_act.sa_sigaction = segv_handler_early;
|
||||
+ if (sigaction( SIGSEGV, &sig_act, NULL ) == -1)
|
||||
+ {
|
||||
+ perror("sigaction");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+}
|
||||
|
||||
#ifdef __HAVE_VM86
|
||||
/**********************************************************************
|
||||
diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c
|
||||
index 0fca342..5d1d756 100644
|
||||
--- a/dlls/ntdll/signal_powerpc.c
|
||||
+++ b/dlls/ntdll/signal_powerpc.c
|
||||
@@ -1048,6 +1048,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* __wine_enter_vm86 (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
|
||||
index 05581c2..22da5d6 100644
|
||||
--- a/dlls/ntdll/signal_x86_64.c
|
||||
+++ b/dlls/ntdll/signal_x86_64.c
|
||||
@@ -2576,6 +2576,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* RtlAddFunctionTable (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
|
||||
index c8461b0..a2937c2 100644
|
||||
--- a/dlls/ntdll/thread.c
|
||||
+++ b/dlls/ntdll/thread.c
|
||||
@@ -221,6 +221,7 @@ HANDLE thread_init(void)
|
||||
static struct debug_info debug_info; /* debug info for initial thread */
|
||||
|
||||
virtual_init();
|
||||
+ signal_init_early();
|
||||
|
||||
/* reserve space for shared user data */
|
||||
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 4819d2d..47654f4 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -179,8 +179,13 @@ static int VIRTUAL_GetUnixProt( BYTE vprot )
|
||||
{
|
||||
if (vprot & VPROT_READ) prot |= PROT_READ;
|
||||
if (vprot & VPROT_WRITE) prot |= PROT_WRITE | PROT_READ;
|
||||
- if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE | PROT_READ;
|
||||
if (vprot & VPROT_EXEC) prot |= PROT_EXEC | PROT_READ;
|
||||
+#if defined(__i386__)
|
||||
+ if (vprot & VPROT_WRITECOPY) prot &= ~PROT_WRITE;
|
||||
+#else
|
||||
+ /* FIXME: Architecture needs implementation of signal_init_early. */
|
||||
+ if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE | PROT_READ;
|
||||
+#endif
|
||||
if (vprot & VPROT_WRITEWATCH) prot &= ~PROT_WRITE;
|
||||
}
|
||||
if (!prot) prot = PROT_NONE;
|
||||
@@ -1522,21 +1527,26 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
|
||||
{
|
||||
void *page = ROUND_ADDR( addr, page_mask );
|
||||
BYTE *vprot = &view->prot[((const char *)page - (const char *)view->base) >> page_shift];
|
||||
- if (*vprot & VPROT_GUARD)
|
||||
- {
|
||||
- VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
|
||||
- ret = STATUS_GUARD_PAGE_VIOLATION;
|
||||
- }
|
||||
- if ((err & EXCEPTION_WRITE_FAULT) && (view->protect & VPROT_WRITEWATCH))
|
||||
+ if (err & EXCEPTION_WRITE_FAULT)
|
||||
{
|
||||
- if (*vprot & VPROT_WRITEWATCH)
|
||||
+ if ((view->protect & VPROT_WRITEWATCH) && (*vprot & VPROT_WRITEWATCH))
|
||||
{
|
||||
*vprot &= ~VPROT_WRITEWATCH;
|
||||
VIRTUAL_SetProt( view, page, page_size, *vprot );
|
||||
}
|
||||
+ if (*vprot & VPROT_WRITECOPY)
|
||||
+ {
|
||||
+ *vprot = (*vprot & ~VPROT_WRITECOPY) | VPROT_WRITE;
|
||||
+ VIRTUAL_SetProt( view, page, page_size, *vprot );
|
||||
+ }
|
||||
/* ignore fault if page is writable now */
|
||||
if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS;
|
||||
}
|
||||
+ if (*vprot & VPROT_GUARD)
|
||||
+ {
|
||||
+ VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
|
||||
+ ret = STATUS_GUARD_PAGE_VIOLATION;
|
||||
+ }
|
||||
}
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
return ret;
|
||||
--
|
||||
1.9.1
|
||||
|
@ -0,0 +1,32 @@
|
||||
From 9dd581f7b7013b9bc26894292f0fffc493caebdd Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:35:44 +0200
|
||||
Subject: ntdll: Trigger write watches before passing userdata pointer to
|
||||
wait_reply.
|
||||
|
||||
---
|
||||
dlls/ntdll/server.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
|
||||
index aabda4f..4d5d4ba 100644
|
||||
--- a/dlls/ntdll/server.c
|
||||
+++ b/dlls/ntdll/server.c
|
||||
@@ -292,6 +292,14 @@ unsigned int wine_server_call( void *req_ptr )
|
||||
sigset_t old_set;
|
||||
unsigned int ret;
|
||||
|
||||
+ /* trigger write watches, otherwise read() might return EFAULT */
|
||||
+ if (req->u.req.request_header.reply_size &&
|
||||
+ !virtual_check_buffer_for_write( req->reply_data, req->u.req.request_header.reply_size ))
|
||||
+ {
|
||||
+ ret = STATUS_ACCESS_VIOLATION;
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
|
||||
ret = send_request( req );
|
||||
if (!ret) ret = wait_reply( req );
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 7d9f628d8fa776d60c1f81d88cd1730c65d2f349 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:38:27 +0200
|
||||
Subject: advapi: Trigger write watches before passing userdata pointer to read
|
||||
syscall.
|
||||
|
||||
---
|
||||
dlls/advapi32/crypt.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c
|
||||
index b2be5e3..50502b8 100644
|
||||
--- a/dlls/advapi32/crypt.c
|
||||
+++ b/dlls/advapi32/crypt.c
|
||||
@@ -2378,7 +2378,8 @@ BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
|
||||
dev_random = open("/dev/urandom", O_RDONLY);
|
||||
if (dev_random != -1)
|
||||
{
|
||||
- if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
|
||||
+ if (!IsBadWritePtr( pbBuffer, dwLen ) &&
|
||||
+ read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
|
||||
{
|
||||
close(dev_random);
|
||||
return TRUE;
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From e01c439ea2f8af11a0ebefd23cabf59e0864c142 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:48:16 +0200
|
||||
Subject: ntdll: Fix handling of page fault if a guard page and write watch is
|
||||
triggered at the same time.
|
||||
|
||||
---
|
||||
dlls/ntdll/virtual.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 4819d2d..f8a5dd3 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -1522,11 +1522,6 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
|
||||
{
|
||||
void *page = ROUND_ADDR( addr, page_mask );
|
||||
BYTE *vprot = &view->prot[((const char *)page - (const char *)view->base) >> page_shift];
|
||||
- if (*vprot & VPROT_GUARD)
|
||||
- {
|
||||
- VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
|
||||
- ret = STATUS_GUARD_PAGE_VIOLATION;
|
||||
- }
|
||||
if ((err & EXCEPTION_WRITE_FAULT) && (view->protect & VPROT_WRITEWATCH))
|
||||
{
|
||||
if (*vprot & VPROT_WRITEWATCH)
|
||||
@@ -1537,6 +1532,11 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
|
||||
/* ignore fault if page is writable now */
|
||||
if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS;
|
||||
}
|
||||
+ if (*vprot & VPROT_GUARD)
|
||||
+ {
|
||||
+ VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
|
||||
+ ret = STATUS_GUARD_PAGE_VIOLATION;
|
||||
+ }
|
||||
}
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
return ret;
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 7bec7a1bbe62894ed24a07fb7cb2af6a1a496210 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:49:51 +0200
|
||||
Subject: ntdll: Avoid race-condition if two threads trigger a write watch at
|
||||
exactly the same time.
|
||||
|
||||
---
|
||||
dlls/ntdll/virtual.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index f8a5dd3..0864c24 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -1522,9 +1522,9 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
|
||||
{
|
||||
void *page = ROUND_ADDR( addr, page_mask );
|
||||
BYTE *vprot = &view->prot[((const char *)page - (const char *)view->base) >> page_shift];
|
||||
- if ((err & EXCEPTION_WRITE_FAULT) && (view->protect & VPROT_WRITEWATCH))
|
||||
+ if (err & EXCEPTION_WRITE_FAULT)
|
||||
{
|
||||
- if (*vprot & VPROT_WRITEWATCH)
|
||||
+ if ((view->protect & VPROT_WRITEWATCH) && (*vprot & VPROT_WRITEWATCH))
|
||||
{
|
||||
*vprot &= ~VPROT_WRITEWATCH;
|
||||
VIRTUAL_SetProt( view, page, page_size, *vprot );
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,27 @@
|
||||
From bcf2dbbc2b5a3551ab2db7ed6d49b1d34c8067d7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:51:51 +0200
|
||||
Subject: ntdll: Wait until builtin dlls are unloaded before releasing the
|
||||
virtual view.
|
||||
|
||||
---
|
||||
dlls/ntdll/loader.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 18ae29c..f0fb1f2 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -2641,8 +2641,8 @@ static void free_modref( WINE_MODREF *wm )
|
||||
|
||||
free_tls_slot( &wm->ldr );
|
||||
RtlReleaseActivationContext( wm->ldr.ActivationContext );
|
||||
- NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
|
||||
if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
|
||||
+ NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
|
||||
if (cached_modref == wm) cached_modref = NULL;
|
||||
RtlFreeUnicodeString( &wm->ldr.FullDllName );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, wm->deps );
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,176 @@
|
||||
From 8237dc994163a63581b9a5414facdab0da897d59 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:53:22 +0200
|
||||
Subject: ntdll: Setup a temporary signal handler during process startup to
|
||||
handle page faults.
|
||||
|
||||
---
|
||||
dlls/ntdll/ntdll_misc.h | 1 +
|
||||
dlls/ntdll/signal_arm.c | 6 ++++++
|
||||
dlls/ntdll/signal_arm64.c | 6 ++++++
|
||||
dlls/ntdll/signal_i386.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/signal_powerpc.c | 6 ++++++
|
||||
dlls/ntdll/signal_x86_64.c | 6 ++++++
|
||||
dlls/ntdll/thread.c | 1 +
|
||||
7 files changed, 73 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 4370084..53e6b55 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -67,6 +67,7 @@ extern NTSTATUS signal_alloc_thread( TEB **teb ) DECLSPEC_HIDDEN;
|
||||
extern void signal_free_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||
extern void signal_init_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||
extern void signal_init_process(void) DECLSPEC_HIDDEN;
|
||||
+extern void signal_init_early(void) DECLSPEC_HIDDEN;
|
||||
extern void version_init( const WCHAR *appname ) DECLSPEC_HIDDEN;
|
||||
extern void debug_init(void) DECLSPEC_HIDDEN;
|
||||
extern HANDLE thread_init(void) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
|
||||
index e3ae7bd..1d79b3d 100644
|
||||
--- a/dlls/ntdll/signal_arm.c
|
||||
+++ b/dlls/ntdll/signal_arm.c
|
||||
@@ -930,6 +930,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* __wine_enter_vm86 (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
|
||||
index 8c8f7af..483bc85 100644
|
||||
--- a/dlls/ntdll/signal_arm64.c
|
||||
+++ b/dlls/ntdll/signal_arm64.c
|
||||
@@ -791,6 +791,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* __wine_enter_vm86 (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
|
||||
index 12aa5a4..d24e3bf 100644
|
||||
--- a/dlls/ntdll/signal_i386.c
|
||||
+++ b/dlls/ntdll/signal_i386.c
|
||||
@@ -1949,6 +1949,30 @@ static void usr2_handler( int signal, siginfo_t *siginfo, void *sigcontext )
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
+ * segv_handler_early
|
||||
+ *
|
||||
+ * Handler for SIGSEGV and related errors. Used only during the initialization
|
||||
+ * of the process to handle virtual faults.
|
||||
+ */
|
||||
+static void segv_handler_early( int signal, siginfo_t *siginfo, void *sigcontext )
|
||||
+{
|
||||
+ WORD fs, gs;
|
||||
+ ucontext_t *context = sigcontext;
|
||||
+ init_handler( sigcontext, &fs, &gs );
|
||||
+
|
||||
+ switch(get_trap_code(context))
|
||||
+ {
|
||||
+ case TRAP_x86_PAGEFLT: /* Page fault */
|
||||
+ if (!virtual_handle_fault( siginfo->si_addr, (get_error_code(context) >> 1) & 0x09 ))
|
||||
+ return;
|
||||
+ /* fall-through */
|
||||
+ default:
|
||||
+ WINE_ERR( "Got unexpected trap %d during process initialization\n", get_trap_code(context) );
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**********************************************************************
|
||||
* segv_handler
|
||||
*
|
||||
* Handler for SIGSEGV and related errors.
|
||||
@@ -2371,6 +2395,29 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+ struct sigaction sig_act;
|
||||
+
|
||||
+ sig_act.sa_mask = server_block_set;
|
||||
+ sig_act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||
+#ifdef SA_ONSTACK
|
||||
+ sig_act.sa_flags |= SA_ONSTACK;
|
||||
+#endif
|
||||
+#ifdef __ANDROID__
|
||||
+ sig_act.sa_flags |= SA_RESTORER;
|
||||
+ sig_act.sa_restorer = rt_sigreturn;
|
||||
+#endif
|
||||
+ sig_act.sa_sigaction = segv_handler_early;
|
||||
+ if (sigaction( SIGSEGV, &sig_act, NULL ) == -1)
|
||||
+ {
|
||||
+ perror("sigaction");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+}
|
||||
|
||||
#ifdef __HAVE_VM86
|
||||
/**********************************************************************
|
||||
diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c
|
||||
index 0fca342..5d1d756 100644
|
||||
--- a/dlls/ntdll/signal_powerpc.c
|
||||
+++ b/dlls/ntdll/signal_powerpc.c
|
||||
@@ -1048,6 +1048,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* __wine_enter_vm86 (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
|
||||
index 05581c2..22da5d6 100644
|
||||
--- a/dlls/ntdll/signal_x86_64.c
|
||||
+++ b/dlls/ntdll/signal_x86_64.c
|
||||
@@ -2576,6 +2576,12 @@ void signal_init_process(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+/**********************************************************************
|
||||
+ * signal_init_early
|
||||
+ */
|
||||
+void signal_init_early(void)
|
||||
+{
|
||||
+}
|
||||
|
||||
/**********************************************************************
|
||||
* RtlAddFunctionTable (NTDLL.@)
|
||||
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
|
||||
index c8461b0..a2937c2 100644
|
||||
--- a/dlls/ntdll/thread.c
|
||||
+++ b/dlls/ntdll/thread.c
|
||||
@@ -221,6 +221,7 @@ HANDLE thread_init(void)
|
||||
static struct debug_info debug_info; /* debug info for initial thread */
|
||||
|
||||
virtual_init();
|
||||
+ signal_init_early();
|
||||
|
||||
/* reserve space for shared user data */
|
||||
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,74 @@
|
||||
From 48c067d93de63a0dacbeaf1b962fa614f6015598 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 02:56:08 +0200
|
||||
Subject: ntdll: Properly handle PAGE_WRITECOPY protection.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 12 ++----------
|
||||
dlls/ntdll/virtual.c | 12 +++++++++++-
|
||||
2 files changed, 13 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 0955d30..5b81e38 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -2038,11 +2038,7 @@ todo_wine
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = VirtualQuery(base, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed %d\n", GetLastError());
|
||||
- /* FIXME: remove the condition below once Wine is fixed */
|
||||
- if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
|
||||
- todo_wine ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
|
||||
- else
|
||||
- ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
|
||||
+ ok(info.Protect == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_after_write);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2056,11 +2052,7 @@ todo_wine
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
|
||||
ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
|
||||
- /* FIXME: remove the condition below once Wine is fixed */
|
||||
- if (td[i].prot == PAGE_WRITECOPY || td[i].prot == PAGE_EXECUTE_WRITECOPY)
|
||||
- todo_wine ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
|
||||
- else
|
||||
- ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
|
||||
+ ok(old_prot == td[i].prot_after_write, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_after_write);
|
||||
}
|
||||
|
||||
UnmapViewOfFile(base);
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 0864c24..47654f4 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -179,8 +179,13 @@ static int VIRTUAL_GetUnixProt( BYTE vprot )
|
||||
{
|
||||
if (vprot & VPROT_READ) prot |= PROT_READ;
|
||||
if (vprot & VPROT_WRITE) prot |= PROT_WRITE | PROT_READ;
|
||||
- if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE | PROT_READ;
|
||||
if (vprot & VPROT_EXEC) prot |= PROT_EXEC | PROT_READ;
|
||||
+#if defined(__i386__)
|
||||
+ if (vprot & VPROT_WRITECOPY) prot &= ~PROT_WRITE;
|
||||
+#else
|
||||
+ /* FIXME: Architecture needs implementation of signal_init_early. */
|
||||
+ if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE | PROT_READ;
|
||||
+#endif
|
||||
if (vprot & VPROT_WRITEWATCH) prot &= ~PROT_WRITE;
|
||||
}
|
||||
if (!prot) prot = PROT_NONE;
|
||||
@@ -1529,6 +1534,11 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
|
||||
*vprot &= ~VPROT_WRITEWATCH;
|
||||
VIRTUAL_SetProt( view, page, page_size, *vprot );
|
||||
}
|
||||
+ if (*vprot & VPROT_WRITECOPY)
|
||||
+ {
|
||||
+ *vprot = (*vprot & ~VPROT_WRITECOPY) | VPROT_WRITE;
|
||||
+ VIRTUAL_SetProt( view, page, page_size, *vprot );
|
||||
+ }
|
||||
/* ignore fault if page is writable now */
|
||||
if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS;
|
||||
}
|
||||
--
|
||||
2.1.1
|
||||
|
@ -0,0 +1,54 @@
|
||||
From d333e51c9996681756ceef30322bf20ae907cd68 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 4 Oct 2014 03:22:09 +0200
|
||||
Subject: ntdll: Only enable true WRITECOPY protection when a special
|
||||
environment variable is set.
|
||||
|
||||
---
|
||||
dlls/ntdll/virtual.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 47654f4..6fad8f7 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -166,6 +166,21 @@ static const char *VIRTUAL_GetProtStr( BYTE prot )
|
||||
return buffer;
|
||||
}
|
||||
|
||||
+/* This might look like a hack, but it actually isn't - the 'experimental' version
|
||||
+ * is correct, but it already has revealed a couple of additional Wine bugs, which
|
||||
+ * were not triggered before, and there are probably some more.
|
||||
+ * To avoid breaking Wine for everyone, the new correct implementation has to be
|
||||
+ * manually enabled, until it is tested a bit more. */
|
||||
+static inline BOOL experimental_WRITECOPY( void )
|
||||
+{
|
||||
+ static int enabled = -1;
|
||||
+ if (enabled == -1)
|
||||
+ {
|
||||
+ const char *str = getenv("COMPHOLIO_WRITECOPY");
|
||||
+ enabled = str && (atoi(str) != 0);
|
||||
+ }
|
||||
+ return enabled;
|
||||
+}
|
||||
|
||||
/***********************************************************************
|
||||
* VIRTUAL_GetUnixProt
|
||||
@@ -181,7 +196,13 @@ static int VIRTUAL_GetUnixProt( BYTE vprot )
|
||||
if (vprot & VPROT_WRITE) prot |= PROT_WRITE | PROT_READ;
|
||||
if (vprot & VPROT_EXEC) prot |= PROT_EXEC | PROT_READ;
|
||||
#if defined(__i386__)
|
||||
- if (vprot & VPROT_WRITECOPY) prot &= ~PROT_WRITE;
|
||||
+ if (vprot & VPROT_WRITECOPY)
|
||||
+ {
|
||||
+ if (experimental_WRITECOPY())
|
||||
+ prot &= ~PROT_WRITE;
|
||||
+ else
|
||||
+ prot |= PROT_WRITE | PROT_READ;
|
||||
+ }
|
||||
#else
|
||||
/* FIXME: Architecture needs implementation of signal_init_early. */
|
||||
if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE | PROT_READ;
|
||||
--
|
||||
2.1.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
Author: Michael Müller
|
||||
Subject: Change WRITECOPY memory protection to WRITE on first write.
|
||||
Revision: 2
|
||||
Revision: 3
|
||||
Fixes: [29384] Voobly expects correct handling of WRITECOPY memory protection
|
||||
|
Loading…
Reference in New Issue
Block a user