1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-01 07:14:31 +00:00

kernelbase: Send cross process notifications in WriteProcessMemory on ARM64.

This commit is contained in:
Alexandre Julliard 2024-06-18 12:48:19 +02:00
parent 6ea77ec086
commit 2c7f4181bc
2 changed files with 73 additions and 7 deletions

View File

@ -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
***********************************************************************/
@ -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)
{
@ -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;
@ -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:
@ -579,6 +647,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteProcessMemory( HANDLE process, void *addr, co
break;
}
close_cross_process_connection( list );
return set_ntstatus( status );
}

View File

@ -729,8 +729,6 @@ static void test_cross_process_notifications( HANDLE process, ULONG_PTR section,
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,
@ -748,7 +746,6 @@ static void test_cross_process_notifications( HANDLE process, ULONG_PTR section,
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 );