[runtime] Check for ReferenceAssemblyAttribute when loading for execution.
authorAleksey Kliger <aleksey@xamarin.com>
Fri, 26 Aug 2016 18:10:25 +0000 (14:10 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Thu, 1 Sep 2016 21:53:26 +0000 (17:53 -0400)
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/class.c
mono/metadata/domain.c

index 7a214c3f541abe19c32d9c5a12f354893db86aa0..bc214cc92e2f598e3a6d5f62e5b8d1e88448dadb 100644 (file)
@@ -1934,6 +1934,20 @@ mono_domain_assembly_search (MonoAssemblyName *aname,
        return NULL;
 }
 
+static gboolean
+prevent_running_reference_assembly (MonoAssembly *ass, MonoError *error)
+{
+       mono_error_init (error);
+       gboolean refasm = mono_assembly_get_reference_assembly_attribute (ass, error);
+       if (!is_ok (error))
+               return TRUE;
+       if (refasm) {
+               mono_error_set_bad_image (error, ass->image, "Could not load file or assembly or one of its dependencies. Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context.\n");
+               return TRUE;
+       }
+       return FALSE;
+}
+
 MonoReflectionAssembly *
 ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean refOnly)
 {
@@ -1942,37 +1956,40 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoString *fname, MonoBoolean re
        MonoDomain *domain = mono_domain_get ();
        char *name, *filename;
        MonoImageOpenStatus status = MONO_IMAGE_OK;
-       MonoAssembly *ass;
+       MonoAssembly *ass = NULL;
+
+       name = NULL;
+       result = NULL;
+
+       mono_error_init (&error);
 
        if (fname == NULL) {
-               MonoException *exc = mono_get_exception_argument_null ("assemblyFile");
-               mono_set_pending_exception (exc);
-               return NULL;
+               mono_error_set_argument_null (&error, "assemblyFile", "");
+               goto leave;
        }
                
        name = filename = mono_string_to_utf8_checked (fname, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       if (!is_ok (&error))
+               goto leave;
        
        ass = mono_assembly_open_full (filename, &status, refOnly);
        
        if (!ass) {
-               MonoException *exc;
-
                if (status == MONO_IMAGE_IMAGE_INVALID)
-                       exc = mono_get_exception_bad_image_format2 (NULL, fname);
+                       mono_error_set_bad_image_name (&error, name, "");
                else
-                       exc = mono_get_exception_file_not_found2 (NULL, fname);
-               g_free (name);
-               mono_set_pending_exception (exc);
-               return NULL;
+                       mono_error_set_exception_instance (&error, mono_get_exception_file_not_found2 (NULL, fname));
+               goto leave;
        }
 
-       g_free (name);
+       if (!refOnly && prevent_running_reference_assembly (ass, &error))
+               goto leave;
 
        result = mono_assembly_get_object_checked (domain, ass, &error);
-       if (!result)
-               mono_error_set_pending_exception (&error);
+
+leave:
+       mono_error_set_pending_exception (&error);
+       g_free (name);
        return result;
 }
 
@@ -2007,6 +2024,11 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad,
                return NULL; 
        }
 
+       if (!refonly && prevent_running_reference_assembly (ass, &error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
        refass = mono_assembly_get_object_checked (domain, ass, &error);
        if (!refass)
                mono_error_set_pending_exception (&error);
@@ -2024,7 +2046,7 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoString *assRef,
        MonoAssembly *ass;
        MonoAssemblyName aname;
        MonoReflectionAssembly *refass = NULL;
-       gchar *name;
+       gchar *name = NULL;
        gboolean parsed;
 
        g_assert (assRef);
@@ -2033,16 +2055,13 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoString *assRef,
        if (mono_error_set_pending_exception (&error))
                return NULL;
        parsed = mono_assembly_name_parse (name, &aname);
-       g_free (name);
 
        if (!parsed) {
                /* This is a parse error... */
                if (!refOnly) {
                        refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error);
-                       if (!mono_error_ok (&error)) {
-                               mono_error_set_pending_exception (&error);
-                               return NULL;
-                       }
+                       if (!is_ok (&error))
+                               goto leave;
                }
                return refass;
        }
@@ -2054,25 +2073,31 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoString *assRef,
                /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
                if (!refOnly) {
                        refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error);
-                       if (!mono_error_ok (&error)) {
-                               mono_error_set_pending_exception (&error);
-                               return NULL;
-                       }
+                       if (!is_ok (&error))
+                               goto leave;
                }
                else
                        refass = NULL;
-               if (!refass) {
-                       return NULL;
-               }
+               if (!refass)
+                       goto leave;
+               ass = refass->assembly;
        }
 
-       if (refass == NULL)
+       if (!refOnly && prevent_running_reference_assembly (ass, &error))
+               goto leave;
+
+       g_assert (ass);
+       if (refass == NULL) {
                refass = mono_assembly_get_object_checked (domain, ass, &error);
+               if (!is_ok (&error))
+                       goto leave;
+       }
 
-       if (refass == NULL)
-               mono_error_set_pending_exception (&error);
-       else
-               MONO_OBJECT_SETREF (refass, evidence, evidence);
+       MONO_OBJECT_SETREF (refass, evidence, evidence);
+
+leave:
+       g_free (name);
+       mono_error_set_pending_exception (&error);
        return refass;
 }
 
index d018deb29fef95bdf8c2d55f45e566a213f6c1b3..0744389c400bf4539c0d88f3e530df2a95436b6e 100644 (file)
@@ -1191,6 +1191,23 @@ mono_assembly_load_reference (MonoImage *image, int index)
                                   aname.major, aname.minor, aname.build, aname.revision,
                                   strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg);
                g_free (extra_msg);
+
+       } else if (!image->assembly->ref_only) {
+               MonoError error;
+               if (mono_assembly_get_reference_assembly_attribute (reference, &error)) {
+                       mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following reference assembly assembly referenced from %s was not loaded.  Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context:\n"
+                                   "     Assembly:   %s    (assemblyref_index=%d)\n"
+                                   "     Version:    %d.%d.%d.%d\n"
+                                   "     Public Key: %s\n",
+                                   image->name, aname.name, index,
+                                   aname.major, aname.minor, aname.build, aname.revision,
+                                   strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token);
+                       reference = NULL; /* don't load reference assemblies for execution */
+               }
+               if (!is_ok (&error)) {
+                       reference = NULL;
+                       mono_error_cleanup (&error);
+               }
        }
 
        mono_assemblies_lock ();
index a419af381492313e250c7887c0217c26ea071269..7ec6ee9186e119598af72817dfe7df1bfd7e203f 100644 (file)
@@ -5591,6 +5591,7 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
                        /* set the parent to something useful and safe, but mark the type as broken */
                        parent = mono_defaults.object_class;
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       g_assert (parent);
                }
 
                klass->parent = parent;
index 54e4115771d8a8d52a48e752fec201f173d2aefd..6cfd0dbbb9ea31c1a6ff8ba24d0db0e423381f01 100644 (file)
@@ -808,6 +808,16 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
 
        mono_profiler_appdomain_name (domain, domain->friendly_name);
 
+       /* Have to do this quite late so that we at least have System.Object */
+       MonoError custom_attr_error;
+       if (mono_assembly_get_reference_assembly_attribute (ass, &custom_attr_error)) {
+               char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
+               g_print ("Could not load file or assembly %s. Reference assemblies should not be loaded for execution.  They can only be loaded in the Reflection-only loader context.", corlib_file);
+               g_free (corlib_file);
+               exit (1);
+       }
+       mono_error_assert_ok (&custom_attr_error);
+
        return domain;
 }