Module: wine Branch: master Commit: e4c9ec075b788148951c18f34225091969c5a957 URL: https://gitlab.winehq.org/wine/wine/-/commit/e4c9ec075b788148951c18f34225091...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Nov 15 13:09:07 2023 +0100
ntdll: Set function pointers in the ARM64EC metadata on dll load.
---
dlls/ntdll/loader.c | 96 +++++++++++++++++++++++++++++++++++++++---------- dlls/ntdll/ntdll_misc.h | 13 +++++++ 2 files changed, 91 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 93edc237405..89756c57433 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -241,6 +241,52 @@ static void module_push_unload_trace( const WINE_MODREF *wm ) unload_trace_ptr = unload_traces; }
+#ifdef __arm64ec__ + +static void update_hybrid_metadata( void *module, IMAGE_NT_HEADERS *nt, + const IMAGE_ARM64EC_METADATA *metadata ) +{ + DWORD i, protect_old; + const IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION( nt ); + + if (metadata->Version != 1) + { + ERR( "unknown version %lu\n", metadata->Version ); + return; + } + + /* assume that all pointers are in the same section */ + + for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) + { + if ((sec->VirtualAddress <= metadata->__os_arm64x_dispatch_call) && + (sec->VirtualAddress + sec->Misc.VirtualSize > metadata->__os_arm64x_dispatch_call)) + { + void *base = get_rva( module, sec->VirtualAddress ); + SIZE_T size = sec->Misc.VirtualSize; + + NtProtectVirtualMemory( NtCurrentProcess(), &base, &size, PAGE_READWRITE, &protect_old ); + +#define SET_FUNC(func,val) *(void **)get_rva( module, metadata->func ) = val + SET_FUNC( __os_arm64x_dispatch_call, __os_arm64x_check_call ); + SET_FUNC( __os_arm64x_dispatch_call_no_redirect, __os_arm64x_dispatch_call_no_redirect ); + SET_FUNC( __os_arm64x_dispatch_fptr, __os_arm64x_dispatch_fptr ); + SET_FUNC( __os_arm64x_dispatch_icall, __os_arm64x_check_icall ); + SET_FUNC( __os_arm64x_dispatch_icall_cfg, __os_arm64x_check_icall_cfg ); + SET_FUNC( __os_arm64x_dispatch_ret, __os_arm64x_dispatch_ret ); + SET_FUNC( GetX64InformationFunctionPointer, __os_arm64x_get_x64_information ); + SET_FUNC( SetX64InformationFunctionPointer, __os_arm64x_set_x64_information ); +#undef SET_FUNC + + NtProtectVirtualMemory( NtCurrentProcess(), &base, &size, protect_old, &protect_old ); + return; + } + } + ERR( "module %p no section found for %lx\n", module, metadata->__os_arm64x_dispatch_call ); +} + +#endif + /********************************************************************* * RtlGetUnloadEventTrace [NTDLL.@] */ @@ -1983,26 +2029,10 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, * Create a random security cookie for buffer overflow protection. Make * sure it does not accidentally match the default cookie value. */ -static void set_security_cookie( void *module, SIZE_T len ) +static void set_security_cookie( ULONG_PTR *cookie ) { static ULONG seed; - IMAGE_LOAD_CONFIG_DIRECTORY *loadcfg; - ULONG loadcfg_size; - ULONG_PTR *cookie; - - loadcfg = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &loadcfg_size ); - if (!loadcfg) return; - if (loadcfg_size < offsetof(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie) + sizeof(loadcfg->SecurityCookie)) return; - if (!loadcfg->SecurityCookie) return; - if (loadcfg->SecurityCookie < (ULONG_PTR)module || - loadcfg->SecurityCookie > (ULONG_PTR)module + len - sizeof(ULONG_PTR)) - { - WARN( "security cookie %p outside of image %p-%p\n", - (void *)loadcfg->SecurityCookie, module, (char *)module + len ); - return; - }
- cookie = (ULONG_PTR *)loadcfg->SecurityCookie; TRACE( "initializing security cookie %p\n", cookie );
if (!seed) seed = NtGetTickCount() ^ GetCurrentProcessId(); @@ -2025,6 +2055,36 @@ static void set_security_cookie( void *module, SIZE_T len ) } }
+ +/*********************************************************************** + * update_load_config + */ +static void update_load_config( void *module ) +{ + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module ); + IMAGE_LOAD_CONFIG_DIRECTORY *cfg; + ULONG size; + + cfg = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size ); + if (!cfg) return; + size = min( size, cfg->Size ); + if (size > offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie ) && + cfg->SecurityCookie > (ULONG_PTR)module && + cfg->SecurityCookie < (ULONG_PTR)module + nt->OptionalHeader.SizeOfImage) + { + set_security_cookie( (ULONG_PTR *)cfg->SecurityCookie ); + } +#ifdef __arm64ec__ + if (size > offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, CHPEMetadataPointer ) && + cfg->CHPEMetadataPointer > (ULONG_PTR)module && + cfg->CHPEMetadataPointer < (ULONG_PTR)module + nt->OptionalHeader.SizeOfImage) + { + update_hybrid_metadata( module, nt, (void *)cfg->CHPEMetadataPointer ); + } +#endif +} + + static NTSTATUS perform_relocations( void *module, IMAGE_NT_HEADERS *nt, SIZE_T len ) { char *base; @@ -2135,7 +2195,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, if (image_info->ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY; wm->system = system;
- set_security_cookie( *module, map_size ); + update_load_config( *module );
/* fixup imports */
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 8d489afda7f..d24bd0c887a 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -131,4 +131,17 @@ static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) extern TEB_FLS_DATA *fls_alloc_data(void) DECLSPEC_HIDDEN; extern void heap_thread_detach(void) DECLSPEC_HIDDEN;
+#ifdef __arm64ec__ + +extern void *__os_arm64x_check_call; +extern void *__os_arm64x_check_icall; +extern void *__os_arm64x_check_icall_cfg; +extern void *__os_arm64x_dispatch_call_no_redirect; +extern void *__os_arm64x_dispatch_fptr; +extern void *__os_arm64x_dispatch_ret; +extern void *__os_arm64x_get_x64_information; +extern void *__os_arm64x_set_x64_information; + +#endif + #endif