/* * Ensure that the restrictions for partially trusted code are satisfied. * * @domain The current application domain * @caller The method calling * @callee The called method * return value: TRUE if a security violation is detected, FALSE otherwise. * * If callee's assembly is strongnamed and doesn't have an * [AllowPartiallyTrustedCallers] attribute then we must enforce a LinkDemand * for FullTrust on all public/protected methods on public class. * * Note: APTC is only effective on stongnamed assemblies. */ static gboolean mono_declsec_linkdemand_aptc (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee) { MonoSecurityManager* secman = NULL; MonoAssembly *assembly; guint32 size = 0; InterlockedIncrement (&mono_jit_stats.cas_linkdemand_aptc); /* A - Applicable only if we're calling into *another* assembly */ if (caller->klass->image == callee->klass->image) return FALSE; /* B - Applicable if we're calling a public/protected method from a public class */ if (!(callee->klass->flags & TYPE_ATTRIBUTE_PUBLIC) || !(callee->flags & FIELD_ATTRIBUTE_PUBLIC)) return FALSE; /* C - Applicable if the callee's assembly is strongnamed */ if ((mono_image_get_public_key (callee->klass->image, &size) == NULL) || (size < MONO_ECMA_KEY_LENGTH)) return FALSE; /* D - the callee's assembly must have [AllowPartiallyTrustedCallers] */ assembly = mono_image_get_assembly (callee->klass->image); if (!MONO_SECMAN_FLAG_INIT (assembly->aptc)) { MonoCustomAttrInfo* cinfo = mono_custom_attrs_from_assembly (assembly); gboolean result = FALSE; secman = mono_security_manager_get_methods (); if (secman && cinfo) { /* look for AllowPartiallyTrustedCallersAttribute */ result = mono_custom_attrs_has_attr (cinfo, secman->allowpartiallytrustedcallers); } if (cinfo) mono_custom_attrs_free (cinfo); MONO_SECMAN_FLAG_SET_VALUE (assembly->aptc, result); } if (MONO_SECMAN_FLAG_GET_VALUE (assembly->aptc)) return FALSE; /* E - the caller's assembly must have full trust permissions */ assembly = mono_image_get_assembly (caller->klass->image); if (mono_declsec_is_assembly_fulltrust (domain, assembly)) return FALSE; /* g_warning ("FAILURE *** JIT LinkDemand APTC check *** %s.%s calls into %s.%s", caller->klass->name, caller->name, callee->klass->name, callee->name); */ return TRUE; /* i.e. throw new SecurityException(); */ }
static MonoObject * mono_jit_exec_virt (MonoAssembly *assembly, char *mtd_name, MonoArray *v_args) { MonoImage *image = mono_assembly_get_image (assembly); MonoMethod *method; MonoClass *class; MonoMethodDesc *desc; MonoObject *exc = NULL, *ret; class = mono_class_from_name (image, "", "VInvoke"); desc = mono_method_desc_new (mtd_name, 1); method = mono_method_desc_search_in_image (desc, image); mono_assembly_set_main ( mono_image_get_assembly ( mono_class_get_image ( mono_method_get_class (method)))); /*mono_start_method = mono_marshal_get_runtime_invoke (method);*/ ret = virt_mono_runtime_exec_main (method, v_args, &exc); if (exc) virt_mono_throw_unhandled_exception (exc); return ret; }
/* * Ensure that the restrictions for calling internal calls are satisfied. * * @domain The current application domain * @caller The method calling * @icall The internal call method * return value: TRUE if a security violation is detected, FALSE otherwise. * * We can't trust the icall flags/iflags as it comes from the assembly * that we may want to restrict and we do not have the public/restricted * information about icalls in the runtime. Actually it is not so bad * as the CLR 2.0 doesn't enforce that restriction anymore. * * So we'll limit the icalls to originate from ECMA signed assemblies * (as this is required for partial trust scenarios) - or - assemblies that * have FullTrust. */ static gboolean mono_declsec_linkdemand_icall (MonoDomain *domain, MonoMethod *caller, MonoMethod *icall) { MonoAssembly *assembly; InterlockedIncrement (&mono_jit_stats.cas_linkdemand_icall); /* check if the _icall_ is defined inside an ECMA signed assembly */ assembly = mono_image_get_assembly (icall->klass->image); if (!MONO_SECMAN_FLAG_INIT (assembly->ecma)) { guint32 size = 0; const char *pk = mono_image_get_public_key (icall->klass->image, &size); MONO_SECMAN_FLAG_SET_VALUE (assembly->ecma, mono_is_ecma_key (pk, size)); } if (MONO_SECMAN_FLAG_GET_VALUE (assembly->ecma)) return FALSE; /* else check if the _calling_ assembly is running at FullTrust */ assembly = mono_image_get_assembly (caller->klass->image); return !mono_declsec_is_assembly_fulltrust (domain, assembly); }
void MonoAssembly::loadFromImage(MonoImage* image) { ::MonoAssembly* monoAssembly = mono_image_get_assembly(image); if(monoAssembly == nullptr) { BS_EXCEPT(InvalidParametersException, "Cannot get assembly from image."); } mMonoAssembly = monoAssembly; mMonoImage = image; mIsLoaded = true; mIsDependency = true; }
Error GDMonoAssembly::wrapper_for_image(MonoImage *p_image) { ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE); assembly = mono_image_get_assembly(p_image); ERR_FAIL_NULL_V(assembly, FAILED); image = p_image; mono_image_addref(image); loaded = true; return OK; }
/* * Context propagation is required when: * (a) the security manager is active (1.x and later) * (b) other contexts needs to be propagated (2.x and later) * * returns NULL if no context propagation is required, else the returns the * MonoMethod to call to Capture the ExecutionContext. */ MonoMethod* mono_get_context_capture_method (void) { static MonoMethod *method = NULL; if (mono_image_get_assembly (mono_defaults.corlib)->aname.major < 2) return NULL; /* older corlib revisions won't have the class (nor the method) */ MonoClass *execution_context = mono_class_try_get_execution_context_class (); if (execution_context && !method) { mono_class_init (execution_context); method = mono_class_get_method_from_name (execution_context, "Capture", 0); } return method; }
/* * Context propagation is required when: * (a) the security manager is active (1.x and later) * (b) other contexts needs to be propagated (2.x and later) * * returns NULL if no context propagation is required, else the returns the * MonoMethod to call to Capture the ExecutionContext. */ MonoMethod* mono_get_context_capture_method (void) { static MonoMethod *method = NULL; if (mono_image_get_assembly (mono_defaults.corlib)->aname.major < 2) return NULL; /* older corlib revisions won't have the class (nor the method) */ MonoClass *execution_context = mono_class_try_get_execution_context_class (); if (execution_context && !method) { ERROR_DECL (error); mono_class_init_internal (execution_context); method = mono_class_get_method_from_name_checked (execution_context, "Capture", 0, 0, error); mono_error_assert_ok (error); } return method; }
/* * Ensure that the restrictions for calling native code are satisfied. * * @domain The current application domain * @caller The method calling * @native The native method called * return value: TRUE if a security violation is detected, FALSE otherwise. * * Executing Platform Invokes (P/Invoke) is a is a restricted operation. * The security policy must allow (SecurityPermissionFlag.UnmanagedCode) * an assembly to do this. * * This LinkDemand case is special because it only needs to call managed * code once per assembly. Further calls on this assembly will use a cached * flag for better performance. This is not done before the first call (e.g. * when loading the assembly) because that would break the lazy policy * evaluation that Mono use (another time saving optimization). * * Note: P/Invoke checks are ALWAYS (1) done at JIT time (as a LinkDemand). * They are also checked at runtime, using a Demand (stack walk), unless the * method or it's class has a [SuppressUnmanagedCodeSecurity] attribute. * * (1) well as long as the security manager is active (i.e. --security) */ static gboolean mono_declsec_linkdemand_pinvoke (MonoDomain *domain, MonoMethod *caller, MonoMethod *native) { MonoAssembly *assembly = mono_image_get_assembly (caller->klass->image); InterlockedIncrement (&mono_jit_stats.cas_linkdemand_pinvoke); /* Check for P/Invoke flag for the assembly */ if (!MONO_SECMAN_FLAG_INIT (assembly->unmanaged)) { /* Check if we know (and have) or FullTrust status */ if (MONO_SECMAN_FLAG_INIT (assembly->fulltrust) && MONO_SECMAN_FLAG_GET_VALUE (assembly->fulltrust)) { /* FullTrust includes UnmanagedCode permission */ MONO_SECMAN_FLAG_SET_VALUE (assembly->unmanaged, TRUE); return FALSE; } else { MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (domain, assembly); MonoSecurityManager* secman = mono_security_manager_get_methods (); if (secman && refass) { MonoObject *res; gpointer args [1]; args [0] = refass; res = mono_runtime_invoke (secman->linkdemandunmanaged, NULL, args, NULL); if (*(MonoBoolean *) mono_object_unbox(res)) { MONO_SECMAN_FLAG_SET_VALUE (assembly->unmanaged, TRUE); return FALSE; } } } MONO_SECMAN_FLAG_SET_VALUE (assembly->unmanaged, FALSE); } if (MONO_SECMAN_FLAG_GET_VALUE (assembly->unmanaged)) return FALSE; /* g_warning ("FAILURE *** JIT LinkDemand P/Invoke check *** %s.%s calls into %s.%s", caller->klass->name, caller->name, native->klass->name, native->name); */ return TRUE; /* i.e. throw new SecurityException(); */ }
/* * Execute any LinkDemand, NonCasLinkDemand, LinkDemandChoice declarative * security attribute present on the called method or it's class. * * @domain The current application domain * @caller The method calling * @callee The called method. * return value: TRUE if a security violation is detection, FALSE otherwise. * * Note: The execution is done in managed code in SecurityManager.LinkDemand */ static gboolean mono_declsec_linkdemand_standard (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee) { MonoDeclSecurityActions linkclass, linkmethod; InterlockedIncrement (&mono_jit_stats.cas_linkdemand); if (mono_declsec_get_linkdemands (callee, &linkclass, &linkmethod)) { MonoAssembly *assembly = mono_image_get_assembly (caller->klass->image); MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (domain, assembly); MonoSecurityManager *secman = mono_security_manager_get_methods (); MonoObject *res; gpointer args [3]; args [0] = refass; args [1] = &linkclass; args [2] = &linkmethod; res = mono_runtime_invoke (secman->linkdemand, NULL, args, NULL); return !(*(MonoBoolean *) mono_object_unbox(res)); } return FALSE; }
static MonoObject * virt_mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc) { MonoDomain *domain; MonoObject *obj, *ret; g_assert (args); domain = mono_object_get_domain ((MonoObject *) args); mono_runtime_ensure_entry_assembly (domain, mono_image_get_assembly ( mono_class_get_image ( mono_method_get_class (method)))); #if 0 #ifndef MONO_AGENT mono_new_thread_init (get_mono_thread(), &ret); #endif #endif obj = mono_object_new (domain, mono_method_get_class (method)); ret = mono_runtime_invoke_array (method, obj, args, exc); return ret; /* FIXME: check signature of method if (method->signature->ret->type == MONO_TYPE_I4) { res = mono_runtime_invoke (method, NULL, pa, exc); if (!exc || !*exc) rval = *(guint32 *)((char *)res + sizeof (MonoObject)); else rval = -1; fprintf (stderr, "[INT:%i]\n", rval); } else if (method->signature->ret->type == MONO_TYPE_SZARRAY) { MonoObject *res; int len; res = mono_runtime_invoke (method, NULL, pa, exc); rval = mono_array_length ((MonoArrayType *)res); len = mono_array_length ((MonoArray*)res); for (i = 0; i < len; ++i) { MonoObject *s; // = (MonoString *)mono_array_get ((MonoArray*)res, gpointer, i); fprintf (stderr, "[STRING:%s]\n", mono_string_to_utf8 ((MonoString *)s)); } if (!exc || !*exc) rval = *(guint32 *)((char *)res + sizeof (MonoObject)); else rval = -1; fprintf (stderr, "[INT:%i]\n", rval); } else { MonoObject *ress; ress = mono_runtime_invoke (method, NULL, pa, exc); fprintf (stderr, "[STRING:%s]\n", mono_string_to_utf8 ((MonoString *)ress)); } // return rval;*/ }
static gboolean collect_coverage_for (MonoProfiler *prof, MonoMethod *method) { int i; char *classname; char *fqn; MonoMethodHeader *header; gboolean has_positive, found; guint32 iflags, flags, code_size; MonoClass *klass; MonoImage *image; flags = mono_method_get_flags (method, &iflags); if ((iflags & 0x1000 /*METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL*/) || (flags & 0x2000 /*METHOD_ATTRIBUTE_PINVOKE_IMPL*/)) return FALSE; //if (method->wrapper_type != MONO_WRAPPER_NONE) // return FALSE; klass = mono_method_get_class (method); image = mono_class_get_image (klass); /* Hacky way of determining the executing assembly */ if (! prof->outfile_name && (strcmp (mono_method_get_name (method), "Main") == 0)) { prof->outfile_name = g_strdup_printf ("%s.cov", mono_image_get_filename (image)); } /* Check filters */ if (prof->filters) { /* Check already filtered classes first */ if (g_hash_table_lookup (prof->filtered_classes, klass)) return FALSE; classname = mono_type_get_name (mono_class_get_type (klass)); fqn = g_strdup_printf ("[%s]%s", mono_image_get_name (image), classname); // Check positive filters first has_positive = FALSE; found = FALSE; for (i = 0; i < prof->filters->len; ++i) { char *filter = g_ptr_array_index (prof->filters_as_str, i); if (filter [0] == '+') { filter = &filter [1]; if (strstr (fqn, filter) != NULL) found = TRUE; has_positive = TRUE; } } if (has_positive && !found) return FALSE; for (i = 0; i < prof->filters->len; ++i) { // Is substring search suffices ??? // GPatternSpec *spec = g_ptr_array_index (filters, i); // if (g_pattern_match_string (spec, classname)) { char *filter = g_ptr_array_index (prof->filters_as_str, i); if (filter [0] == '+') continue; // Skip '-' filter = &filter [1]; if (strstr (fqn, filter) != NULL) { g_hash_table_insert (prof->filtered_classes, klass, klass); return FALSE; } } g_free (fqn); g_free (classname); } header = mono_method_get_header (method); mono_method_header_get_code (header, &code_size, NULL); if (code_size > 20000) { exit (1); g_warning ("Unable to instrument method %s:%s since it is too complex.", mono_class_get_name (klass), mono_method_get_name (method)); return FALSE; } g_hash_table_insert (prof->methods, method, method); g_hash_table_insert (prof->classes, klass, klass); g_hash_table_insert (prof->assemblies, mono_image_get_assembly (image), mono_image_get_assembly (image)); return TRUE; }