[1/2] ntdll: Setting WRITECOPY protection on an image section is allowed. Resend.

Dmitry Timoshkov dmitry at baikal.ru
Tue Nov 8 22:32:42 CST 2011


This patch should fix the regression reported in the bug 28994.
---
 dlls/ntdll/virtual.c |   35 ++++++++++++++++++++++++-----------
 1 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index fb8786f..11869a1 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -555,7 +555,7 @@ static DWORD VIRTUAL_GetWin32Prot( BYTE vprot )
  * RETURNS
  *	Value of page protection flags
  */
-static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )
+static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot, BOOL image )
 {
     switch(protect & 0xff)
     {
@@ -563,7 +563,10 @@ static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )
         *vprot = VPROT_READ;
         break;
     case PAGE_READWRITE:
-        *vprot = VPROT_READ | VPROT_WRITE;
+        if (image)
+            *vprot = VPROT_READ | VPROT_WRITECOPY;
+        else
+            *vprot = VPROT_READ | VPROT_WRITE;
         break;
     case PAGE_WRITECOPY:
         *vprot = VPROT_READ | VPROT_WRITECOPY;
@@ -575,7 +578,10 @@ static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot )
         *vprot = VPROT_EXEC | VPROT_READ;
         break;
     case PAGE_EXECUTE_READWRITE:
-        *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;
+        if (image)
+            *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
+        else
+            *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITE;
         break;
     case PAGE_EXECUTE_WRITECOPY:
         *vprot = VPROT_EXEC | VPROT_READ | VPROT_WRITECOPY;
@@ -1869,7 +1875,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG zero_
 
     if (is_beyond_limit( 0, size, working_set_limit )) return STATUS_WORKING_SET_LIMIT_RANGE;
 
-    if ((status = get_vprot_flags( protect, &vprot ))) return status;
+    if ((status = get_vprot_flags( protect, &vprot, FALSE ))) return status;
     if (vprot & VPROT_WRITECOPY) return STATUS_INVALID_PAGE_PROTECTION;
     vprot |= VPROT_VALLOC;
     if (type & MEM_COMMIT) vprot |= VPROT_COMMITTED;
@@ -2088,9 +2094,6 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
 
     size = ROUND_SIZE( addr, size );
     base = ROUND_ADDR( addr, page_mask );
-    if ((status = get_vprot_flags( new_prot, &new_vprot ))) return status;
-    if (new_vprot & VPROT_WRITECOPY) return STATUS_INVALID_PAGE_PROTECTION;
-    new_vprot |= VPROT_COMMITTED;
 
     server_enter_uninterrupted_section( &csVirtual, &sigset );
 
@@ -2103,8 +2106,18 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
         /* Make sure all the pages are committed */
         if (get_committed_size( view, base, &vprot ) >= size && (vprot & VPROT_COMMITTED))
         {
-            if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot );
-            if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED;
+            if (!(status = get_vprot_flags( new_prot, &new_vprot, view->protect & VPROT_IMAGE )))
+            {
+                new_vprot |= VPROT_COMMITTED;
+
+                if ((new_vprot & VPROT_WRITECOPY) && !(view->protect & VPROT_IMAGE))
+                    status = STATUS_INVALID_PAGE_PROTECTION;
+                else
+                {
+                    if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot );
+                    if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED;
+                }
+            }
         }
         else status = STATUS_NOT_COMMITTED;
     }
@@ -2397,7 +2410,7 @@ NTSTATUS WINAPI NtCreateSection( HANDLE *handle, ACCESS_MASK access, const OBJEC
 
     if (len > MAX_PATH*sizeof(WCHAR)) return STATUS_NAME_TOO_LONG;
 
-    if ((ret = get_vprot_flags( protect, &vprot ))) return ret;
+    if ((ret = get_vprot_flags( protect, &vprot, sec_flags & SEC_IMAGE ))) return ret;
 
     objattr.rootdir = wine_server_obj_handle( attr ? attr->RootDirectory : 0 );
     objattr.sd_len = 0;
@@ -2607,7 +2620,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
 
     server_enter_uninterrupted_section( &csVirtual, &sigset );
 
-    get_vprot_flags( protect, &vprot );
+    get_vprot_flags( protect, &vprot, map_vprot & VPROT_IMAGE );
     vprot |= (map_vprot & VPROT_COMMITTED);
     res = map_view( &view, *addr_ptr, size, mask, FALSE, vprot );
     if (res)
-- 
1.7.7.2




More information about the wine-patches mailing list