mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Partially removed patches for ATL thunk fixes (accepted upstream).
This commit is contained in:
parent
7336108ab8
commit
b757d6fe5c
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -8,6 +8,7 @@ wine-compholio (1.7.29) UNRELEASED; urgency=low
|
||||
* Removed patch to set ldr.EntryPoint for main executable (accepted upstream).
|
||||
* Removed patch to implement stubs for [Get|Set]SystemFileCacheSize (accepted upstream).
|
||||
* Partially removed patches for WRITECOPY memory protection (accepted upstream).
|
||||
* Partially removed patches for ATL thunk patches (accepted upstream).
|
||||
-- Sebastian Lackner <sebastian@fds-team.de> Mon, 06 Oct 2014 01:02:37 +0200
|
||||
|
||||
wine-compholio (1.7.28) unstable; urgency=low
|
||||
|
@ -550,17 +550,12 @@ msvcp90-basic_string_wchar_dtor.ok:
|
||||
# | * [#34479] Fix issue with ATL thunks in combination with guard pages
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/tests/virtual.c, dlls/ntdll/signal_i386.c, dlls/ntdll/virtual.c, include/winternl.h
|
||||
# | * dlls/kernel32/tests/virtual.c, dlls/ntdll/signal_i386.c
|
||||
# |
|
||||
.INTERMEDIATE: ntdll-ATL_Thunk.ok
|
||||
ntdll-ATL_Thunk.ok:
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0001-kernel32-tests-Add-tests-for-DEP-combined-with-guard.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0002-ntdll-Avoid-recursive-exception-handler-calls-when-h.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0003-ntdll-Ensure-force_exec_prot-is-also-used-for-views-.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0004-ntdll-reset_write_watches-shouldn-t-remove-enforced-.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0005-ntdll-Only-check-for-ATL-thunk-if-allowed-by-execute.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0006-kernel32-tests-Add-test-to-show-incorrect-behaviour-.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0007-ntdll-Try-to-not-raise-exceptions-when-checking-for-.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0001-kernel32-tests-Add-test-to-show-incorrect-behaviour-.patch)
|
||||
$(call APPLY_FILE,ntdll-ATL_Thunk/0002-ntdll-Try-to-not-raise-exceptions-when-checking-for-.patch)
|
||||
@( \
|
||||
echo '+ { "ntdll-ATL_Thunk", "Sebastian Lackner", "Fix several issues with execute permissions in guard page / write watch handling. [rev 2]" },'; \
|
||||
) > ntdll-ATL_Thunk.ok
|
||||
|
@ -1,499 +0,0 @@
|
||||
From 74b84ed98a660e029a60ef7c6e20efa6a71c2361 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 8 Oct 2014 20:54:50 +0200
|
||||
Subject: kernel32/tests: Add tests for DEP combined with guard pages and write
|
||||
watches.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 449 ++++++++++++++++++++++++++++++++++++++++++
|
||||
include/winternl.h | 1 +
|
||||
2 files changed, 450 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 0fa2b99..501934d 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "winnt.h"
|
||||
#include "winternl.h"
|
||||
#include "winerror.h"
|
||||
+#include "winuser.h"
|
||||
#include "excpt.h"
|
||||
#include "wine/test.h"
|
||||
|
||||
@@ -1797,6 +1798,449 @@ static void test_guard_page(void)
|
||||
VirtualFree( base, 0, MEM_FREE );
|
||||
}
|
||||
|
||||
+DWORD num_execute_fault_calls;
|
||||
+
|
||||
+static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
+ CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
+{
|
||||
+ ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
|
||||
+
|
||||
+ trace( "exception: %08x flags:%x addr:%p info[0]:%ld info[1]:%p\n",
|
||||
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
|
||||
+ rec->ExceptionInformation[0], (void *)rec->ExceptionInformation[1] );
|
||||
+
|
||||
+ ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
|
||||
+ ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION || rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION,
|
||||
+ "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION or STATUS_GUARD_PAGE_VIOLATION\n", rec->ExceptionCode );
|
||||
+
|
||||
+ NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags), NULL );
|
||||
+
|
||||
+ if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
|
||||
+ {
|
||||
+
|
||||
+ todo_wine
|
||||
+ ok( rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ||
|
||||
+ broken(!(flags & MEM_EXECUTE_OPTION_DISABLE) && rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT), /* Windows 2000 */
|
||||
+ "ExceptionInformation[0] is %d instead of %d\n", (DWORD)rec->ExceptionInformation[0], EXCEPTION_EXECUTE_FAULT );
|
||||
+
|
||||
+ num_guard_page_calls++;
|
||||
+ }
|
||||
+ else if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION)
|
||||
+ {
|
||||
+ DWORD err, old_prot;
|
||||
+ BOOL success;
|
||||
+
|
||||
+ err = (flags & MEM_EXECUTE_OPTION_DISABLE) ? EXCEPTION_EXECUTE_FAULT : EXCEPTION_READ_FAULT;
|
||||
+ ok( rec->ExceptionInformation[0] == err, "ExceptionInformation[0] is %d instead of %d\n",
|
||||
+ (DWORD)rec->ExceptionInformation[0], err );
|
||||
+
|
||||
+ success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+ ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+
|
||||
+ num_execute_fault_calls++;
|
||||
+ }
|
||||
+
|
||||
+ return ExceptionContinueExecution;
|
||||
+}
|
||||
+
|
||||
+static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
+{
|
||||
+ EXCEPTION_REGISTRATION_RECORD frame;
|
||||
+ DWORD ret;
|
||||
+
|
||||
+ frame.Handler = execute_fault_seh_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = SendMessageA( hWnd, WM_USER, 0, 0 );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
+{
|
||||
+ if (uMsg == WM_USER)
|
||||
+ return 42;
|
||||
+
|
||||
+ return DefWindowProcA( hWnd, uMsg, wParam, lParam );
|
||||
+}
|
||||
+
|
||||
+static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
+{
|
||||
+ DWORD arg = (DWORD)hWnd;
|
||||
+ ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg );
|
||||
+ return 43;
|
||||
+}
|
||||
+
|
||||
+static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
+{
|
||||
+ static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
|
||||
+ static const char code_atl[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00};
|
||||
+ static const char cls_name[] = "atl_thunk_class";
|
||||
+ DWORD ret, size, old_prot;
|
||||
+ ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
|
||||
+ void *results[64];
|
||||
+ ULONG_PTR count;
|
||||
+ ULONG pagesize;
|
||||
+ WNDCLASSEXA wc;
|
||||
+ BOOL success;
|
||||
+ char *base;
|
||||
+ HWND hWnd;
|
||||
+
|
||||
+ if (!pNtCurrentTeb)
|
||||
+ {
|
||||
+ win_skip( "NtCurrentTeb not supported\n" );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
|
||||
+
|
||||
+ NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
|
||||
+ if (old_flags != dep_flags)
|
||||
+ {
|
||||
+ ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &dep_flags, sizeof(dep_flags) );
|
||||
+ if (ret == STATUS_INVALID_INFO_CLASS) /* Windows 2000 */
|
||||
+ {
|
||||
+ win_skip( "Skipping DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
|
||||
+ return;
|
||||
+ }
|
||||
+ ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
|
||||
+ }
|
||||
+
|
||||
+ size = 0x1000;
|
||||
+ base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
|
||||
+ ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
+
|
||||
+ memcpy( base, code_jmp, sizeof(code_jmp) );
|
||||
+ *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
|
||||
+
|
||||
+ /* On Windows, the ATL Thunk emulation is only enabled while running WndProc functions,
|
||||
+ * whereas in Wine such a limitation doesn't exist yet. We want to test in a scenario
|
||||
+ * where it is active, so that application which depend on that still work properly.
|
||||
+ * We have no exception handler enabled yet, so give proper EXECUTE permissions to
|
||||
+ * prevent crashes while creating the window. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ memset( &wc, 0, sizeof(wc) );
|
||||
+ wc.cbSize = sizeof(wc);
|
||||
+ wc.style = CS_VREDRAW | CS_HREDRAW;
|
||||
+ wc.hInstance = GetModuleHandleA( 0 );
|
||||
+ wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
|
||||
+ wc.hbrBackground = NULL;
|
||||
+ wc.lpszClassName = cls_name;
|
||||
+ wc.lpfnWndProc = (WNDPROC)base;
|
||||
+ success = RegisterClassExA(&wc) != 0;
|
||||
+ ok( success, "RegisterClassExA failed %u\n", GetLastError() );
|
||||
+
|
||||
+ hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
|
||||
+ ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = SendMessageA(hWnd, WM_USER, 0, 0);
|
||||
+ ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
|
||||
+
|
||||
+ /* At first try with an instruction which is not recognized as proper ATL thunk
|
||||
+ * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
|
||||
+ * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ /* Now a bit more complicated, the page containing the code is protected with
|
||||
+ * PAGE_GUARD memory protection. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ /* Now test with a proper ATL thunk instruction. */
|
||||
+
|
||||
+ memcpy( base, code_atl, sizeof(code_atl) );
|
||||
+ *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = SendMessageA(hWnd, WM_USER, 0, 0);
|
||||
+ ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
|
||||
+
|
||||
+ /* Try executing with PAGE_READWRITE protection. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ /* Now a bit more complicated, the page containing the code is protected with
|
||||
+ * PAGE_GUARD memory protection. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ /* the same, but with PAGE_GUARD set */
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ /* Restore the JMP instruction, set to executable, and then destroy the Window */
|
||||
+
|
||||
+ memcpy( base, code_jmp, sizeof(code_jmp) );
|
||||
+ *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ DestroyWindow( hWnd );
|
||||
+
|
||||
+ success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
|
||||
+ ok( success, "UnregisterClass failed %u\n", GetLastError() );
|
||||
+
|
||||
+ VirtualFree( base, 0, MEM_FREE );
|
||||
+
|
||||
+ /* Repeat the tests from above with MEM_WRITE_WATCH protected memory. */
|
||||
+
|
||||
+ base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
|
||||
+ if (!base && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
|
||||
+ {
|
||||
+ win_skip( "MEM_WRITE_WATCH not supported\n" );
|
||||
+ goto out;
|
||||
+ }
|
||||
+ ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 0, "wrong count %lu\n", count );
|
||||
+
|
||||
+ memcpy( base, code_jmp, sizeof(code_jmp) );
|
||||
+ *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 1, "wrong count %lu\n", count );
|
||||
+ ok( results[0] == base, "wrong result %p\n", results[0] );
|
||||
+
|
||||
+ /* Create a new window class and associcated Window (see above) */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ memset( &wc, 0, sizeof(wc) );
|
||||
+ wc.cbSize = sizeof(wc);
|
||||
+ wc.style = CS_VREDRAW | CS_HREDRAW;
|
||||
+ wc.hInstance = GetModuleHandleA( 0 );
|
||||
+ wc.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW );
|
||||
+ wc.hbrBackground = NULL;
|
||||
+ wc.lpszClassName = cls_name;
|
||||
+ wc.lpfnWndProc = (WNDPROC)base;
|
||||
+ success = RegisterClassExA(&wc) != 0;
|
||||
+ ok( success, "RegisterClassExA failed %u\n", GetLastError() );
|
||||
+
|
||||
+ hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
|
||||
+ ok( hWnd != 0, "CreateWindowExA failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = SendMessageA(hWnd, WM_USER, 0, 0);
|
||||
+ ok( ret == 42, "SendMessage returned unexpected result %d\n", ret );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 0, "wrong count %lu\n", count );
|
||||
+
|
||||
+ /* At first try with an instruction which is not recognized as proper ATL thunk
|
||||
+ * by the Windows ATL Thunk Emulator. Removing execute permissions will lead to
|
||||
+ * STATUS_ACCESS_VIOLATION exceptions when DEP is enabled. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 0, "wrong count %lu\n", count );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ /* Now a bit more complicated, the page containing the code is protected with
|
||||
+ * PAGE_GUARD memory protection. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
|
||||
+
|
||||
+ /* Now test with a proper ATL thunk instruction. */
|
||||
+
|
||||
+ memcpy( base, code_atl, sizeof(code_atl) );
|
||||
+ *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 1, "wrong count %lu\n", count );
|
||||
+ ok( results[0] == base, "wrong result %p\n", results[0] );
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = SendMessageA(hWnd, WM_USER, 0, 0);
|
||||
+ ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
|
||||
+
|
||||
+ /* Try executing with PAGE_READWRITE protection. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 0, "wrong count %lu\n", count );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ /* Now a bit more complicated, the page containing the code is protected with
|
||||
+ * PAGE_GUARD memory protection. */
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ /* the same, but with PAGE_GUARD set */
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
|
||||
+
|
||||
+ /* Restore the JMP instruction, set to executable, and then destroy the Window */
|
||||
+
|
||||
+ memcpy( base, code_jmp, sizeof(code_jmp) );
|
||||
+ *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
+ ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
+ ok( count == 1, "wrong count %lu\n", count );
|
||||
+ ok( results[0] == base, "wrong result %p\n", results[0] );
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ DestroyWindow( hWnd );
|
||||
+
|
||||
+ success = UnregisterClassA( cls_name, GetModuleHandleA(0) );
|
||||
+ ok( success, "UnregisterClass failed %u\n", GetLastError() );
|
||||
+
|
||||
+ VirtualFree( base, 0, MEM_FREE );
|
||||
+
|
||||
+out:
|
||||
+ if (old_flags != dep_flags)
|
||||
+ {
|
||||
+ ret = NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags) );
|
||||
+ ok( !ret, "NtSetInformationProcess failed with status %08x\n", ret );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#endif /* __i386__ */
|
||||
|
||||
static void test_VirtualProtect(void)
|
||||
@@ -2859,5 +3303,10 @@ START_TEST(virtual)
|
||||
test_write_watch();
|
||||
#ifdef __i386__
|
||||
test_guard_page();
|
||||
+ /* The following tests should be executed as a last step, and in exactly this
|
||||
+ * order, since ATL thunk emulation cannot be enabled anymore on Windows. */
|
||||
+ test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE );
|
||||
+ test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE );
|
||||
+ test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION );
|
||||
#endif
|
||||
}
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index 95951e2..5a27f94 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -728,6 +728,7 @@ typedef enum _PROCESSINFOCLASS {
|
||||
|
||||
#define MEM_EXECUTE_OPTION_DISABLE 0x01
|
||||
#define MEM_EXECUTE_OPTION_ENABLE 0x02
|
||||
+#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 0x04
|
||||
#define MEM_EXECUTE_OPTION_PERMANENT 0x08
|
||||
|
||||
typedef enum _SECTION_INHERIT {
|
||||
--
|
||||
2.1.2
|
||||
|
@ -1,68 +0,0 @@
|
||||
From f04b80a0472feb427cecabf6e05fb23515272a63 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 8 Oct 2014 21:11:55 +0200
|
||||
Subject: ntdll: Avoid recursive exception handler calls when handling guard
|
||||
pages.
|
||||
|
||||
The ATL check leads to problems when a page is protected with guard page protection.
|
||||
raise_segv_exception is called with EXCEPTION_EXECUTE_FAULT. The ATL check tries to
|
||||
read the memory, and triggers another exception handler. This time the virtual_handle_fault
|
||||
check is executed, and removes the guard page protection. Afterwards, when the ATL
|
||||
check returns, the exception is _not_ catched by virtual_handle_fault, but instead
|
||||
passed to the application.
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 2 --
|
||||
dlls/ntdll/signal_i386.c | 10 ++++++----
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 501934d..4d8277d 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1818,7 +1818,6 @@ static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTR
|
||||
if (rec->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
|
||||
{
|
||||
|
||||
- todo_wine
|
||||
ok( rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT ||
|
||||
broken(!(flags & MEM_EXECUTE_OPTION_DISABLE) && rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT), /* Windows 2000 */
|
||||
"ExceptionInformation[0] is %d instead of %d\n", (DWORD)rec->ExceptionInformation[0], EXCEPTION_EXECUTE_FAULT );
|
||||
@@ -1971,7 +1970,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
|
||||
index 12aa5a4..b9b45a8 100644
|
||||
--- a/dlls/ntdll/signal_i386.c
|
||||
+++ b/dlls/ntdll/signal_i386.c
|
||||
@@ -1821,17 +1821,19 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
if (rec->NumberParameters == 2)
|
||||
{
|
||||
- if (rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT && check_atl_thunk( rec, context ))
|
||||
- goto done;
|
||||
if (rec->ExceptionInformation[1] == 0xffffffff && check_invalid_gs( context ))
|
||||
goto done;
|
||||
if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
|
||||
rec->ExceptionInformation[0] )))
|
||||
goto done;
|
||||
- /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
|
||||
- if (rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
|
||||
+ if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
||||
+ rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
|
||||
{
|
||||
ULONG flags;
|
||||
+ if (check_atl_thunk( rec, context ))
|
||||
+ goto done;
|
||||
+
|
||||
+ /* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
|
||||
NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
|
||||
&flags, sizeof(flags), NULL );
|
||||
if (!(flags & MEM_EXECUTE_OPTION_DISABLE))
|
||||
--
|
||||
2.1.2
|
||||
|
@ -1,113 +0,0 @@
|
||||
From 8f01f73ec7329ccff04899140d8d661d9db60719 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 8 Oct 2014 21:26:28 +0200
|
||||
Subject: ntdll: Ensure force_exec_prot is also used for views with write watch
|
||||
permissions.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 8 +++++---
|
||||
dlls/ntdll/virtual.c | 36 +++++++++++++++++++++++-------------
|
||||
2 files changed, 28 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 4d8277d..2d2554b 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -2102,7 +2102,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
count = 64;
|
||||
@@ -2113,7 +2112,11 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
/* Now a bit more complicated, the page containing the code is protected with
|
||||
* PAGE_GUARD memory protection. */
|
||||
@@ -2127,7 +2130,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index f8a5dd3..3c9a4b5 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -591,6 +591,25 @@ static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot, BOOL image
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
+ * mprotect_exec
|
||||
+ *
|
||||
+ * Wrapper for mprotect, adds PROT_EXEC if forced by force_exec_prot
|
||||
+ */
|
||||
+static inline int mprotect_exec( void *base, size_t size, int unix_prot, unsigned int view_protect )
|
||||
+{
|
||||
+ if (force_exec_prot && !(view_protect & VPROT_NOEXEC) &&
|
||||
+ (unix_prot & PROT_READ) && !(unix_prot & PROT_EXEC))
|
||||
+ {
|
||||
+ TRACE( "forcing exec permission on %p-%p\n", base, (char *)base + size - 1 );
|
||||
+ if (!mprotect( base, size, unix_prot | PROT_EXEC )) return 0;
|
||||
+ /* exec + write may legitimately fail, in that case fall back to write only */
|
||||
+ if (!(unix_prot & PROT_WRITE)) return -1;
|
||||
+ }
|
||||
+
|
||||
+ return mprotect( base, size, unix_prot );
|
||||
+}
|
||||
+
|
||||
+/***********************************************************************
|
||||
* VIRTUAL_SetProt
|
||||
*
|
||||
* Change the protection of a range of pages.
|
||||
@@ -624,12 +643,12 @@ static BOOL VIRTUAL_SetProt( struct file_view *view, /* [in] Pointer to view */
|
||||
p[i] = vprot | (p[i] & VPROT_WRITEWATCH);
|
||||
prot = VIRTUAL_GetUnixProt( p[i] );
|
||||
if (prot == unix_prot) continue;
|
||||
- mprotect( addr, count << page_shift, unix_prot );
|
||||
+ mprotect_exec( addr, count << page_shift, unix_prot, view->protect );
|
||||
addr += count << page_shift;
|
||||
unix_prot = prot;
|
||||
count = 0;
|
||||
}
|
||||
- if (count) mprotect( addr, count << page_shift, unix_prot );
|
||||
+ if (count) mprotect_exec( addr, count << page_shift, unix_prot, view->protect );
|
||||
VIRTUAL_DEBUG_DUMP_VIEW( view );
|
||||
return TRUE;
|
||||
}
|
||||
@@ -646,18 +665,9 @@ static BOOL VIRTUAL_SetProt( struct file_view *view, /* [in] Pointer to view */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- if (force_exec_prot && !(view->protect & VPROT_NOEXEC) &&
|
||||
- (unix_prot & PROT_READ) && !(unix_prot & PROT_EXEC))
|
||||
- {
|
||||
- TRACE( "forcing exec permission on %p-%p\n", base, (char *)base + size - 1 );
|
||||
- if (!mprotect( base, size, unix_prot | PROT_EXEC )) goto done;
|
||||
- /* exec + write may legitimately fail, in that case fall back to write only */
|
||||
- if (!(unix_prot & PROT_WRITE)) return FALSE;
|
||||
- }
|
||||
-
|
||||
- if (mprotect( base, size, unix_prot )) return FALSE; /* FIXME: last error */
|
||||
+ if (mprotect_exec( base, size, unix_prot, view->protect )) /* FIXME: last error */
|
||||
+ return FALSE;
|
||||
|
||||
-done:
|
||||
memset( p, vprot, size >> page_shift );
|
||||
VIRTUAL_DEBUG_DUMP_VIEW( view );
|
||||
return TRUE;
|
||||
--
|
||||
2.1.2
|
||||
|
@ -1,50 +0,0 @@
|
||||
From 2ef6876f6633398bbb8d59241ea321331a5d45ea Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 8 Oct 2014 21:28:25 +0200
|
||||
Subject: ntdll: reset_write_watches shouldn't remove enforced exec
|
||||
permissions.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 6 +-----
|
||||
dlls/ntdll/virtual.c | 4 ++--
|
||||
2 files changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 2d2554b..4627c5a 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -2112,11 +2112,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
|
||||
ok( ret == 42, "call returned wrong result, expected 42, got %d\n", ret );
|
||||
ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
- if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
- else
|
||||
- todo_wine
|
||||
- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
/* Now a bit more complicated, the page containing the code is protected with
|
||||
* PAGE_GUARD memory protection. */
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index 3c9a4b5..d2bb152 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -693,12 +693,12 @@ static void reset_write_watches( struct file_view *view, void *base, SIZE_T size
|
||||
p[i] |= VPROT_WRITEWATCH;
|
||||
prot = VIRTUAL_GetUnixProt( p[i] );
|
||||
if (prot == unix_prot) continue;
|
||||
- mprotect( addr, count << page_shift, unix_prot );
|
||||
+ mprotect_exec( addr, count << page_shift, unix_prot, view->protect );
|
||||
addr += count << page_shift;
|
||||
unix_prot = prot;
|
||||
count = 0;
|
||||
}
|
||||
- if (count) mprotect( addr, count << page_shift, unix_prot );
|
||||
+ if (count) mprotect_exec( addr, count << page_shift, unix_prot, view->protect );
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.1.2
|
||||
|
@ -1,70 +0,0 @@
|
||||
From 36a090784f8fb7b4bb0e79ecfcd0fc5422474f22 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 11 Oct 2014 00:08:41 +0200
|
||||
Subject: ntdll: Only check for ATL thunk if allowed by execute option flags.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 4 ----
|
||||
dlls/ntdll/signal_i386.c | 7 ++++---
|
||||
2 files changed, 4 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 4627c5a..434d880 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1997,7 +1997,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
@@ -2013,7 +2012,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
@@ -2164,7 +2162,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
@@ -2193,7 +2190,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
ok( num_guard_page_calls == 1, "expected one STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls );
|
||||
if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
|
||||
index b9b45a8..7f01554 100644
|
||||
--- a/dlls/ntdll/signal_i386.c
|
||||
+++ b/dlls/ntdll/signal_i386.c
|
||||
@@ -1830,12 +1830,13 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
|
||||
rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
|
||||
{
|
||||
ULONG flags;
|
||||
- if (check_atl_thunk( rec, context ))
|
||||
+ NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
|
||||
+ &flags, sizeof(flags), NULL );
|
||||
+
|
||||
+ if (!(flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION) && check_atl_thunk( rec, context ))
|
||||
goto done;
|
||||
|
||||
/* send EXCEPTION_EXECUTE_FAULT only if data execution prevention is enabled */
|
||||
- NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags,
|
||||
- &flags, sizeof(flags), NULL );
|
||||
if (!(flags & MEM_EXECUTE_OPTION_DISABLE))
|
||||
rec->ExceptionInformation[0] = EXCEPTION_READ_FAULT;
|
||||
}
|
||||
--
|
||||
2.1.2
|
||||
|
Loading…
Reference in New Issue
Block a user