From 88ef07a501e101d1c082f4d8d5a9efc4de85d7bd Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Thu, 2 Aug 2018 12:23:54 -0400 Subject: [PATCH] [loader] Use appdomain base dir and loadfrom asmctx hooks 1. If an assembly filename is in the GAC, always open the assembly in default context. 2. If an assembly filename is in the appdomain search path (base directory or private bin path) always open the assembly in default context. 3. If an assembly filename is in the base dir of the requesting assembly and the requesting assembly was in LoadFrom context, always open the assembly in LoadFrom context. Fixes https://github.com/mono/mono/issues/9753 and Fixes https://github.com/mono/mono/issues/9542 --- mono/metadata/appdomain.c | 19 +++++++++++++++++++ mono/metadata/assembly.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index a95bde7e36e..576da20cc1f 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -102,6 +102,9 @@ mono_domain_assembly_search (MonoAssemblyName *aname, static void mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data); +static gboolean +mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx); + static void add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *hash); @@ -280,6 +283,7 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT mono_install_assembly_postload_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE)); mono_install_assembly_postload_refonly_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE)); mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL); + mono_install_assembly_asmctx_from_path_hook (mono_domain_asmctx_from_path, NULL); mono_thread_init (start_cb, attach_cb); @@ -1356,6 +1360,21 @@ leave: HANDLE_FUNCTION_RETURN (); } +static gboolean +mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx) +{ + MonoDomain *domain = mono_domain_get (); + char **search_path = NULL; + + for (search_path = domain->search_path; search_path && *search_path; search_path++) { + if (mono_path_filename_in_basedir (fname, *search_path)) { + *out_asmctx = MONO_ASMCTX_DEFAULT; + return TRUE; + } + } + return FALSE; +} + /* * LOCKING: Acquires the domain assemblies lock. */ diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c index 18f169bc22a..87bbec07e2d 100644 --- a/mono/metadata/assembly.c +++ b/mono/metadata/assembly.c @@ -368,6 +368,9 @@ framework_assembly_sn_match (MonoAssemblyName *wanted_name, MonoAssemblyName *ca static const char * mono_asmctx_get_name (const MonoAssemblyContext *asmctx); +static gboolean +assembly_loadfrom_asmctx_from_path (const char *filename, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx); + static gchar* encode_public_tok (const guchar *token, gint32 len) { @@ -997,6 +1000,8 @@ mono_assemblies_init (void) g_hash_table_insert (assembly_remapping_table, (void*)framework_assemblies [i].assembly_name, (void*)&framework_assemblies [i]); #endif + mono_install_assembly_asmctx_from_path_hook (assembly_loadfrom_asmctx_from_path, NULL); + } static void @@ -2133,6 +2138,16 @@ mono_assembly_open_a_lot (const char *filename, MonoImageOpenStatus *status, Mon return mono_assembly_open_predicate (filename, asmctx, NULL, NULL, NULL, status); } +static gboolean +assembly_loadfrom_asmctx_from_path (const char *filename, MonoAssembly *requesting_assembly, + gpointer user_data, MonoAssemblyContextKind *out_asmctx) { + if (requesting_assembly && mono_asmctx_get_kind (&requesting_assembly->context) == MONO_ASMCTX_LOADFROM) { + if (mono_path_filename_in_basedir (filename, requesting_assembly->basedir)) { + *out_asmctx = MONO_ASMCTX_LOADFROM; + return TRUE; + } + } + return FALSE; } MonoAssembly * @@ -2199,6 +2214,21 @@ mono_assembly_open_predicate (const char *filename, MonoAssemblyContextKind asmc g_free (fname); return NULL; } + + if (asmctx != MONO_ASMCTX_REFONLY) { + MonoAssemblyContextKind out_asmctx; + /* If the path belongs to the appdomain base dir or the + * base dir of the requesting assembly, load the + * assembly in the corresponding asmctx. + */ + if (assembly_invoke_asmctx_from_path_hook (fname, requesting_assembly, &out_asmctx)) + asmctx = out_asmctx; + } + } else { + if (asmctx != MONO_ASMCTX_REFONLY) { + /* GAC assemblies always in default context or refonly context. */ + asmctx = MONO_ASMCTX_DEFAULT; + } } if (new_fname && new_fname != fname) { g_free (fname); -- 2.11.4.GIT