Added patch to return failure in NtProtectVirtualMemory when last argument is omitted.

This commit is contained in:
Sebastian Lackner
2015-05-02 18:55:34 +02:00
parent e25c35e363
commit f23ff69f86
14 changed files with 354 additions and 13 deletions

View File

@@ -0,0 +1,73 @@
From e99c972628d923d9fa53a57899b6835844ec83a2 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 2 May 2015 18:37:26 +0200
Subject: kernel32/tests: Add tests for calling VirtualProtect with NULL as
last argument.
---
dlls/kernel32/tests/virtual.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 75e91d5..311e87b 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -47,6 +47,7 @@ static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
+static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
/* ############################### */
@@ -2478,6 +2479,9 @@ static void test_VirtualProtect(void)
DWORD ret, old_prot, rw_prot, exec_prot, i, j;
MEMORY_BASIC_INFORMATION info;
SYSTEM_INFO si;
+ void *addr;
+ SIZE_T size;
+ NTSTATUS status;
GetSystemInfo(&si);
trace("system page size %#x\n", si.dwPageSize);
@@ -2486,6 +2490,29 @@ static void test_VirtualProtect(void)
base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = VirtualProtect(base, si.dwPageSize, PAGE_READONLY, NULL);
+ todo_wine
+ ok(!ret, "VirtualProtect should fail\n");
+ todo_wine
+ ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %d\n", GetLastError());
+ old_prot = 0xdeadbeef;
+ ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
+ ok(ret, "VirtualProtect failed %d\n", GetLastError());
+ todo_wine
+ ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
+
+ addr = base; size = si.dwPageSize;
+ status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL);
+ todo_wine
+ ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08x\n", status);
+ old_prot = 0xdeadbeef;
+ addr = base; size = si.dwPageSize;
+ status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot);
+ ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08x\n", status);
+ todo_wine
+ ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
+
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
{
SetLastError(0xdeadbeef);
@@ -3477,6 +3504,7 @@ START_TEST(virtual)
pNtCurrentTeb = (void *)GetProcAddress( hntdll, "NtCurrentTeb" );
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
+ pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" );
test_shared_memory(FALSE);
test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
--
2.3.5

View File

@@ -0,0 +1,33 @@
From 6e645b3f441ca310a17a06487b0a55fa629aa0d1 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 2 May 2015 18:42:09 +0200
Subject: kernel32: Do not omit mandatory argument for VirtualProtect.
---
dlls/kernel32/except.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/except.c b/dlls/kernel32/except.c
index bd50e88..2a7dbaa 100644
--- a/dlls/kernel32/except.c
+++ b/dlls/kernel32/except.c
@@ -401,6 +401,7 @@ static BOOL start_debugger_atomic(PEXCEPTION_POINTERS epointers)
*/
static inline BOOL check_resource_write( void *addr )
{
+ DWORD old_prot;
void *rsrc;
DWORD size;
MEMORY_BASIC_INFORMATION info;
@@ -412,7 +413,7 @@ static inline BOOL check_resource_write( void *addr )
return FALSE;
if (addr < rsrc || (char *)addr >= (char *)rsrc + size) return FALSE;
TRACE( "Broken app is writing to the resource data, enabling work-around\n" );
- VirtualProtect( rsrc, size, PAGE_READWRITE, NULL );
+ VirtualProtect( rsrc, size, PAGE_READWRITE, &old_prot );
return TRUE;
}
--
2.3.5

View File

@@ -0,0 +1,68 @@
From 0c9bbd27acb0df45ec7e6a501cb5e2b14bd69161 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 2 May 2015 18:43:05 +0200
Subject: krnl386.exe16: Do not omit mandatory argument for VirtualProtect.
---
dlls/krnl386.exe16/dosmem.c | 6 ++++--
dlls/krnl386.exe16/dosvm.c | 3 ++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/krnl386.exe16/dosmem.c b/dlls/krnl386.exe16/dosmem.c
index f0feba9..b899f7b 100644
--- a/dlls/krnl386.exe16/dosmem.c
+++ b/dlls/krnl386.exe16/dosmem.c
@@ -302,6 +302,7 @@ BOOL DOSMEM_InitDosMemory(void)
{
static BOOL done;
static HANDLE hRunOnce;
+ DWORD old_prot;
if (done) return TRUE;
@@ -317,7 +318,7 @@ BOOL DOSMEM_InitDosMemory(void)
/* ok, we're the winning thread */
if (!(ret = VirtualProtect( DOSMEM_dosmem + DOSMEM_protect,
DOSMEM_SIZE - DOSMEM_protect,
- PAGE_READWRITE, NULL )))
+ PAGE_READWRITE, &old_prot )))
ERR("Cannot load access low 1Mb, DOS subsystem unavailable\n");
RemoveVectoredExceptionHandler( vectored_handler );
@@ -650,10 +651,11 @@ UINT DOSMEM_Available(void)
BOOL DOSMEM_MapDosLayout(void)
{
static BOOL already_mapped;
+ DWORD old_prot;
if (!already_mapped)
{
- if (DOSMEM_dosmem || !VirtualProtect( NULL, DOSMEM_SIZE, PAGE_EXECUTE_READWRITE, NULL ))
+ if (DOSMEM_dosmem || !VirtualProtect( NULL, DOSMEM_SIZE, PAGE_EXECUTE_READWRITE, &old_prot ))
{
ERR( "Need full access to the first megabyte for DOS mode\n" );
ExitProcess(1);
diff --git a/dlls/krnl386.exe16/dosvm.c b/dlls/krnl386.exe16/dosvm.c
index 87adf33..4e76215 100644
--- a/dlls/krnl386.exe16/dosvm.c
+++ b/dlls/krnl386.exe16/dosvm.c
@@ -827,6 +827,7 @@ LPVOID DOSVM_AllocDataUMB( DWORD size, WORD *segment, WORD *selector )
*/
void DOSVM_InitSegments(void)
{
+ DWORD old_prot;
LPSTR ptr;
int i;
@@ -966,7 +967,7 @@ void DOSVM_InitSegments(void)
/*
* As we store code in UMB we should make sure it is executable
*/
- VirtualProtect((void *)DOSVM_UMB_BOTTOM, DOSVM_UMB_TOP - DOSVM_UMB_BOTTOM, PAGE_EXECUTE_READWRITE, NULL);
+ VirtualProtect((void *)DOSVM_UMB_BOTTOM, DOSVM_UMB_TOP - DOSVM_UMB_BOTTOM, PAGE_EXECUTE_READWRITE, &old_prot);
event_notifier = CreateEventW(NULL, FALSE, FALSE, NULL);
}
--
2.3.5

View File

@@ -0,0 +1,25 @@
From 7eacc14beee477a470f66c2d7524054f0a38ff86 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 2 May 2015 18:43:24 +0200
Subject: ntdll: Do not omit mandatory argument for VirtualProtect.
---
dlls/ntdll/loader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 9810f07..921bf57 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -685,7 +685,7 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d
done:
/* restore old protection of the import address table */
- NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, NULL );
+ NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, &protect_old );
return wmImp;
}
--
2.3.5

View File

@@ -0,0 +1,33 @@
From 52dd3d51573897cc41a78f86a66518946d2dca40 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 2 May 2015 18:43:34 +0200
Subject: winedevice: Do not omit mandatory argument for VirtualProtect.
---
programs/winedevice/device.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c
index 9677a82..ef1e1ef 100644
--- a/programs/winedevice/device.c
+++ b/programs/winedevice/device.c
@@ -98,14 +98,14 @@ static HMODULE load_driver_module( const WCHAR *name )
VirtualProtect( page, info.PageSize, PAGE_EXECUTE_READWRITE, &old );
rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
(USHORT *)(rel + 1), delta );
- if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, info.PageSize, old, NULL );
+ if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, info.PageSize, old, &old );
if (!rel) goto error;
}
/* make sure we don't try again */
size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader;
VirtualProtect( nt, size, PAGE_READWRITE, &old );
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
- VirtualProtect( nt, size, old, NULL );
+ VirtualProtect( nt, size, old, &old );
}
}
--
2.3.5

View File

@@ -0,0 +1,58 @@
From 4fa917bcdc3685a9181df8d1d7c1b3b07d816fc6 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 2 May 2015 18:46:38 +0200
Subject: ntdll: Return failure in NtProtectVirtualMemory when last argument is
omitted.
---
dlls/kernel32/tests/virtual.c | 5 -----
dlls/ntdll/virtual.c | 3 +++
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 311e87b..1c70eca 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -2492,25 +2492,20 @@ static void test_VirtualProtect(void)
SetLastError(0xdeadbeef);
ret = VirtualProtect(base, si.dwPageSize, PAGE_READONLY, NULL);
- todo_wine
ok(!ret, "VirtualProtect should fail\n");
- todo_wine
ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %d\n", GetLastError());
old_prot = 0xdeadbeef;
ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
ok(ret, "VirtualProtect failed %d\n", GetLastError());
- todo_wine
ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
addr = base; size = si.dwPageSize;
status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL);
- todo_wine
ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08x\n", status);
old_prot = 0xdeadbeef;
addr = base; size = si.dwPageSize;
status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot);
ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08x\n", status);
- todo_wine
ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 9d29c33..0629816 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -2164,6 +2164,9 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
TRACE("%p %p %08lx %08x\n", process, addr, size, new_prot );
+ if (!old_prot)
+ return STATUS_ACCESS_VIOLATION;
+
if (process != NtCurrentProcess())
{
apc_call_t call;
--
2.3.5

View File

@@ -0,0 +1 @@
Fixes: [38495] Return failure in NtProtectVirtualMemory when last argument is omitted