diff --git a/debian/changelog b/debian/changelog index 4f8b99cf..2e19a874 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ wine-staging (1.7.34) UNRELEASED; urgency=low * Avoid duplicate wined3d specfile by adding PARENTSPEC Makefile argument. * Fix issue in DOS Attributes patch which broke ./configure on systems with alternative shells. * Fix issue in user32-WndProc patch which caused crashes for some 16-bit apps. + * Fix issue in ws2_32-WriteWatches patch which can cause exceptions on the signal stack. * Added patch with stubs for WinSqm[Start|End]Session. * Added patch to fix handling of subdirectory in FtpFindFirstFile. * Added patch to return proper charcount for GetLocaleInfo with LOCALE_IFIRSTDAYOFWEEK. diff --git a/patches/Makefile b/patches/Makefile index 81ae639c..337713db 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -1284,17 +1284,17 @@ ntdll-User_Shared_Data.ok: # | dlls/ntdll/signal_x86_64.c, dlls/ntdll/thread.c, dlls/ntdll/virtual.c # | .INTERMEDIATE: ntdll-WRITECOPY.ok -ntdll-WRITECOPY.ok: +ntdll-WRITECOPY.ok: ws2_32-WriteWatches.ok $(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-Setup-a-temporary-signal-handler-during-proces.patch) - $(call APPLY_FILE,ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.patch) + $(call APPLY_FILE,ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.-try.patch) $(call APPLY_FILE,ntdll-WRITECOPY/0005-ntdll-Only-enable-true-WRITECOPY-protection-when-a-s.patch) @( \ echo '+ { "Sebastian Lackner", "ntdll: Trigger write watches before passing userdata pointer to wait_reply.", 1 },'; \ echo '+ { "Sebastian Lackner", "advapi: Trigger write watches before passing userdata pointer to read syscall.", 1 },'; \ echo '+ { "Michael Müller", "ntdll: Setup a temporary signal handler during process startup to handle page faults.", 1 },'; \ - echo '+ { "Michael Müller", "ntdll: Properly handle PAGE_WRITECOPY protection.", 4 },'; \ + echo '+ { "Michael Müller", "ntdll: Properly handle PAGE_WRITECOPY protection.", 5 },'; \ echo '+ { "Michael Müller", "ntdll: Only enable true WRITECOPY protection when a special environment variable is set.", 1 },'; \ ) > ntdll-WRITECOPY.ok @@ -2701,13 +2701,18 @@ ws2_32-TransmitFile.ok: # Patchset ws2_32-WriteWatches # | # | Modified files: -# | * dlls/ws2_32/socket.c +# | * dlls/ntdll/ntdll.spec, dlls/ntdll/ntdll_misc.h, dlls/ntdll/signal_i386.c, dlls/ntdll/virtual.c, dlls/ws2_32/socket.c, +# | include/winternl.h # | .INTERMEDIATE: ws2_32-WriteWatches.ok ws2_32-WriteWatches.ok: - $(call APPLY_FILE,ws2_32-WriteWatches/0001-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch) + $(call APPLY_FILE,ws2_32-WriteWatches/0001-ntdll-Handle-write-watches-in-virtual_uninterrupted_.patch) + $(call APPLY_FILE,ws2_32-WriteWatches/0002-ntdll-Expose-wine_uninterrupted_-read-write-_memory-.patch) + $(call APPLY_FILE,ws2_32-WriteWatches/0003-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch) @( \ - echo '+ { "Sebastian Lackner", "ws2_32: Avoid race-conditions of async WSARecv() operations with write watches.", 1 },'; \ + echo '+ { "Sebastian Lackner", "ntdll: Handle write watches in virtual_uninterrupted_write_memory.", 1 },'; \ + echo '+ { "Sebastian Lackner", "ntdll: Expose wine_uninterrupted_[read|write]_memory as exports.", 1 },'; \ + echo '+ { "Sebastian Lackner", "ws2_32: Avoid race-conditions of async WSARecv() operations with write watches.", 2 },'; \ ) > ws2_32-WriteWatches.ok # Patchset ws2_32-getaddrinfo diff --git a/patches/ntdll-WRITECOPY/0001-ntdll-Trigger-write-watches-before-passing-userdata-.patch b/patches/ntdll-WRITECOPY/0001-ntdll-Trigger-write-watches-before-passing-userdata-.patch index 5ba178ce..e94e95ff 100644 --- a/patches/ntdll-WRITECOPY/0001-ntdll-Trigger-write-watches-before-passing-userdata-.patch +++ b/patches/ntdll-WRITECOPY/0001-ntdll-Trigger-write-watches-before-passing-userdata-.patch @@ -1,4 +1,4 @@ -From 482071f086b4e93d8bd9e1c57652478bfcd98ecf Mon Sep 17 00:00:00 2001 +From e4f9424f025aebdbcd96a6f0eb2c39f479b4eda7 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 4 Oct 2014 02:35:44 +0200 Subject: ntdll: Trigger write watches before passing userdata pointer to @@ -28,5 +28,5 @@ index aabda4f..4d5d4ba 100644 ret = send_request( req ); if (!ret) ret = wait_reply( req ); -- -2.1.1 +2.2.1 diff --git a/patches/ntdll-WRITECOPY/0002-advapi-Trigger-write-watches-before-passing-userdata.patch b/patches/ntdll-WRITECOPY/0002-advapi-Trigger-write-watches-before-passing-userdata.patch index 43803f6f..6aa463d1 100644 --- a/patches/ntdll-WRITECOPY/0002-advapi-Trigger-write-watches-before-passing-userdata.patch +++ b/patches/ntdll-WRITECOPY/0002-advapi-Trigger-write-watches-before-passing-userdata.patch @@ -1,4 +1,4 @@ -From 1eeeb531c7e0188ecf7f39166dfe299fef2c7116 Mon Sep 17 00:00:00 2001 +From adcf73538130589e5c4831ec5a8fdd37a6408824 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 4 Oct 2014 02:38:27 +0200 Subject: advapi: Trigger write watches before passing userdata pointer to read @@ -23,5 +23,5 @@ index b2be5e3..50502b8 100644 close(dev_random); return TRUE; -- -2.1.1 +2.2.1 diff --git a/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch b/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch index d420590a..52336681 100644 --- a/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch +++ b/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch @@ -1,4 +1,4 @@ -From cbb34fc193e2b2236ef7fec301e6d34be39d92aa Mon Sep 17 00:00:00 2001 +From 91cdcf5f955d3cbd7a22531054448dc01c171e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 4 Oct 2014 02:53:22 +0200 Subject: ntdll: Setup a temporary signal handler during process startup to @@ -15,7 +15,7 @@ Subject: ntdll: Setup a temporary signal handler during process startup to 7 files changed, 73 insertions(+) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index 4370084..53e6b55 100644 +index e56e78b..a33f7a0 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; @@ -61,10 +61,10 @@ index 8c8f7af..483bc85 100644 /********************************************************************** * __wine_enter_vm86 (NTDLL.@) diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c -index 12aa5a4..d24e3bf 100644 +index de55c31..49222f4 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 ) +@@ -2035,6 +2035,30 @@ static void usr2_handler( int signal, siginfo_t *siginfo, void *sigcontext ) /********************************************************************** @@ -95,7 +95,7 @@ index 12aa5a4..d24e3bf 100644 * segv_handler * * Handler for SIGSEGV and related errors. -@@ -2371,6 +2395,29 @@ void signal_init_process(void) +@@ -2457,6 +2481,29 @@ void signal_init_process(void) exit(1); } @@ -172,5 +172,5 @@ index c8461b0..a2937c2 100644 /* reserve space for shared user data */ -- -2.1.1 +2.2.1 diff --git a/patches/ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.patch b/patches/ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.-try.patch similarity index 73% rename from patches/ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.patch rename to patches/ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.-try.patch index 30287146..ad2ca2d1 100644 --- a/patches/ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.patch +++ b/patches/ntdll-WRITECOPY/0004-ntdll-Properly-handle-PAGE_WRITECOPY-protection.-try.patch @@ -1,18 +1,18 @@ -From 0596c2b03fa72a5159fa5a9df3e909e925d6144f Mon Sep 17 00:00:00 2001 +From 9e5ef34f4cbfb381528750caabd4ba6a3da439f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 4 Oct 2014 02:56:08 +0200 -Subject: ntdll: Properly handle PAGE_WRITECOPY protection. (try 4) +Subject: ntdll: Properly handle PAGE_WRITECOPY protection. (try 5) --- dlls/kernel32/tests/virtual.c | 12 ++---------- - dlls/ntdll/virtual.c | 16 +++++++++++++--- - 2 files changed, 15 insertions(+), 13 deletions(-) + dlls/ntdll/virtual.c | 26 +++++++++++++++++++------- + 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c -index 73b753e..5797805 100644 +index 75e91d5..3520546 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c -@@ -2786,11 +2786,7 @@ todo_wine +@@ -2929,11 +2929,7 @@ todo_wine SetLastError(0xdeadbeef); ret = VirtualQuery(base, &info, sizeof(info)); ok(ret, "VirtualQuery failed %d\n", GetLastError()); @@ -25,7 +25,7 @@ index 73b753e..5797805 100644 } } else -@@ -2804,11 +2800,7 @@ todo_wine +@@ -2947,11 +2943,7 @@ todo_wine SetLastError(0xdeadbeef); ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot); ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError()); @@ -39,7 +39,7 @@ index 73b753e..5797805 100644 UnmapViewOfFile(base); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 4c4c05d..d26fe26 100644 +index 17792e1..36d8836 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -179,8 +179,13 @@ static int VIRTUAL_GetUnixProt( BYTE vprot ) @@ -78,6 +78,27 @@ index 4c4c05d..d26fe26 100644 /* ignore fault if page is writable now */ if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS; } +@@ -1748,14 +1758,16 @@ SIZE_T CDECL wine_uninterrupted_write_memory( void *addr, const void *buffer, SI + * handle guard pages here. */ + if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE)) + { +- if (!(view->protect & VPROT_WRITEWATCH)) +- break; +- +- if (*p & VPROT_WRITEWATCH) ++ if ((view->protect & VPROT_WRITEWATCH) && (*p & VPROT_WRITEWATCH)) + { + *p &= ~VPROT_WRITEWATCH; + VIRTUAL_SetProt( view, page, page_size, *p ); + } ++ if (*p & VPROT_WRITECOPY) ++ { ++ *p = (*p & ~VPROT_WRITECOPY) | VPROT_WRITE; ++ VIRTUAL_SetProt( view, page, page_size, *p ); ++ } + /* ignore fault if page is writable now */ + if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE)) + break; -- -2.1.2 +2.2.1 diff --git a/patches/ntdll-WRITECOPY/0005-ntdll-Only-enable-true-WRITECOPY-protection-when-a-s.patch b/patches/ntdll-WRITECOPY/0005-ntdll-Only-enable-true-WRITECOPY-protection-when-a-s.patch index 69ffc720..e3953797 100644 --- a/patches/ntdll-WRITECOPY/0005-ntdll-Only-enable-true-WRITECOPY-protection-when-a-s.patch +++ b/patches/ntdll-WRITECOPY/0005-ntdll-Only-enable-true-WRITECOPY-protection-when-a-s.patch @@ -1,4 +1,4 @@ -From 566ff0e978e59354160a1d2cdde79cb9e5ead244 Mon Sep 17 00:00:00 2001 +From 3d29cd7c6feabae6c5ae5941f49c663b1fb78ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Sat, 4 Oct 2014 03:22:09 +0200 Subject: ntdll: Only enable true WRITECOPY protection when a special @@ -9,7 +9,7 @@ Subject: ntdll: Only enable true WRITECOPY protection when a special 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index d26fe26..02e32fb 100644 +index 36d8836..0c7ae29 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -166,6 +166,21 @@ static const char *VIRTUAL_GetProtStr( BYTE prot ) @@ -50,5 +50,5 @@ index d26fe26..02e32fb 100644 /* FIXME: Architecture needs implementation of signal_init_early. */ if (vprot & VPROT_WRITECOPY) prot |= PROT_WRITE | PROT_READ; -- -2.1.2 +2.2.1 diff --git a/patches/ntdll-WRITECOPY/definition b/patches/ntdll-WRITECOPY/definition index 28372a78..c477fc5b 100644 --- a/patches/ntdll-WRITECOPY/definition +++ b/patches/ntdll-WRITECOPY/definition @@ -1 +1,2 @@ Fixes: [29384] Voobly expects correct handling of WRITECOPY memory protection +Depends: ws2_32-WriteWatches diff --git a/patches/ws2_32-WriteWatches/0001-ntdll-Handle-write-watches-in-virtual_uninterrupted_.patch b/patches/ws2_32-WriteWatches/0001-ntdll-Handle-write-watches-in-virtual_uninterrupted_.patch new file mode 100644 index 00000000..f5850adf --- /dev/null +++ b/patches/ws2_32-WriteWatches/0001-ntdll-Handle-write-watches-in-virtual_uninterrupted_.patch @@ -0,0 +1,54 @@ +From 67e51503f973289b85c526eb05d76d78f7bd337e Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 3 Jan 2015 19:11:40 +0100 +Subject: ntdll: Handle write watches in virtual_uninterrupted_write_memory. + +--- + dlls/ntdll/virtual.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c +index 4c4c05d..8823164 100644 +--- a/dlls/ntdll/virtual.c ++++ b/dlls/ntdll/virtual.c +@@ -1730,12 +1730,32 @@ SIZE_T virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_ + { + if (!(view->protect & VPROT_SYSTEM)) + { +- void *page = ROUND_ADDR( addr, page_mask ); +- BYTE *p = view->prot + (((const char *)page - (const char *)view->base) >> page_shift); +- +- while (bytes_written < size && (VIRTUAL_GetUnixProt( *p++ ) & PROT_WRITE)) ++ while (bytes_written < size) + { +- SIZE_T block_size = min( size, page_size - ((UINT_PTR)addr & page_mask) ); ++ void *page = ROUND_ADDR( addr, page_mask ); ++ BYTE *p = view->prot + (((const char *)page - (const char *)view->base) >> page_shift); ++ SIZE_T block_size; ++ ++ /* If the page is not writeable then check for write watches ++ * before giving up. This can be done without raising a real ++ * exception. Similar to virtual_handle_fault, but we can't ++ * handle guard pages here. */ ++ if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE)) ++ { ++ if (!(view->protect & VPROT_WRITEWATCH)) ++ break; ++ ++ if (*p & VPROT_WRITEWATCH) ++ { ++ *p &= ~VPROT_WRITEWATCH; ++ VIRTUAL_SetProt( view, page, page_size, *p ); ++ } ++ /* ignore fault if page is writable now */ ++ if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE)) ++ break; ++ } ++ ++ block_size = min( size, page_size - ((UINT_PTR)addr & page_mask) ); + memcpy( addr, buffer, block_size ); + + addr = (void *)((char *)addr + block_size); +-- +2.2.1 + diff --git a/patches/ws2_32-WriteWatches/0002-ntdll-Expose-wine_uninterrupted_-read-write-_memory-.patch b/patches/ws2_32-WriteWatches/0002-ntdll-Expose-wine_uninterrupted_-read-write-_memory-.patch new file mode 100644 index 00000000..ee6b8a99 --- /dev/null +++ b/patches/ws2_32-WriteWatches/0002-ntdll-Expose-wine_uninterrupted_-read-write-_memory-.patch @@ -0,0 +1,169 @@ +From 32e36972905ea820ac557c37b6d3a02dd32fd795 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 3 Jan 2015 20:07:08 +0100 +Subject: ntdll: Expose wine_uninterrupted_[read|write]_memory as exports. + +--- + dlls/ntdll/ntdll.spec | 4 ++++ + dlls/ntdll/ntdll_misc.h | 2 -- + dlls/ntdll/signal_i386.c | 10 +++++----- + dlls/ntdll/virtual.c | 34 ++++++++++++++++++++++------------ + include/winternl.h | 3 +++ + 5 files changed, 34 insertions(+), 19 deletions(-) + +diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec +index 51de6e7..1e91089 100644 +--- a/dlls/ntdll/ntdll.spec ++++ b/dlls/ntdll/ntdll.spec +@@ -1430,6 +1430,10 @@ + # signal handling + @ cdecl __wine_set_signal_handler(long ptr) + ++# Virtual memory management ++@ cdecl wine_uninterrupted_read_memory(ptr ptr long) ++@ cdecl wine_uninterrupted_write_memory(ptr ptr long) ++ + # Filesystem + @ cdecl wine_nt_to_unix_file_name(ptr ptr long long) + @ cdecl wine_unix_to_nt_file_name(ptr ptr) +diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h +index b7ea6dc..e56e78b 100644 +--- a/dlls/ntdll/ntdll_misc.h ++++ b/dlls/ntdll/ntdll_misc.h +@@ -171,8 +171,6 @@ extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLS + extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err ) DECLSPEC_HIDDEN; + extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) DECLSPEC_HIDDEN; + extern BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) DECLSPEC_HIDDEN; +-extern SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) DECLSPEC_HIDDEN; +-extern SIZE_T virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) DECLSPEC_HIDDEN; + extern void VIRTUAL_SetForceExec( BOOL enable ) DECLSPEC_HIDDEN; + extern void virtual_release_address_space(void) DECLSPEC_HIDDEN; + extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; +diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c +index 1a69bc0..de55c31 100644 +--- a/dlls/ntdll/signal_i386.c ++++ b/dlls/ntdll/signal_i386.c +@@ -1669,13 +1669,13 @@ static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context ) + union atl_thunk thunk_copy; + SIZE_T thunk_len; + +- thunk_len = virtual_uninterrupted_read_memory( thunk, &thunk_copy, sizeof(*thunk) ); ++ thunk_len = wine_uninterrupted_read_memory( thunk, &thunk_copy, sizeof(*thunk) ); + if (!thunk_len) return FALSE; + + if (thunk_len >= sizeof(thunk_copy.t1) && thunk_copy.t1.movl == 0x042444c7 && + thunk_copy.t1.jmp == 0xe9) + { +- if (virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1, ++ if (wine_uninterrupted_write_memory( (DWORD *)context->Esp + 1, + &thunk_copy.t1.this, sizeof(DWORD) ) == sizeof(DWORD)) + { + context->Eip = (DWORD_PTR)(&thunk->t1.func + 1) + thunk_copy.t1.func; +@@ -1719,11 +1719,11 @@ static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context ) + thunk_copy.t5.inst2 == 0x0460) + { + DWORD func, stack[2]; +- if (virtual_uninterrupted_read_memory( (DWORD *)context->Esp, ++ if (wine_uninterrupted_read_memory( (DWORD *)context->Esp, + stack, sizeof(stack) ) == sizeof(stack) && +- virtual_uninterrupted_read_memory( (DWORD *)stack[1] + 1, ++ wine_uninterrupted_read_memory( (DWORD *)stack[1] + 1, + &func, sizeof(DWORD) ) == sizeof(DWORD) && +- virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1, ++ wine_uninterrupted_write_memory( (DWORD *)context->Esp + 1, + &stack[0], sizeof(stack[0]) ) == sizeof(stack[0])) + { + context->Ecx = stack[0]; +diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c +index 8823164..17792e1 100644 +--- a/dlls/ntdll/virtual.c ++++ b/dlls/ntdll/virtual.c +@@ -1672,13 +1672,14 @@ BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) + + + /*********************************************************************** +- * virtual_uninterrupted_read_memory ++ * wine_uninterrupted_read_memory (NTDLL.@) + * + * Similar to NtReadVirtualMemory, but without wineserver calls. Moreover + * permissions are checked before accessing each page, to ensure that no +- * exceptions can happen. ++ * exceptions can happen. When a NULL pointer is passed as buffer the ++ * permissions are only checked and no actual memcpy is performed. + */ +-SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) ++SIZE_T CDECL wine_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) + { + struct file_view *view; + sigset_t sigset; +@@ -1697,10 +1698,14 @@ SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T + while (bytes_read < size && (VIRTUAL_GetUnixProt( *p++ ) & PROT_READ)) + { + SIZE_T block_size = min( size, page_size - ((UINT_PTR)addr & page_mask) ); +- memcpy( buffer, addr, block_size ); + +- addr = (const void *)((const char *)addr + block_size); +- buffer = (void *)((char *)buffer + block_size); ++ if (buffer) ++ { ++ memcpy( buffer, addr, block_size ); ++ buffer = (void *)((char *)buffer + block_size); ++ } ++ ++ addr = (const void *)((const char *)addr + block_size); + bytes_read += block_size; + } + } +@@ -1711,13 +1716,14 @@ SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T + + + /*********************************************************************** +- * virtual_uninterrupted_write_memory ++ * wine_uninterrupted_write_memory (NTDLL.@) + * + * Similar to NtWriteVirtualMemory, but without wineserver calls. Moreover + * permissions are checked before accessing each page, to ensure that no +- * exceptions can happen. ++ * exceptions can happen. When a NULL pointer is passed as buffer the ++ * permissions are only checked and no actual memcpy is performed. + */ +-SIZE_T virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) ++SIZE_T CDECL wine_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) + { + struct file_view *view; + sigset_t sigset; +@@ -1756,10 +1762,14 @@ SIZE_T virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_ + } + + block_size = min( size, page_size - ((UINT_PTR)addr & page_mask) ); +- memcpy( addr, buffer, block_size ); + +- addr = (void *)((char *)addr + block_size); +- buffer = (const void *)((const char *)buffer + block_size); ++ if (buffer) ++ { ++ memcpy( addr, buffer, block_size ); ++ buffer = (const void *)((const char *)buffer + block_size); ++ } ++ ++ addr = (void *)((char *)addr + block_size); + bytes_written += block_size; + } + } +diff --git a/include/winternl.h b/include/winternl.h +index 1a694da..02dda9a 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -2605,6 +2605,9 @@ NTSYSAPI NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, + UINT disposition, BOOLEAN check_case ); + NTSYSAPI NTSTATUS CDECL wine_unix_to_nt_file_name( const ANSI_STRING *name, UNICODE_STRING *nt ); + ++NTSYSAPI SIZE_T CDECL wine_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ); ++NTSYSAPI SIZE_T CDECL wine_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ); ++ + + /*********************************************************************** + * Inline functions +-- +2.2.1 + diff --git a/patches/ws2_32-WriteWatches/0001-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch b/patches/ws2_32-WriteWatches/0003-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch similarity index 84% rename from patches/ws2_32-WriteWatches/0001-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch rename to patches/ws2_32-WriteWatches/0003-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch index 7b87b3ae..bc80c215 100644 --- a/patches/ws2_32-WriteWatches/0001-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch +++ b/patches/ws2_32-WriteWatches/0003-ws2_32-Avoid-race-conditions-of-async-WSARecv-operat.patch @@ -1,8 +1,8 @@ -From dc07ceb5dff69b2a306278d5d3254c18c98205df Mon Sep 17 00:00:00 2001 +From ae757e6bb862919e3b5a59bdb590555c462258ee Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Fri, 21 Nov 2014 12:22:46 +0100 Subject: ws2_32: Avoid race-conditions of async WSARecv() operations with - write watches. + write watches. (try 2) Under specific circumstances Silverlight resets the write watch while the async WSARecv() operation is still pending: @@ -37,14 +37,14 @@ Based on the code it looks like we could savely remove the write-watch check at the beginning of WS2_recv_base, which might make the application think that data is immediately available. --- - dlls/ws2_32/socket.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) + dlls/ws2_32/socket.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c -index b3db306..ef86b28 100644 +index a9ab0a5..9d94893 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c -@@ -1930,7 +1930,16 @@ static int WS2_recv( int fd, struct ws2_async *wsa ) +@@ -1930,7 +1930,17 @@ static int WS2_recv( int fd, struct ws2_async *wsa ) while ((n = recvmsg(fd, &hdr, wsa->flags)) == -1) { @@ -54,7 +54,8 @@ index b3db306..ef86b28 100644 + unsigned int i; + for (i = wsa->first_iovec; i < wsa->n_iovecs; i++) + { -+ if (IsBadWritePtr( wsa->iovec[i].iov_base, wsa->iovec[i].iov_len )) ++ struct iovec *iov = &wsa->iovec[i]; ++ if (wine_uninterrupted_write_memory( iov->iov_base, NULL, iov->iov_len ) < iov->iov_len) + return -1; + } + } @@ -63,5 +64,5 @@ index b3db306..ef86b28 100644 } -- -2.1.3 +2.2.1