[PATCH] ntdll: Fixed file view mapping in regards to no-exec

Marcus Meissner marcus at jet.franken.de
Sun Nov 14 05:52:01 CST 2010


Hi,

A readwrite mapped file should also get its execute permissions
turned on.

This is only testable by actually executing code in it.

http://bugs.winehq.org/show_bug.cgi?id=25057

Ciao, Marcus
---
 dlls/ntdll/tests/info.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/virtual.c    |    6 +++-
 2 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 6345e08..beffca8 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -29,6 +29,10 @@ static NTSTATUS (WINAPI * pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PV
 static NTSTATUS (WINAPI * pNtSetInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
 static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
 static NTSTATUS (WINAPI * pNtQueryVirtualMemory)(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS , PVOID , SIZE_T , SIZE_T *);
+static NTSTATUS (WINAPI * pNtCreateSection)(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
+static NTSTATUS (WINAPI * pNtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG);
+static NTSTATUS (WINAPI * pNtUnmapViewOfSection)(HANDLE,PVOID);
+static NTSTATUS (WINAPI * pNtClose)(HANDLE);
 static BOOL     (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
 
 static BOOL is_wow64;
@@ -63,6 +67,10 @@ static BOOL InitFunctionPtrs(void)
     NTDLL_GET_PROC(NtSetInformationThread);
     NTDLL_GET_PROC(NtReadVirtualMemory);
     NTDLL_GET_PROC(NtQueryVirtualMemory);
+    NTDLL_GET_PROC(NtClose);
+    NTDLL_GET_PROC(NtCreateSection);
+    NTDLL_GET_PROC(NtMapViewOfSection);
+    NTDLL_GET_PROC(NtUnmapViewOfSection);
 
     pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
     if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
@@ -1068,6 +1076,67 @@ static void test_readvirtualmemory(void)
     CloseHandle(process);
 }
 
+static void test_mapprotection(void)
+{
+    HANDLE h;
+    void* addr;
+    MEMORY_BASIC_INFORMATION info;
+    ULONG oldflags, flagsize, flags = MEM_EXECUTE_OPTION_ENABLE;
+    LARGE_INTEGER size, offset;
+    NTSTATUS status;
+    SIZE_T retlen, count;
+    void (*f)(void);
+
+    if (!pNtClose) {
+        skip("No NtClose ... Win98\n");
+        return;
+    }
+    /* Switch to being a noexec unaware process */
+    status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof (oldflags), &flagsize);
+    if (status == STATUS_INVALID_PARAMETER) {
+        skip("Invalid Parameter on ProcessExecuteFlags query?\n");
+        return;
+    }
+    ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
+    status = pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
+    ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
+
+    size.u.LowPart  = 0x1000;
+    size.u.HighPart = 0;
+    status = pNtCreateSection ( &h,
+        STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
+        NULL,
+        &size,
+        PAGE_READWRITE,
+        SEC_COMMIT | SEC_NOCACHE,
+        0
+    );
+    ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+
+    offset.u.LowPart  = 0;
+    offset.u.HighPart = 0;
+    count = 0x1000;
+    addr = NULL;
+    status = pNtMapViewOfSection ( h, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, PAGE_READWRITE);
+    ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+    memset (addr, 0xc3, 1); /* lret ... in both i386 and x86_64 */
+    trace("trying to execute code in the readwrite only mapped anon file...\n");
+    f = addr;f();
+    trace("...done.\n");
+
+    status = pNtQueryVirtualMemory( GetCurrentProcess(), addr, MemoryBasicInformation, &info, sizeof(info), &retlen );
+    ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+    ok( retlen == sizeof(info), "Expected STATUS_SUCCESS, got %08x\n", status);
+    ok(info.Protect == PAGE_READWRITE, "addr.Protect is not PAGE_READWRITE, but 0x%x\n", info.Protect);
+
+    status = pNtUnmapViewOfSection (GetCurrentProcess(), addr);
+    ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+    pNtClose (h);
+
+    /* Switch back */
+    pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof(oldflags) );
+}
+
 static void test_queryvirtualmemory(void)
 {
     NTSTATUS status;
@@ -1340,9 +1409,13 @@ START_TEST(info)
     /* belongs into it's own file */
     trace("Starting test_readvirtualmemory()\n");
     test_readvirtualmemory();
+
     trace("Starting test_queryvirtualmemory()\n");
     test_queryvirtualmemory();
 
+    trace("Starting test_mapprotection()\n");
+    test_mapprotection();
+
     trace("Starting test_affinity()\n");
     test_affinity();
 }
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 7dff79f..587c4a3 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -862,6 +862,11 @@ static NTSTATUS map_file_into_view( struct file_view *view, int fd, size_t start
     assert( start < view->size );
     assert( start + size <= view->size );
 
+    if (force_exec_prot && !(vprot & VPROT_NOEXEC) && (vprot & VPROT_READ)) {
+        TRACE( "forcing exec permission on file mapping.\n" );
+        prot |= PROT_EXEC;
+    }
+
     /* only try mmap if media is not removable (or if we require write access) */
     if (!removable || shared_write)
     {
@@ -2566,7 +2571,6 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
 
     TRACE("handle=%p size=%lx offset=%x%08x\n",
           handle, size, offset.u.HighPart, offset.u.LowPart );
-
     res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, vprot, !dup_mapping );
     if (res == STATUS_SUCCESS)
     {
-- 
1.7.1



More information about the wine-patches mailing list