mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Updated patch for ntdll-ATL_Thunk.
This commit is contained in:
parent
9e2db30661
commit
8a1c3d4d46
@ -35,10 +35,12 @@ Wine. All those differences are also documented on the
|
||||
Included bugfixes and improvements
|
||||
==================================
|
||||
|
||||
**Bugfixes and features included in the next upcoming release [4]:**
|
||||
**Bugfixes and features included in the next upcoming release [6]:**
|
||||
|
||||
* ATL thunk check shouldn't trigger page fault ([Wine Bug #19296](http://bugs.winehq.org/show_bug.cgi?id=19296))
|
||||
* Anno 1602 installer depends on Windows 98 behavior of SHFileOperationW
|
||||
* FEAR 1 installer expects basic_string_wchar_dtor to return NULL ([Wine Bug #37358](http://bugs.winehq.org/show_bug.cgi?id=37358))
|
||||
* Fix issue with ATL thunks in combination with guard pages ([Wine Bug #34479](http://bugs.winehq.org/show_bug.cgi?id=34479))
|
||||
* Support for UTF7 encoding/decoding ([Wine Bug #27388](http://bugs.winehq.org/show_bug.cgi?id=27388))
|
||||
* Wine ignores IDF_CHECKFIRST flag in SetupPromptForDisk ([Wine Bug #20465](http://bugs.winehq.org/show_bug.cgi?id=20465))
|
||||
|
||||
|
@ -543,7 +543,11 @@ msvcp90-basic_string_wchar_dtor.ok:
|
||||
# Patchset ntdll-ATL_Thunk
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Fix several issues with execute permissions in guard page / write watch handling. [by Sebastian Lackner]
|
||||
# | * Fix several issues with execute permissions in guard page / write watch handling. [rev 2, by Sebastian Lackner]
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#19296] ATL thunk check shouldn't trigger page fault
|
||||
# | * [#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
|
||||
@ -554,9 +558,11 @@ ntdll-ATL_Thunk.ok:
|
||||
$(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-DEP-is-not-enabled.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)
|
||||
@( \
|
||||
echo '+ { "ntdll-ATL_Thunk", "Sebastian Lackner", "Fix several issues with execute permissions in guard page / write watch handling." },'; \
|
||||
echo '+ { "ntdll-ATL_Thunk", "Sebastian Lackner", "Fix several issues with execute permissions in guard page / write watch handling. [rev 2]" },'; \
|
||||
) > ntdll-ATL_Thunk.ok
|
||||
|
||||
# Patchset ntdll-DOS_Attributes
|
||||
|
@ -1,26 +1,34 @@
|
||||
From c672ac883d5b2c6f00fb6cff0abd70887dbbcef1 Mon Sep 17 00:00:00 2001
|
||||
From 58524cf1b19cd820ee51e38e5ca6c002142f2047 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 | 293 ++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/kernel32/tests/virtual.c | 438 ++++++++++++++++++++++++++++++++++++++++++
|
||||
include/winternl.h | 1 +
|
||||
2 files changed, 294 insertions(+)
|
||||
2 files changed, 439 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 0fa2b99..ecb5d2f 100644
|
||||
index 0fa2b99..47feff1 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1797,6 +1797,295 @@ static void test_guard_page(void)
|
||||
@@ -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,438 @@ static void test_guard_page(void)
|
||||
VirtualFree( base, 0, MEM_FREE );
|
||||
}
|
||||
|
||||
+DWORD num_execute_fault_calls;
|
||||
+
|
||||
+static DWORD execute_fault_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
+ CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
+static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
+ CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
+{
|
||||
+ trace( "exception: %08x flags:%x addr:%p\n",
|
||||
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
@ -52,25 +60,52 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ return ExceptionContinueExecution;
|
||||
+}
|
||||
+
|
||||
+static DWORD atl_test_func( DWORD arg )
|
||||
+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_data_execution_prevention( ULONG dep_flags )
|
||||
+static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
+{
|
||||
+ static const char code_ret[] = {0xB8, 0x2A, 0x00, 0x00, 0x00, 0xC3};
|
||||
+ 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};
|
||||
+ EXCEPTION_REGISTRATION_RECORD frame;
|
||||
+ DWORD (*code)(DWORD);
|
||||
+ 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)
|
||||
+ {
|
||||
@ -80,7 +115,6 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+
|
||||
+ trace( "Running DEP tests with ProcessExecuteFlags = %d\n", dep_flags );
|
||||
+
|
||||
+ /* Adjust ProcessExecuteFlags if necessary */
|
||||
+ NtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &old_flags, sizeof(old_flags), NULL );
|
||||
+ if (old_flags != dep_flags)
|
||||
+ {
|
||||
@ -97,16 +131,43 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
|
||||
+ ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
+
|
||||
+ /* write some instructions into the memory, and try to execute it */
|
||||
+ memcpy( base, code_ret, sizeof(code_ret) );
|
||||
+ code = (void *)base;
|
||||
+ memcpy( base, code_jmp, sizeof(code_jmp) );
|
||||
+ *(DWORD *)(base + 1) = (DWORD_PTR)jmp_test_func - (DWORD_PTR)(base + 5);
|
||||
+
|
||||
+ frame.Handler = execute_fault_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+ /* 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. */
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ 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)
|
||||
@ -114,22 +175,13 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ else
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+ /* 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() );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+ else
|
||||
+ ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+
|
||||
+ /* the same, but with PAGE_GUARD set */
|
||||
+ frame.Handler = execute_fault_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ 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)
|
||||
@ -138,45 +190,74 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+ 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. */
|
||||
+
|
||||
+ /* special case, test with ATL thunk */
|
||||
+ memcpy( base, code_atl, sizeof(code_atl) );
|
||||
+ *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+
|
||||
+ frame.Handler = execute_fault_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+ ret = SendMessageA(hWnd, WM_USER, 0, 0);
|
||||
+ ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ /* 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 == 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_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 );
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ /* 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 );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+ /* 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 );
|
||||
+
|
||||
+ /* same as above, but using memory with a write watch */
|
||||
+ /* 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))
|
||||
+ {
|
||||
@ -186,13 +267,12 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
+
|
||||
+ count = 64;
|
||||
+ ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
+ 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 );
|
||||
+
|
||||
+ /* write some instructions into the memory, and try to execute it */
|
||||
+ memcpy( base, code_ret, sizeof(code_ret) );
|
||||
+ code = (void *)base;
|
||||
+ 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 );
|
||||
@ -200,12 +280,41 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ ok( count == 1, "wrong count %lu\n", count );
|
||||
+ ok( results[0] == base, "wrong result %p\n", results[0] );
|
||||
+
|
||||
+ frame.Handler = execute_fault_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+ /* Create a new window class and associcated Window (see above) */
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ 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)
|
||||
@ -214,28 +323,23 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+
|
||||
+ 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() );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+
|
||||
+ /* the same, but with PAGE_GUARD set */
|
||||
+ frame.Handler = execute_fault_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ 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)
|
||||
@ -244,14 +348,18 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+ 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 );
|
||||
+ ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
|
||||
+
|
||||
+ /* Now test with a proper ATL thunk instruction. */
|
||||
+
|
||||
+ /* special case, test with ATL thunk */
|
||||
+ memcpy( base, code_atl, sizeof(code_atl) );
|
||||
+ *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13);
|
||||
+
|
||||
@ -261,30 +369,56 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ ok( count == 1, "wrong count %lu\n", count );
|
||||
+ ok( results[0] == base, "wrong result %p\n", results[0] );
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
+ success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+ if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
+ ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+ else
|
||||
+ todo_wine
|
||||
+ ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
+
|
||||
+ frame.Handler = execute_fault_handler;
|
||||
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
+ ret = SendMessageA(hWnd, WM_USER, 0, 0);
|
||||
+ ok( ret == 43, "SendMessage returned unexpected result %d\n", ret );
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ /* 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 == 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_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 );
|
||||
+
|
||||
+ num_guard_page_calls = num_execute_fault_calls = 0;
|
||||
+ ret = code( 0xdeadbeef );
|
||||
+ 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 );
|
||||
@ -292,9 +426,26 @@ index 0fa2b99..ecb5d2f 100644
|
||||
+ 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 );
|
||||
+ ok( count == 0 || broken(count == 1) /* Windows 8 */, "wrong count %lu\n", count );
|
||||
+
|
||||
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
+ /* 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 );
|
||||
+
|
||||
@ -309,25 +460,26 @@ index 0fa2b99..ecb5d2f 100644
|
||||
#endif /* __i386__ */
|
||||
|
||||
static void test_VirtualProtect(void)
|
||||
@@ -2859,5 +3148,9 @@ START_TEST(virtual)
|
||||
@@ -2859,5 +3292,10 @@ START_TEST(virtual)
|
||||
test_write_watch();
|
||||
#ifdef __i386__
|
||||
test_guard_page();
|
||||
+ test_data_execution_prevention( MEM_EXECUTE_OPTION_ENABLE );
|
||||
+ test_data_execution_prevention( MEM_EXECUTE_OPTION_ENABLE | MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION );
|
||||
+ test_data_execution_prevention( MEM_EXECUTE_OPTION_DISABLE );
|
||||
+ test_data_execution_prevention( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION );
|
||||
+ /* 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..7f9a85d 100644
|
||||
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_ATL7_THUNK_EMULATION 0x04
|
||||
+#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 0x04
|
||||
#define MEM_EXECUTE_OPTION_PERMANENT 0x08
|
||||
|
||||
typedef enum _SECTION_INHERIT {
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 5dc9f7a909b8d0e7bee4be1c0b846a21b7e78240 Mon Sep 17 00:00:00 2001
|
||||
From 0c2c4a58bd184a58e05ce2eb361c1dc565569a2c 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
|
||||
@ -11,30 +11,22 @@ check is executed, and removes the guard page protection. Afterwards, when the A
|
||||
check returns, the exception is _not_ catched by virtual_handle_fault, but instead
|
||||
passed to the application.
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 2 --
|
||||
dlls/kernel32/tests/virtual.c | 1 -
|
||||
dlls/ntdll/signal_i386.c | 10 ++++++----
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
2 files changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index ecb5d2f..90a5578 100644
|
||||
index 47feff1..7905320 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1915,7 +1915,6 @@ static void test_data_execution_prevention( ULONG dep_flags )
|
||||
@@ -1960,7 +1960,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 );
|
||||
|
||||
pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
@@ -1929,7 +1928,6 @@ static void test_data_execution_prevention( ULONG dep_flags )
|
||||
if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
else
|
||||
- todo_wine
|
||||
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
|
||||
frame.Handler = execute_fault_handler;
|
||||
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
|
||||
|
@ -1,34 +1,47 @@
|
||||
From 94360ac47e9300f85ab0f63c49ba8044107ac1c1 Mon Sep 17 00:00:00 2001
|
||||
From bf053b74d743f38789ad01a0ad2610925c571e25 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 | 2 --
|
||||
dlls/kernel32/tests/virtual.c | 8 +++++---
|
||||
dlls/ntdll/virtual.c | 36 +++++++++++++++++++++++-------------
|
||||
2 files changed, 23 insertions(+), 15 deletions(-)
|
||||
2 files changed, 28 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 90a5578..a233b37 100644
|
||||
index 7905320..a58d085 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -2019,7 +2019,6 @@ static void test_data_execution_prevention( ULONG dep_flags )
|
||||
@@ -2092,7 +2092,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 );
|
||||
|
||||
pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
@@ -2044,7 +2043,6 @@ static void test_data_execution_prevention( ULONG dep_flags )
|
||||
count = 64;
|
||||
@@ -2103,7 +2102,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. */
|
||||
@@ -2117,7 +2120,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
else
|
||||
- todo_wine
|
||||
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
frame.Handler = execute_fault_handler;
|
||||
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
|
||||
|
@ -1,34 +1,31 @@
|
||||
From db098e8367cb2f01a7f5a4d6309e0ea476821e60 Mon Sep 17 00:00:00 2001
|
||||
From 8385e203f822c454373a1fd21f99bd4a47f9ea0d 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 | 2 --
|
||||
dlls/kernel32/tests/virtual.c | 6 +-----
|
||||
dlls/ntdll/virtual.c | 4 ++--
|
||||
2 files changed, 2 insertions(+), 4 deletions(-)
|
||||
2 files changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index a233b37..f236edb 100644
|
||||
index a58d085..8e3f43f 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1989,7 +1989,6 @@ static void test_data_execution_prevention( 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
|
||||
@@ -2102,11 +2102,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 );
|
||||
+ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
|
||||
pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
@@ -2004,7 +2003,6 @@ static void test_data_execution_prevention( ULONG dep_flags )
|
||||
if (dep_flags & MEM_EXECUTE_OPTION_DISABLE)
|
||||
ok( old_prot == PAGE_EXECUTE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
else
|
||||
- todo_wine
|
||||
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
|
||||
/* the same, but with PAGE_GUARD set */
|
||||
/* 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
|
||||
|
@ -1,56 +0,0 @@
|
||||
From 7df7b751e99689d72cf41095df1d697ccc41a1ab Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 8 Oct 2014 21:32:46 +0200
|
||||
Subject: ntdll: Only check for ATL thunk if DEP is not enabled.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 2 --
|
||||
dlls/ntdll/signal_i386.c | 8 ++++----
|
||||
2 files changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index f236edb..1bed9bc 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1939,7 +1939,6 @@ static void test_data_execution_prevention( 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)
|
||||
- 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 );
|
||||
@@ -2052,7 +2051,6 @@ static void test_data_execution_prevention( 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)
|
||||
- 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..f854dec 100644
|
||||
--- a/dlls/ntdll/signal_i386.c
|
||||
+++ b/dlls/ntdll/signal_i386.c
|
||||
@@ -1830,14 +1830,14 @@ 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 ))
|
||||
- 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))
|
||||
+ {
|
||||
+ if (check_atl_thunk( rec, context ))
|
||||
+ goto done;
|
||||
rec->ExceptionInformation[0] = EXCEPTION_READ_FAULT;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
break;
|
||||
--
|
||||
2.1.2
|
||||
|
@ -0,0 +1,70 @@
|
||||
From 1724b495cbaad5a806d74785bb8d8a53c9ff7062 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 8e3f43f..def2011 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -1987,7 +1987,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 );
|
||||
@@ -2003,7 +2002,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 );
|
||||
@@ -2154,7 +2152,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 );
|
||||
@@ -2183,7 +2180,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
|
||||
|
@ -0,0 +1,127 @@
|
||||
From 4298254e506fae9d2f3d119286309ac1598a0d4e Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 11 Oct 2014 00:35:02 +0200
|
||||
Subject: kernel32/tests: Add test to show incorrect behaviour in ATL thunk
|
||||
handler.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 71 +++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 65 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index def2011..1bd04ee 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -35,7 +35,7 @@
|
||||
#define NUM_THREADS 4
|
||||
#define MAPPING_SIZE 0x100000
|
||||
|
||||
-static HINSTANCE hkernel32;
|
||||
+static HINSTANCE hkernel32, hntdll;
|
||||
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
||||
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
|
||||
static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
|
||||
@@ -44,6 +44,8 @@ static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
|
||||
static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
|
||||
static DWORD (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
|
||||
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
||||
+static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
|
||||
+static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
|
||||
|
||||
/* ############################### */
|
||||
|
||||
@@ -1833,6 +1835,31 @@ static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTR
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
+static LONG CALLBACK execute_fault_vec_handler( EXCEPTION_POINTERS *ExceptionInfo )
|
||||
+{
|
||||
+ PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
|
||||
+ DWORD old_prot;
|
||||
+ BOOL success;
|
||||
+
|
||||
+ trace( "exception: %08x flags:%x addr:%p\n",
|
||||
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
+
|
||||
+ ok( rec->NumberParameters == 2, "NumberParameters is %d instead of 2\n", rec->NumberParameters );
|
||||
+ ok( rec->ExceptionCode == STATUS_ACCESS_VIOLATION,
|
||||
+ "ExceptionCode is %08x instead of STATUS_ACCESS_VIOLATION\n", rec->ExceptionCode );
|
||||
+
|
||||
+ num_execute_fault_calls++;
|
||||
+
|
||||
+ if (rec->ExceptionInformation[0] == EXCEPTION_READ_FAULT)
|
||||
+ return EXCEPTION_CONTINUE_SEARCH;
|
||||
+
|
||||
+ success = VirtualProtect( (void *)rec->ExceptionInformation[1], 16, PAGE_EXECUTE_READWRITE, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+ ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
|
||||
+
|
||||
+ return EXCEPTION_CONTINUE_EXECUTION;
|
||||
+}
|
||||
+
|
||||
static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
@@ -2011,6 +2038,35 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
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 );
|
||||
|
||||
+ /* The following test shows that on Windows, even a vectored exception handler cannot intercept
|
||||
+ * internal exceptions thrown by the ATL thunk emulation layer. */
|
||||
+
|
||||
+
|
||||
+ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && !(dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION))
|
||||
+ {
|
||||
+ if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
|
||||
+ {
|
||||
+ PVOID vectored_handler;
|
||||
+
|
||||
+ success = VirtualProtect( base, size, PAGE_NOACCESS, &old_prot );
|
||||
+ ok( success, "VirtualProtect failed %u\n", GetLastError() );
|
||||
+
|
||||
+ vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, &execute_fault_vec_handler );
|
||||
+ ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
|
||||
+
|
||||
+ num_execute_fault_calls = 0;
|
||||
+ ret = SendMessageA( hWnd, WM_USER, 0, 0 );
|
||||
+
|
||||
+ pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
||||
+
|
||||
+ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
+ todo_wine
|
||||
+ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
+ }
|
||||
+ else
|
||||
+ win_skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
|
||||
+ }
|
||||
+
|
||||
/* Restore the JMP instruction, set to executable, and then destroy the Window */
|
||||
|
||||
memcpy( base, code_jmp, sizeof(code_jmp) );
|
||||
@@ -3255,15 +3311,18 @@ START_TEST(virtual)
|
||||
}
|
||||
|
||||
hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||
+ hntdll = GetModuleHandleA("ntdll.dll");
|
||||
+
|
||||
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
|
||||
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
|
||||
pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
|
||||
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
|
||||
- pNtAreMappedFilesTheSame = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"),
|
||||
- "NtAreMappedFilesTheSame" );
|
||||
- pNtMapViewOfSection = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtMapViewOfSection");
|
||||
- pNtUnmapViewOfSection = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection");
|
||||
- pNtCurrentTeb = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtCurrentTeb" );
|
||||
+ pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" );
|
||||
+ pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" );
|
||||
+ pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" );
|
||||
+ pNtCurrentTeb = (void *)GetProcAddress( hntdll, "NtCurrentTeb" );
|
||||
+ pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
|
||||
+ pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
|
||||
|
||||
test_shared_memory(FALSE);
|
||||
test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
|
||||
--
|
||||
2.1.2
|
||||
|
@ -0,0 +1,48 @@
|
||||
From 1651ad24a94ffa9b75e498822c92ecfedc16d9c7 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 11 Oct 2014 02:04:27 +0200
|
||||
Subject: ntdll: Try to not raise exceptions when checking for ATL thunks.
|
||||
|
||||
Original patch by Markus Amsler.
|
||||
---
|
||||
dlls/kernel32/tests/virtual.c | 1 -
|
||||
dlls/ntdll/signal_i386.c | 7 +++++++
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
|
||||
index 1bd04ee..e6b1aee 100644
|
||||
--- a/dlls/kernel32/tests/virtual.c
|
||||
+++ b/dlls/kernel32/tests/virtual.c
|
||||
@@ -2060,7 +2060,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
|
||||
pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
||||
|
||||
ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret );
|
||||
- todo_wine
|
||||
ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls );
|
||||
}
|
||||
else
|
||||
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
|
||||
index 7f01554..48212ba 100644
|
||||
--- a/dlls/ntdll/signal_i386.c
|
||||
+++ b/dlls/ntdll/signal_i386.c
|
||||
@@ -1633,10 +1633,17 @@ struct atl_thunk
|
||||
static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||
{
|
||||
const struct atl_thunk *thunk = (const struct atl_thunk *)rec->ExceptionInformation[1];
|
||||
+ MEMORY_BASIC_INFORMATION mbi;
|
||||
+ NTSTATUS status;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!virtual_is_valid_code_address( thunk, sizeof(*thunk) )) return FALSE;
|
||||
|
||||
+ /* Try to avoid exceptions, to not confuse debuggers / vectored handlers. */
|
||||
+ status = NtQueryVirtualMemory( NtCurrentProcess(), thunk, 0, &mbi, sizeof(mbi), NULL );
|
||||
+ if (status != STATUS_SUCCESS || (mbi.Protect & PAGE_NOACCESS))
|
||||
+ return FALSE;
|
||||
+
|
||||
__TRY
|
||||
{
|
||||
if (thunk->movl == 0x042444c7 && thunk->jmp == 0xe9)
|
||||
--
|
||||
2.1.2
|
||||
|
@ -1,3 +1,5 @@
|
||||
Author: Sebastian Lackner
|
||||
Subject: Fix several issues with execute permissions in guard page / write watch handling.
|
||||
Revision: 1
|
||||
Revision: 2
|
||||
Fixes: [19296] ATL thunk check shouldn't trigger page fault
|
||||
Fixes: [34479] Fix issue with ATL thunks in combination with guard pages
|
||||
|
Loading…
Reference in New Issue
Block a user