mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Add patch to handle WRITECOPY memory protection properly.
This commit is contained in:
parent
7a36c29ef4
commit
108cd9f304
@ -35,7 +35,7 @@ Wine. All those differences are also documented on the
|
||||
Included bugfixes and improvements
|
||||
==================================
|
||||
|
||||
**Bugfixes and features included in the next upcoming release [9]:**
|
||||
**Bugfixes and features included in the next upcoming release [10]:**
|
||||
|
||||
* Correctly treat '.' when checking for empty directories ([Wine Bug #26272](http://bugs.winehq.org/show_bug.cgi?id=26272))
|
||||
* Do not fail when a used context is passed to wglShareLists ([Wine Bug #11436](http://bugs.winehq.org/show_bug.cgi?id=11436))
|
||||
@ -46,6 +46,7 @@ Included bugfixes and improvements
|
||||
* Support for IRichEditOle and ITextDocument support for ITextServices. ([Wine Bug #17042](http://bugs.winehq.org/show_bug.cgi?id=17042))
|
||||
* Unity3D Editor requires ProductId registry value ([Wine Bug #36964](http://bugs.winehq.org/show_bug.cgi?id=36964))
|
||||
* Update a XIM candidate position when cursor location changes ([Wine Bug #30938](http://bugs.winehq.org/show_bug.cgi?id=30938))
|
||||
* Voobly expects correct handling of WRITECOPY memory protection ([Wine Bug #29384](http://bugs.winehq.org/show_bug.cgi?id=29384))
|
||||
|
||||
|
||||
**Bugs fixed in Wine-Compholio 1.7.27 [63]:**
|
||||
|
@ -50,6 +50,7 @@ PATCHLIST := \
|
||||
ntdll-Heap_FreeLists.ok \
|
||||
ntdll-Junction_Points.ok \
|
||||
ntdll-Pipe_SpecialCharacters.ok \
|
||||
ntdll-WRITECOPY.ok \
|
||||
ntdll-loader_EntryPoint.ok \
|
||||
ntoskrnl-Irp_Status.ok \
|
||||
quartz-MediaSeeking_Positions.ok \
|
||||
@ -739,6 +740,26 @@ ntdll-Pipe_SpecialCharacters.ok:
|
||||
echo '+ { "ntdll-Pipe_SpecialCharacters", "Michael Müller", "Allow special characters in pipe names." },'; \
|
||||
) > ntdll-Pipe_SpecialCharacters.ok
|
||||
|
||||
# Patchset ntdll-WRITECOPY
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Change WRITECOPY memory protection to WRITE on first write. [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/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
|
||||
# |
|
||||
.INTERMEDIATE: ntdll-WRITECOPY.ok
|
||||
ntdll-WRITECOPY.ok:
|
||||
$(call APPLY_FILE,ntdll-WRITECOPY/0001-ntdll-Change-WRITECOPY-memory-protection-to-WRITE-on.patch)
|
||||
@( \
|
||||
echo '+ { "ntdll-WRITECOPY", "Michael Müller", "Change WRITECOPY memory protection to WRITE on first write." },'; \
|
||||
) > ntdll-WRITECOPY.ok
|
||||
|
||||
# Patchset ntdll-loader_EntryPoint
|
||||
# |
|
||||
# | Included patches:
|
||||
|
@ -0,0 +1,261 @@
|
||||
From c4669a7173ca193f86a4d3e8bc24eb73b527f7f0 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/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 | 25 ++++++++++++++++-------
|
||||
9 files changed, 93 insertions(+), 17 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/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..54d64e1 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;
|
||||
+#endif
|
||||
if (vprot & VPROT_WRITEWATCH) prot &= ~PROT_WRITE;
|
||||
}
|
||||
if (!prot) prot = PROT_NONE;
|
||||
@@ -1522,21 +1527,27 @@ 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) && ((view->protect & VPROT_WRITEWATCH) ||
|
||||
+ (*vprot & VPROT_WRITECOPY)))
|
||||
{
|
||||
if (*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
|
||||
|
4
patches/ntdll-WRITECOPY/definition
Normal file
4
patches/ntdll-WRITECOPY/definition
Normal file
@ -0,0 +1,4 @@
|
||||
Author: Michael Müller
|
||||
Subject: Change WRITECOPY memory protection to WRITE on first write.
|
||||
Revision: 1
|
||||
Fixes: [29384] Voobly expects correct handling of WRITECOPY memory protection
|
Loading…
x
Reference in New Issue
Block a user