2020-07-03 16:18:38 -07:00
|
|
|
From f59e093e93d4ed55111489186ae73f8f3d7ee632 Mon Sep 17 00:00:00 2001
|
2020-04-28 04:07:19 -07:00
|
|
|
From: Andrew Wesie <awesie@gmail.com>
|
|
|
|
Date: Fri, 24 Apr 2020 14:55:14 -0500
|
|
|
|
Subject: [PATCH] ntdll: Track if a WRITECOPY page has been modified.
|
|
|
|
|
|
|
|
Once a WRITECOPY page is modified, it should be mapped as if it is a normal
|
|
|
|
read-write page.
|
|
|
|
|
|
|
|
Signed-off-by: Andrew Wesie <awesie@gmail.com>
|
|
|
|
---
|
2020-06-02 16:20:16 -07:00
|
|
|
dlls/ntdll/unix/virtual.c | 25 +++++++++++++++++++------
|
2020-04-28 04:07:19 -07:00
|
|
|
1 file changed, 19 insertions(+), 6 deletions(-)
|
|
|
|
|
2020-06-02 16:20:16 -07:00
|
|
|
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
2020-07-03 16:18:38 -07:00
|
|
|
index b059261b3c0..0a6d7691575 100644
|
2020-06-02 16:20:16 -07:00
|
|
|
--- a/dlls/ntdll/unix/virtual.c
|
|
|
|
+++ b/dlls/ntdll/unix/virtual.c
|
|
|
|
@@ -97,6 +97,7 @@ struct file_view
|
2020-04-28 04:07:19 -07:00
|
|
|
#define VPROT_GUARD 0x10
|
|
|
|
#define VPROT_COMMITTED 0x20
|
|
|
|
#define VPROT_WRITEWATCH 0x40
|
|
|
|
+#define VPROT_WRITTEN 0x80
|
|
|
|
/* per-mapping protection flags */
|
|
|
|
#define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */
|
|
|
|
|
2020-07-03 16:18:38 -07:00
|
|
|
@@ -811,7 +812,7 @@ static int get_unix_prot( BYTE vprot )
|
2020-04-28 04:07:19 -07:00
|
|
|
#if defined(__i386__)
|
|
|
|
if (vprot & VPROT_WRITECOPY)
|
|
|
|
{
|
|
|
|
- if (experimental_WRITECOPY())
|
|
|
|
+ if (experimental_WRITECOPY() && !(vprot & VPROT_WRITTEN))
|
|
|
|
prot = (prot & ~PROT_WRITE) | PROT_READ;
|
|
|
|
else
|
|
|
|
prot |= PROT_WRITE | PROT_READ;
|
2020-07-03 16:18:38 -07:00
|
|
|
@@ -1390,7 +1391,11 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
|
2020-04-28 04:07:19 -07:00
|
|
|
*/
|
2020-06-02 16:20:16 -07:00
|
|
|
static DWORD get_win32_prot( BYTE vprot, unsigned int map_prot )
|
2020-04-28 04:07:19 -07:00
|
|
|
{
|
|
|
|
- DWORD ret = VIRTUAL_Win32Flags[vprot & 0x0f];
|
|
|
|
+ DWORD ret;
|
|
|
|
+
|
|
|
|
+ if ((vprot & VPROT_WRITECOPY) && (vprot & VPROT_WRITTEN))
|
|
|
|
+ vprot = (vprot & ~VPROT_WRITECOPY) | VPROT_WRITE;
|
|
|
|
+ ret = VIRTUAL_Win32Flags[vprot & 0x0f];
|
|
|
|
if (vprot & VPROT_GUARD) ret |= PAGE_GUARD;
|
|
|
|
if (map_prot & SEC_NOCACHE) ret |= PAGE_NOCACHE;
|
|
|
|
return ret;
|
2020-07-03 16:18:38 -07:00
|
|
|
@@ -1501,7 +1506,7 @@ static BOOL set_vprot( struct file_view *view, void *base, size_t size, BYTE vpr
|
2020-04-28 04:07:19 -07:00
|
|
|
if (view->protect & VPROT_WRITEWATCH)
|
|
|
|
{
|
|
|
|
/* each page may need different protections depending on write watch flag */
|
|
|
|
- set_page_vprot_bits( base, size, vprot & ~VPROT_WRITEWATCH, ~vprot & ~VPROT_WRITEWATCH );
|
|
|
|
+ set_page_vprot_bits( base, size, vprot & ~VPROT_WRITEWATCH, ~vprot & ~(VPROT_WRITEWATCH|VPROT_WRITTEN) );
|
|
|
|
mprotect_range( base, size, 0, 0 );
|
|
|
|
return TRUE;
|
|
|
|
}
|
2020-07-03 16:18:38 -07:00
|
|
|
@@ -1517,10 +1522,18 @@ static BOOL set_vprot( struct file_view *view, void *base, size_t size, BYTE vpr
|
2020-04-28 04:07:19 -07:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ /* check that we can map this memory with PROT_WRITE since we cannot fail later */
|
|
|
|
+ if (vprot & VPROT_WRITECOPY)
|
|
|
|
+ unix_prot |= PROT_WRITE;
|
|
|
|
+
|
|
|
|
if (mprotect_exec( base, size, unix_prot )) /* FIXME: last error */
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
- set_page_vprot( base, size, vprot );
|
|
|
|
+ /* each page may need different protections depending on writecopy */
|
|
|
|
+ set_page_vprot_bits( base, size, vprot, ~vprot & ~VPROT_WRITTEN );
|
|
|
|
+ if (vprot & VPROT_WRITECOPY)
|
|
|
|
+ mprotect_range( base, size, 0, 0 );
|
|
|
|
+
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-07-03 16:18:38 -07:00
|
|
|
@@ -2882,7 +2895,7 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
|
2020-04-28 04:07:19 -07:00
|
|
|
}
|
|
|
|
if (vprot & VPROT_WRITECOPY)
|
|
|
|
{
|
|
|
|
- set_page_vprot_bits( page, page_size, VPROT_WRITE, VPROT_WRITECOPY );
|
|
|
|
+ set_page_vprot_bits( page, page_size, VPROT_WRITE | VPROT_WRITTEN, VPROT_WRITECOPY );
|
|
|
|
mprotect_range( page, page_size, 0, 0 );
|
|
|
|
}
|
|
|
|
/* ignore fault if page is writable now */
|
2020-07-03 16:18:38 -07:00
|
|
|
@@ -3812,7 +3825,7 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
|
2020-04-28 04:07:19 -07:00
|
|
|
else if (view->protect & (SEC_FILE | SEC_RESERVE | SEC_COMMIT)) info->Type = MEM_MAPPED;
|
|
|
|
else info->Type = MEM_PRIVATE;
|
|
|
|
for (ptr = base; ptr < base + range_size; ptr += page_size)
|
|
|
|
- if ((get_page_vprot( ptr ) ^ vprot) & ~VPROT_WRITEWATCH) break;
|
|
|
|
+ if ((get_page_vprot( ptr ) ^ vprot) & ~(VPROT_WRITEWATCH|VPROT_WRITTEN)) break;
|
|
|
|
info->RegionSize = ptr - base;
|
|
|
|
}
|
2020-07-03 16:18:38 -07:00
|
|
|
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
|
2020-04-28 04:07:19 -07:00
|
|
|
--
|
2020-07-03 16:18:38 -07:00
|
|
|
2.27.0
|
2020-04-28 04:07:19 -07:00
|
|
|
|