X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fdeclsec.c;h=65e38d7f8fe5b29cb3e0b517954faace3cd71875;hb=4323fbeaebf249f016dfdd6dc9b3b52a515f87c4;hp=3ee9660c052e0669960eee17c59266c3574e3352;hpb=a1d6bfdb8ab1271b787dd0d031443a4272930eda;p=mono.git diff --git a/mono/mini/declsec.c b/mono/mini/declsec.c index 3ee9660c052..65e38d7f8fe 100644 --- a/mono/mini/declsec.c +++ b/mono/mini/declsec.c @@ -8,6 +8,7 @@ */ #include "declsec.h" +#include "mini.h" /* * Does the methods (or it's class) as any declarative security attribute ? @@ -16,7 +17,9 @@ MonoBoolean mono_method_has_declsec (MonoMethod *method) { - if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) { + mono_jit_stats.cas_declsec_check++; + + if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) { method = mono_marshal_method_from_wrapper (method); if (!method) return FALSE; @@ -67,7 +70,8 @@ mono_declsec_create_frame (MonoDomain *domain, MonoJitInfo *jinfo) jinfo->cas_inited = TRUE; } - frame->method = mono_method_get_object (domain, jinfo->method, NULL); + MONO_OBJECT_SETREF (frame, method, mono_method_get_object (domain, jinfo->method, NULL)); + MONO_OBJECT_SETREF (frame, domain, domain->domain); /* stack modifiers on methods have priority on (i.e. replaces) modifiers on class */ @@ -112,6 +116,8 @@ mono_declsec_linkdemand_standard (MonoDomain *domain, MonoMethod *caller, MonoMe { MonoDeclSecurityActions linkclass, linkmethod; + 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); @@ -129,13 +135,47 @@ mono_declsec_linkdemand_standard (MonoDomain *domain, MonoMethod *caller, MonoMe return FALSE; } +/* + * Ensure that the restrictions for partially trusted code are satisfied. + * + * @domain The current application domain + * @assembly The assembly to query + * return value: TRUE if the assembly is runnning at FullTrust, FALSE otherwise. + */ +static gboolean +mono_declsec_is_assembly_fulltrust (MonoDomain *domain, MonoAssembly *assembly) +{ + if (!MONO_SECMAN_FLAG_INIT (assembly->fulltrust)) { + 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->linkdemandfulltrust, NULL, args, NULL); + if (*(MonoBoolean *) mono_object_unbox(res)) { + /* keep this value cached as it will be used very often */ + MONO_SECMAN_FLAG_SET_VALUE (assembly->fulltrust, TRUE); + return TRUE; + } + } + + MONO_SECMAN_FLAG_SET_VALUE (assembly->fulltrust, FALSE); + return FALSE; + } + + return MONO_SECMAN_FLAG_GET_VALUE (assembly->fulltrust); +} + /* * 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 detection, FALSE otherwise. + * 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 @@ -146,10 +186,12 @@ mono_declsec_linkdemand_standard (MonoDomain *domain, MonoMethod *caller, MonoMe static gboolean mono_declsec_linkdemand_aptc (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee) { - MonoSecurityManager* secman; + MonoSecurityManager* secman = NULL; MonoAssembly *assembly; guint32 size = 0; + 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; @@ -166,12 +208,14 @@ mono_declsec_linkdemand_aptc (MonoDomain *domain, MonoMethod *caller, MonoMethod assembly = mono_image_get_assembly (callee->klass->image); if (!MONO_SECMAN_FLAG_INIT (assembly->aptc)) { MonoCustomAttrInfo* cinfo = mono_custom_attrs_from_assembly (assembly); - secman = mono_security_manager_get_methods (); gboolean result = FALSE; + secman = mono_security_manager_get_methods (); if (secman && cinfo) { /* look for AllowPartiallyTrustedCallersAttribute */ - result = mono_custom_attrs_has_attr (cinfo, secman->aptc); + result = mono_custom_attrs_has_attr (cinfo, secman->allowpartiallytrustedcallers); } + if (cinfo) + mono_custom_attrs_free (cinfo); MONO_SECMAN_FLAG_SET_VALUE (assembly->aptc, result); } @@ -179,28 +223,8 @@ mono_declsec_linkdemand_aptc (MonoDomain *domain, MonoMethod *caller, MonoMethod return FALSE; /* E - the caller's assembly must have full trust permissions */ - if (!MONO_SECMAN_FLAG_INIT (assembly->fulltrust)) { - MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (domain, assembly); - if (!secman) - secman = mono_security_manager_get_methods (); - - if (secman && refass) { - MonoObject *res; - gpointer args [1]; - args [0] = refass; - - res = mono_runtime_invoke (secman->linkdemandfulltrust, NULL, args, NULL); - if (*(MonoBoolean *) mono_object_unbox(res)) { - /* keep this value cached as it will be used very often */ - MONO_SECMAN_FLAG_SET_VALUE (assembly->fulltrust, TRUE); - return FALSE; - } - } - - MONO_SECMAN_FLAG_SET_VALUE (assembly->fulltrust, FALSE); - } - - if (MONO_SECMAN_FLAG_GET_VALUE (assembly->fulltrust)) + 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", @@ -209,54 +233,13 @@ mono_declsec_linkdemand_aptc (MonoDomain *domain, MonoMethod *caller, MonoMethod return TRUE; /* i.e. throw new SecurityException(); */ } -/* - * Ensure that the restrictions for calling internal calls are satisfied. - * - * @caller The method calling - * @icall The internal call method - * return value: TRUE if a security violation is detection, FALSE otherwise. - * - * Executing internal calls (icalls) is a restricted operation. Only - * assemblies with an ECMA public key are allowed to call them (unless they - * are publicly available). - * - * This LinkDemand case is special because it can be done without calling - * managed code. - */ -static gboolean -mono_declsec_linkdemand_ecma (MonoMethod *caller, MonoMethod *icall) -{ - MonoAssembly *assembly; - - /* some icall are public (i.e. they CAN be called by any code) */ - if (((icall->klass->flags & TYPE_ATTRIBUTE_PUBLIC) == TYPE_ATTRIBUTE_PUBLIC) && - ((icall->flags & FIELD_ATTRIBUTE_PUBLIC) == FIELD_ATTRIBUTE_PUBLIC)) { - return FALSE; - } - - 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 (caller->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; - - /* g_warning ("FAILURE *** JIT LinkDemand for ECMA check *** %s.%s calls into %s.%s", - caller->klass->name, caller->name, icall->klass->name, icall->name); */ - - return TRUE; /* i.e. throw new SecurityException(); */ -} - /* * 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 detection, FALSE otherwise. + * 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) @@ -279,12 +262,15 @@ mono_declsec_linkdemand_pinvoke (MonoDomain *domain, MonoMethod *caller, MonoMet { MonoAssembly *assembly = mono_image_get_assembly (caller->klass->image); + 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 (); @@ -313,6 +299,46 @@ mono_declsec_linkdemand_pinvoke (MonoDomain *domain, MonoMethod *caller, MonoMet return TRUE; /* i.e. throw new SecurityException(); */ } +/* + * 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; + + 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); +} + /* * Before the JIT can link (call) into a method the following security checks @@ -335,11 +361,17 @@ guint32 mono_declsec_linkdemand (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee) { guint32 violation = MONO_JIT_SECURITY_OK; - /* first, the special (implied) linkdemand */ + + /* short-circuit corlib as it is fully trusted (within itself) + * and because this cause major recursion headaches */ + if ((caller->klass->image == mono_defaults.corlib) && (callee->klass->image == mono_defaults.corlib)) + return violation; + + /* next, the special (implied) linkdemand */ if (callee->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { - /* restrict calls into the runtime to ECMA signed assemblies */ - if (mono_declsec_linkdemand_ecma (caller, callee)) + /* restrict internal calls into the runtime */ + if (mono_declsec_linkdemand_icall (domain, caller, callee)) violation = MONO_JIT_LINKDEMAND_ECMA; } else if (callee->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { /* CAS can restrict p/invoke calls with the assembly granted permissions */