Skip to content

Commit

Permalink
Merge pull request #3786 from lambdageek/dev-42584-take2
Browse files Browse the repository at this point in the history
Check for ReferenceAssemblyAttribute when loading for execution
  • Loading branch information
lambdageek committed Oct 20, 2016
2 parents b313769 + f7bcbec commit 86e44df
Show file tree
Hide file tree
Showing 12 changed files with 261 additions and 69 deletions.
70 changes: 35 additions & 35 deletions mono/metadata/appdomain.c
Expand Up @@ -1958,37 +1958,37 @@ 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);

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;
}

Expand Down Expand Up @@ -2040,7 +2040,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);
Expand All @@ -2049,16 +2049,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;
}
Expand All @@ -2070,25 +2067,28 @@ 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)
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;
}

Expand Down
65 changes: 54 additions & 11 deletions mono/metadata/assembly.c
Expand Up @@ -214,6 +214,9 @@ mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *request
static MonoBoolean
mono_assembly_is_in_gac (const gchar *filanem);

static MonoAssembly*
prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly);

static gchar*
encode_public_tok (const guchar *token, gint32 len)
{
Expand Down Expand Up @@ -1208,6 +1211,7 @@ 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);

}

mono_assemblies_lock ();
Expand Down Expand Up @@ -1826,15 +1830,15 @@ mono_assembly_load_friends (MonoAssembly* ass)


/**
* mono_assembly_get_reference_assembly_attribute:
* mono_assembly_has_reference_assembly_attribute:
* @assembly: a MonoAssembly
* @error: set on error.
*
* Returns TRUE if @assembly has the System.Runtime.CompilerServices.ReferenceAssemblyAttribute set.
* On error returns FALSE and sets @error.
*/
gboolean
mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
{
mono_error_init (error);

Expand All @@ -1843,14 +1847,8 @@ mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoErro
if (!attrs)
return FALSE;
MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
gboolean result = FALSE;
for (int i = 0; i < attrs->num_attrs; ++i) {
MonoCustomAttrEntry *attr = &attrs->attrs [i];
if (attr->ctor && attr->ctor->klass && attr->ctor->klass == ref_asm_class) {
result = TRUE;
break;
}
}
g_assert (ref_asm_class != NULL && ref_asm_class != mono_defaults.object_class && !strcmp(ref_asm_class->name, "ReferenceAssemblyAttribute") );
gboolean result = mono_custom_attrs_has_attr (attrs, ref_asm_class);
mono_custom_attrs_free (attrs);
return result;
}
Expand Down Expand Up @@ -1990,6 +1988,36 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname,
return ass2;
}

mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);

/* We need to check for ReferenceAssmeblyAttribute before we
* mark the assembly as loaded and before we fire the load
* hook. Otherwise mono_domain_fire_assembly_load () in
* appdomain.c will cache a mapping from the assembly name to
* this image and we won't be able to look for a different
* candidate. */

if (!refonly && strcmp (ass->aname.name, "mscorlib") != 0) {
/* Don't check for reference assmebly attribute for
* corlib here because if corlib isn't loaded yet,
* it's too early to set up the
* ReferenceAssemblyAttribute class. We check that
* we're not running with a reference corlib in
* mono_init_internal().
*/
MonoError refasm_error;
if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
mono_assemblies_unlock ();
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);
g_free (ass);
g_free (base_dir);
mono_image_close (image);
*status = MONO_IMAGE_IMAGE_INVALID;
return NULL;
}
mono_error_cleanup (&refasm_error);
}

image->assembly = ass;

loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
Expand Down Expand Up @@ -3193,6 +3221,19 @@ mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *
return corlib;
}

static MonoAssembly*
prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly)
{
MonoError refasm_error;
mono_error_init (&refasm_error);
if (candidate && !refonly && mono_assembly_has_reference_assembly_attribute (candidate, &refasm_error)) {
candidate = NULL;
}
mono_error_cleanup (&refasm_error);
return candidate;
}


MonoAssembly*
mono_assembly_load_full_nosearch (MonoAssemblyName *aname,
const char *basedir,
Expand Down Expand Up @@ -3274,9 +3315,11 @@ mono_assembly_load_full_internal (MonoAssemblyName *aname, MonoAssembly *request
{
MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly);

if (!result)
if (!result) {
/* Try a postload search hook */
result = mono_assembly_invoke_search_hook_internal (aname, requesting, refonly, TRUE);
result = prevent_reference_assembly_from_running (result, refonly);
}
return result;
}

Expand Down
1 change: 1 addition & 0 deletions mono/metadata/class.c
Expand Up @@ -5554,6 +5554,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_type_load_failure (klass, "");
g_assert (parent);
}

klass->parent = parent;
Expand Down
30 changes: 16 additions & 14 deletions mono/metadata/custom-attrs.c
Expand Up @@ -1434,8 +1434,11 @@ mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
{
int i;
for (i = 0; i < ainfo->num_attrs; ++i) {
MonoClass *klass = ainfo->attrs [i].ctor->klass;
if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
MonoCustomAttrEntry *centry = &ainfo->attrs[i];
if (centry->ctor == NULL)
continue;
MonoClass *klass = centry->ctor->klass;
if (klass == attr_klass || mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
return TRUE;
}
return FALSE;
Expand All @@ -1453,26 +1456,25 @@ mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
MonoObject*
mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
{
int i, attr_index;
MonoArray *attrs;
int i;
MonoCustomAttrEntry *centry = NULL;

g_assert (attr_klass != NULL);

mono_error_init (error);

attr_index = -1;
for (i = 0; i < ainfo->num_attrs; ++i) {
MonoClass *klass = ainfo->attrs [i].ctor->klass;
if (mono_class_has_parent (klass, attr_klass)) {
attr_index = i;
centry = &ainfo->attrs[i];
if (centry->ctor == NULL)
continue;
MonoClass *klass = centry->ctor->klass;
if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass))
break;
}
}
if (attr_index == -1)
if (centry == NULL)
return NULL;

attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
if (!mono_error_ok (error))
return NULL;
return mono_array_get (attrs, MonoObject*, attr_index);
return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion mono/metadata/domain-internals.h
Expand Up @@ -697,7 +697,7 @@ void
mono_context_init_checked (MonoDomain *domain, MonoError *error);

gboolean
mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error);
mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error);


#endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */
10 changes: 10 additions & 0 deletions mono/metadata/domain.c
Expand Up @@ -816,6 +816,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_has_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;
}

Expand Down
1 change: 1 addition & 0 deletions mono/metadata/reflection.h
Expand Up @@ -102,6 +102,7 @@ MONO_API MonoCustomAttrInfo* mono_custom_attrs_from_field (MonoClass *klass,
MONO_RT_EXTERNAL_ONLY
MONO_API MonoCustomAttrInfo* mono_custom_attrs_from_param (MonoMethod *method, uint32_t param);
MONO_API mono_bool mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass);
MONO_RT_EXTERNAL_ONLY
MONO_API MonoObject* mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass);
MONO_API void mono_custom_attrs_free (MonoCustomAttrInfo *ainfo);

Expand Down
25 changes: 18 additions & 7 deletions mono/tests/Makefile.am
Expand Up @@ -470,7 +470,8 @@ BASE_TEST_CS_SRC_UNIVERSAL= \
bug-29585.cs \
priority.cs \
abort-cctor.cs \
thread-native-exit.cs
thread-native-exit.cs \
reference-loader.cs

if INSTALL_MOBILE_STATIC
BASE_TEST_CS_SRC= \
Expand Down Expand Up @@ -803,18 +804,22 @@ endif
# but that need to be compiled
PREREQ_IL_SRC=event-il.il module-cctor.il
PREREQ_CS_SRC=
PREREQ_IL_DLL_SRC=event-il.il module-cctor.il
PREREQ_CS_DLL_SRC=
PREREQ_IL_DLL_SRC=
PREREQ_CS_DLL_SRC=TestingReferenceAssembly.cs TestingReferenceReferenceAssembly.cs

PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe)
PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe)
PREREQSI_IL=$(PREREQ_IL_SRC:.il=.exe) \
$(PREREQ_IL_DLL_SRC:.il=.dll)
PREREQSI_CS=$(PREREQ_CS_SRC:.cs=.exe) \
$(PREREQ_CS_DLL_SRC:.cs=.dll)
TESTSI_CS=$(TEST_CS_SRC:.cs=.exe)
TESTSI_IL=$(TEST_IL_SRC:.il=.exe)
TESTBS=$(BENCHSRC:.cs=.exe)
STRESS_TESTS=$(STRESS_TESTS_SRC:.cs=.exe)

PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX))
PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX))
PREREQSI_IL_AOT=$(PREREQ_IL_SRC:.il=.exe$(PLATFORM_AOT_SUFFIX)) \
$(PREREQ_IL_DLL_SRC:.il=.dll$(PLATFORM_AOT_SUFFIX))
PREREQSI_CS_AOT=$(PREREQ_CS_SRC:.cs=.exe$(PLATFORM_AOT_SUFFIX)) \
$(PREREQ_CS_DLL_SRC:.cs=.dll$(PLATFORM_AOT_SUFFIX))

EXTRA_DIST=test-driver test-runner.cs $(TEST_CS_SRC_DIST) $(TEST_IL_SRC) \
$(BENCHSRC) $(STRESS_TESTS_SRC) stress-runner.pl $(PREREQ_IL_SRC) $(PREREQ_CS_SRC)
Expand All @@ -835,6 +840,12 @@ endif
%.exe: %.cs $(TEST_DRIVER_DEPEND)
$(MCS) -r:System.dll -r:System.Xml.dll -r:System.Core.dll -r:TestDriver.dll $(TEST_DRIVER_HARD_KILL_FEATURE) -out:$@ $<

%.dll: %.cs
$(MCS) -r:System.dll -target:library -out:$@ $<

TestingReferenceReferenceAssembly.dll: TestingReferenceReferenceAssembly.cs TestingReferenceAssembly.dll
$(MCS) -r:TestingReferenceAssembly.dll -target:library -out:$@ $<

%.exe$(PLATFORM_AOT_SUFFIX): %.exe
$(RUNTIME) $(AOT_BUILD_FLAGS) $<

Expand Down

0 comments on commit 86e44df

Please sign in to comment.