From 9e3893cc29dbcfd53d89abc679d0207cf2492999 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 21 Jun 2020 16:56:05 +0200 Subject: [PATCH] ntdll: Use FSCTL_GET_OBJECT_ID to compare file identities. Signed-off-by: Alexandre Julliard --- dlls/ntdll/loader.c | 83 +++++++++++++++++----------------- dlls/ntdll/unix/loader.c | 1 - dlls/ntdll/unix/server.c | 4 +- dlls/ntdll/unix/unix_private.h | 5 +- dlls/ntdll/unixlib.h | 4 +- 5 files changed, 47 insertions(+), 50 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 87a65e4fc11..c90cdcc860b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -37,6 +37,7 @@ #define NONAMELESSSTRUCT #include "windef.h" #include "winnt.h" +#include "winioctl.h" #include "winternl.h" #include "delayloadhandler.h" @@ -122,12 +123,16 @@ static const char * const reason_names[] = static const WCHAR dllW[] = {'.','d','l','l',0}; -/* internal representation of 32bit modules. per process. */ +struct file_id +{ + BYTE ObjectId[16]; +}; + +/* internal representation of loaded modules */ typedef struct _wine_modref { LDR_DATA_TABLE_ENTRY ldr; - dev_t dev; - ino_t ino; + struct file_id id; void *so_handle; int alloc_deps; int nDeps; @@ -554,12 +559,11 @@ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name ) * Find a module from its file id. * The loader_section must be locked while calling this function */ -static WINE_MODREF *find_fileid_module( struct stat *st ) +static WINE_MODREF *find_fileid_module( const struct file_id *id ) { LIST_ENTRY *mark, *entry; - if (cached_modref && cached_modref->dev == st->st_dev && cached_modref->ino == st->st_ino) - return cached_modref; + if (cached_modref && !memcmp( &cached_modref->id, id, sizeof(*id) )) return cached_modref; mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; for (entry = mark->Flink; entry != mark; entry = entry->Flink) @@ -567,7 +571,7 @@ static WINE_MODREF *find_fileid_module( struct stat *st ) LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD( entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); WINE_MODREF *wm = CONTAINING_RECORD( mod, WINE_MODREF, ldr ); - if (wm->dev == st->st_dev && wm->ino == st->st_ino) + if (!memcmp( &wm->id, id, sizeof(*id) )) { cached_modref = wm; return wm; @@ -2303,16 +2307,16 @@ static NTSTATUS get_dll_load_path_search_flags( LPCWSTR module, DWORD flags, WCH * Open a file for a new dll. Helper for find_dll_file. */ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, - void **module, pe_image_info_t *image_info, struct stat *st ) + void **module, pe_image_info_t *image_info, struct file_id *id ) { FILE_BASIC_INFORMATION info; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; LARGE_INTEGER size; + FILE_OBJECTID_BUFFER fid; SIZE_T len = 0; NTSTATUS status; HANDLE handle, mapping; - int fd, needs_close; if ((*pwm = find_fullname_module( nt_name ))) { @@ -2342,11 +2346,10 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, return STATUS_DLL_NOT_FOUND; } - if (!unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )) + if (!NtFsControlFile( handle, 0, NULL, NULL, &io, FSCTL_GET_OBJECT_ID, NULL, 0, &fid, sizeof(fid) )) { - fstat( fd, st ); - if (needs_close) close( fd ); - if ((*pwm = find_fileid_module( st ))) + memcpy( id, fid.ObjectId, sizeof(*id) ); + if ((*pwm = find_fileid_module( id ))) { TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ), (*pwm)->ldr.DllBase, debugstr_w( (*pwm)->ldr.FullDllName.Buffer )); @@ -2390,8 +2393,8 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, * load_native_dll (internal) */ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module, - const pe_image_info_t *image_info, DWORD flags, WINE_MODREF** pwm, - struct stat *st ) + const pe_image_info_t *image_info, const struct file_id *id, + DWORD flags, WINE_MODREF** pwm ) { IMAGE_NT_HEADERS *nt = RtlImageNtHeader( *module ); WINE_MODREF *wm; @@ -2409,8 +2412,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_nam if (!(wm = alloc_module( *module, nt_name, (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) ))) return STATUS_NO_MEMORY; - wm->dev = st->st_dev; - wm->ino = st->st_ino; + wm->id = *id; if (image_info->loader_flags) wm->ldr.Flags |= LDR_COR_IMAGE; if (image_info->image_flags & IMAGE_FLAGS_ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY; @@ -2521,7 +2523,7 @@ static inline char *prepend( char *buffer, const char *str, size_t len ) * open_builtin_file */ static NTSTATUS open_builtin_file( char *name, WINE_MODREF **pwm, void **module, - pe_image_info_t *image_info, struct stat *st, char **so_name ) + pe_image_info_t *image_info, struct file_id *id, char **so_name ) { ANSI_STRING strA; UNICODE_STRING nt_name; @@ -2532,7 +2534,7 @@ static NTSTATUS open_builtin_file( char *name, WINE_MODREF **pwm, void **module, RtlInitString( &strA, name ); if ((status = wine_unix_to_nt_file_name( &strA, &nt_name ))) return status; - status = open_dll_file( &nt_name, pwm, module, image_info, st ); + status = open_dll_file( &nt_name, pwm, module, image_info, id ); RtlFreeUnicodeString( &nt_name ); /* ignore non-builtins */ @@ -2569,9 +2571,8 @@ static NTSTATUS open_builtin_file( char *name, WINE_MODREF **pwm, void **module, /*********************************************************************** * find_builtin_dll */ -static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm, - void **module, pe_image_info_t *image_info, struct stat *st, - char **so_name ) +static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm, void **module, + pe_image_info_t *image_info, struct file_id *id, char **so_name ) { unsigned int i, pos, len, namelen, maxlen = 0; char *ptr, *file; @@ -2608,7 +2609,7 @@ static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm, ptr = prepend( ptr, ptr, namelen ); ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 ); ptr = prepend( ptr, build_dir, strlen(build_dir) ); - status = open_builtin_file( ptr, pwm, module, image_info, st, so_name ); + status = open_builtin_file( ptr, pwm, module, image_info, id, so_name ); if (status != STATUS_DLL_NOT_FOUND) goto done; /* now as a program */ @@ -2619,7 +2620,7 @@ static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm, ptr = prepend( ptr, ptr, namelen ); ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 ); ptr = prepend( ptr, build_dir, strlen(build_dir) ); - status = open_builtin_file( ptr, pwm, module, image_info, st, so_name ); + status = open_builtin_file( ptr, pwm, module, image_info, id, so_name ); if (status != STATUS_DLL_NOT_FOUND) goto done; } @@ -2627,7 +2628,7 @@ static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm, { file[pos + len + 1] = 0; ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) ); - status = open_builtin_file( ptr, pwm, module, image_info, st, so_name ); + status = open_builtin_file( ptr, pwm, module, image_info, id, so_name ); if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE; else if (status != STATUS_DLL_NOT_FOUND) goto done; } @@ -2760,7 +2761,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na NTSTATUS status; void *module = NULL; pe_image_info_t image_info; - struct stat st; + struct file_id id; char *so_name; /* Fix the name in case we have a full path and extension */ @@ -2772,7 +2773,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na if (!module_ptr) module_ptr = &module; - status = find_builtin_dll( name, pwm, module_ptr, &image_info, &st, &so_name ); + status = find_builtin_dll( name, pwm, module_ptr, &image_info, &id, &so_name ); if (status) return status; if (*pwm) @@ -2787,7 +2788,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na if (*module_ptr) { TRACE( "loading %s from PE builtin %s\n", debugstr_w(name), debugstr_us(nt_name) ); - return load_native_dll( load_path, nt_name, module_ptr, &image_info, flags, pwm, &st ); + return load_native_dll( load_path, nt_name, module_ptr, &image_info, &id, flags, pwm ); } status = load_so_dll( load_path, nt_name, so_name, flags, pwm ); @@ -2904,7 +2905,7 @@ done: */ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, pe_image_info_t *image_info, - struct stat *st ) + struct file_id *id ) { WCHAR *name; BOOL found_image = FALSE; @@ -2931,7 +2932,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING * nt_name->Buffer = NULL; if ((status = RtlDosPathNameToNtPathName_U_WithStatus( name, nt_name, NULL, NULL ))) goto done; - status = open_dll_file( nt_name, pwm, module, image_info, st ); + status = open_dll_file( nt_name, pwm, module, image_info, id ); if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE; else if (status != STATUS_DLL_NOT_FOUND) goto done; RtlFreeUnicodeString( nt_name ); @@ -2960,7 +2961,7 @@ done: */ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext, UNICODE_STRING *nt_name, WINE_MODREF **pwm, - void **module, pe_image_info_t *image_info, struct stat *st ) + void **module, pe_image_info_t *image_info, struct file_id *id ) { WCHAR *ext, *dllname; NTSTATUS status; @@ -3011,9 +3012,9 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con } if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) - status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, st ); + status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, id ); else if (!(status = RtlDosPathNameToNtPathName_U_WithStatus( libname, nt_name, NULL, NULL ))) - status = open_dll_file( nt_name, pwm, module, image_info, st ); + status = open_dll_file( nt_name, pwm, module, image_info, id ); if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) status = STATUS_INVALID_IMAGE_FORMAT; @@ -3036,14 +3037,14 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC enum loadorder loadorder; WINE_MODREF *main_exe; UNICODE_STRING nt_name; - struct stat st; + struct file_id id; void *module; pe_image_info_t image_info; NTSTATUS nts; TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) ); - nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &module, &image_info, &st ); + nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &module, &image_info, &id ); if (*pwm) /* found already loaded module */ { @@ -3090,7 +3091,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC case LO_DEFAULT: nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm ); if (nts == STATUS_DLL_NOT_FOUND) - nts = load_native_dll( load_path, &nt_name, &module, &image_info, flags, pwm, &st ); + nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm ); break; default: nts = STATUS_DLL_NOT_FOUND; @@ -3105,7 +3106,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC { case LO_NATIVE: case LO_NATIVE_BUILTIN: - nts = load_native_dll( load_path, &nt_name, &module, &image_info, flags, pwm, &st ); + nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm ); break; case LO_BUILTIN: nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm ); @@ -3121,10 +3122,10 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC LdrUnloadDll( (*pwm)->ldr.DllBase ); nts = STATUS_DLL_NOT_FOUND; /* map the dll again if it was unmapped */ - if (!module && open_dll_file( &nt_name, pwm, &module, &image_info, &st )) break; + if (!module && open_dll_file( &nt_name, pwm, &module, &image_info, &id )) break; } if (nts == STATUS_DLL_NOT_FOUND) - nts = load_native_dll( load_path, &nt_name, &module, &image_info, flags, pwm, &st ); + nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm ); break; default: nts = STATUS_DLL_NOT_FOUND; @@ -3203,13 +3204,13 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S WINE_MODREF *wm; void *module; pe_image_info_t image_info; - struct stat st; + struct file_id id; RtlEnterCriticalSection( &loader_section ); if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; - status = find_dll_file( load_path, name->Buffer, dllW, &nt_name, &wm, &module, &image_info, &st ); + status = find_dll_file( load_path, name->Buffer, dllW, &nt_name, &wm, &module, &image_info, &id ); if (wm) *base = wm->ldr.DllBase; else diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 3fee3bf5154..51ff7f950e8 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1024,7 +1024,6 @@ static struct unix_funcs unix_funcs = exec_process, wine_server_call, server_send_fd, - server_get_unix_fd, server_fd_to_handle, server_handle_to_fd, server_release_fd, diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 1f07f5288eb..d81fb3b89a2 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -999,8 +999,8 @@ static int remove_fd_from_cache( HANDLE handle ) * * The returned unix_fd should be closed iff needs_close is non-zero. */ -int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, - int *needs_close, enum server_fd_type *type, unsigned int *options ) +int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, + int *needs_close, enum server_fd_type *type, unsigned int *options ) { sigset_t sigset; obj_handle_t fd_handle; diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 9904ef7bfd5..e353a17a7de 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -101,9 +101,6 @@ extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN; extern void CDECL virtual_set_large_address_space(void) DECLSPEC_HIDDEN; extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN; -extern int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, - int *needs_close, enum server_fd_type *type, - unsigned int *options ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd, @@ -155,6 +152,8 @@ extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ) DECLSPEC_HIDDEN; +extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, + int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN; extern void server_init_process(void) DECLSPEC_HIDDEN; extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN; extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 2393ae0ca47..311d99f482d 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 56 +#define NTDLL_UNIXLIB_VERSION 57 struct unix_funcs { @@ -310,8 +310,6 @@ struct unix_funcs /* server functions */ unsigned int (CDECL *server_call)( void *req_ptr ); void (CDECL *server_send_fd)( int fd ); - int (CDECL *server_get_unix_fd)( HANDLE handle, unsigned int wanted_access, int *unix_fd, - int *needs_close, enum server_fd_type *type, unsigned int *options ); NTSTATUS (CDECL *server_fd_to_handle)( int fd, unsigned int access, unsigned int attributes, HANDLE *handle ); NTSTATUS (CDECL *server_handle_to_fd)( HANDLE handle, unsigned int access, int *unix_fd,