Skip to content

Commit

Permalink
kernelbase: Send cross process notifications in WriteProcessMemory on…
Browse files Browse the repository at this point in the history
… ARM64.

(cherry picked from commit 2c7f418)

CW-Bug-Id: #23951
  • Loading branch information
julliard authored and Paul Gofman committed Jun 21, 2024
1 parent c8fea58 commit 069b313
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 7 deletions.
77 changes: 73 additions & 4 deletions dlls/kernelbase/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,53 @@ WINE_DECLARE_DEBUG_CHANNEL(virtual);
WINE_DECLARE_DEBUG_CHANNEL(globalmem);



static CROSS_PROCESS_WORK_LIST *open_cross_process_connection( HANDLE process )
{
#ifdef __aarch64__
CROSS_PROCESS_WORK_LIST *list;
HANDLE section;

RtlOpenCrossProcessEmulatorWorkConnection( process, &section, (void **)&list );
if (section) NtClose( section );
return list;
#else
return NULL;
#endif
}

static void close_cross_process_connection( CROSS_PROCESS_WORK_LIST *list )
{
if (list) NtUnmapViewOfSection( GetCurrentProcess(), list );
}

static void send_cross_process_notification( CROSS_PROCESS_WORK_LIST *list, UINT id,
const void *addr, SIZE_T size, int nb_args, ... )
{
#ifdef __aarch64__
CROSS_PROCESS_WORK_ENTRY *entry;
void *unused;
va_list args;
int i;

if (!list) return;
if ((entry = RtlWow64PopCrossProcessWorkFromFreeList( &list->free_list )))
{
entry->id = id;
entry->addr = (ULONG_PTR)addr;
entry->size = size;
if (nb_args)
{
va_start( args, nb_args );
for (i = 0; i < nb_args; i++) entry->args[i] = va_arg( args, int );
va_end( args );
}
RtlWow64PushCrossProcessWorkOntoWorkList( &list->work_list, entry, &unused );
}
#endif
}


/***********************************************************************
* Virtual memory functions
***********************************************************************/
Expand Down Expand Up @@ -540,13 +587,18 @@ BOOL WINAPI DECLSPEC_HOTPATCH VirtualUnlock( void *addr, SIZE_T size )
BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, const void *buffer,
SIZE_T size, SIZE_T *bytes_written )
{
CROSS_PROCESS_WORK_LIST *list = open_cross_process_connection( process );
DWORD old_prot, prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | PAGE_EXECUTE_WRITECOPY;
MEMORY_BASIC_INFORMATION info;
void *base_addr;
SIZE_T region_size;
NTSTATUS status;
NTSTATUS status, status2;

if (!VirtualQueryEx( process, addr, &info, sizeof(info) )) return FALSE;
if (!VirtualQueryEx( process, addr, &info, sizeof(info) ))
{
close_cross_process_connection( list );
return FALSE;
}

switch (info.Protect)
{
Expand All @@ -556,6 +608,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
case PAGE_EXECUTE_WRITECOPY:
/* already writable */
if ((status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ))) break;
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
NtFlushInstructionCache( process, addr, size );
break;

Expand All @@ -565,12 +618,27 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
base_addr = ROUND_ADDR( addr );
region_size = ROUND_SIZE( addr, size );
region_size = min( region_size, (char *)info.BaseAddress + info.RegionSize - (char *)base_addr );

send_cross_process_notification( list, CrossProcessPreVirtualProtect,
base_addr, region_size, 1, prot );
status = NtProtectVirtualMemory( process, &base_addr, &region_size, prot, &old_prot );
send_cross_process_notification( list, CrossProcessPostVirtualProtect,
base_addr, region_size, 2, prot, status );
if (status) break;

status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written );
if (!status) NtFlushInstructionCache( process, addr, size );
if (!status)
{
send_cross_process_notification( list, CrossProcessFlushCache, addr, size, 0 );
NtFlushInstructionCache( process, addr, size );
}

prot = PAGE_TARGETS_NO_UPDATE | PAGE_ENCLAVE_NO_CHANGE | old_prot;
NtProtectVirtualMemory( process, &base_addr, &region_size, prot, &old_prot );
send_cross_process_notification( list, CrossProcessPreVirtualProtect,
base_addr, region_size, 1, prot );
status2 = NtProtectVirtualMemory( process, &base_addr, &region_size, prot, &old_prot );
send_cross_process_notification( list, CrossProcessPostVirtualProtect,
base_addr, region_size, 2, prot, status2 );
break;

default:
Expand All @@ -579,6 +647,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
break;
}

close_cross_process_connection( list );
return set_ntstatus( status );
}

Expand Down
3 changes: 0 additions & 3 deletions dlls/ntdll/tests/wow64.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr )

WriteProcessMemory( process, (char *)addr + 0x1ffe, data, sizeof(data), &size );
entry = pop_from_work_list( &list->work_list );
todo_wine_if (current_machine == IMAGE_FILE_MACHINE_ARM64)
{
entry = expect_cross_work_entry( list, entry, CrossProcessPreVirtualProtect,
(char *)addr + 0x1000, 0x2000, 0x60000000 | PAGE_EXECUTE_WRITECOPY,
(current_machine != IMAGE_FILE_MACHINE_ARM64) ? 0 : 0xcccccccc,
Expand All @@ -582,7 +580,6 @@ static void test_cross_process_notifications( HANDLE process, void *ptr )
entry = expect_cross_work_entry( list, entry, CrossProcessPostVirtualProtect,
(char *)addr + 0x1000, 0x2000,
0x60000000 | PAGE_EXECUTE_READ, 0, 0xcccccccc, 0xcccccccc );
}
ok( !entry, "not at end of list\n" );

status = NtUnmapViewOfSection( process, addr );
Expand Down

0 comments on commit 069b313

Please sign in to comment.