diff options
Diffstat (limited to 'src/vm/securitydeclarative.cpp')
-rw-r--r-- | src/vm/securitydeclarative.cpp | 889 |
1 files changed, 2 insertions, 887 deletions
diff --git a/src/vm/securitydeclarative.cpp b/src/vm/securitydeclarative.cpp index e0aff16ddd..5771138b7d 100644 --- a/src/vm/securitydeclarative.cpp +++ b/src/vm/securitydeclarative.cpp @@ -12,9 +12,6 @@ #include "securitydeclarative.inl" #include "eventtrace.h" -#ifdef FEATURE_REMOTING -#include "remoting.h" -#endif // FEATURE_REMOTING //----------------------------------------------------------------------------- @@ -198,19 +195,11 @@ void SecurityDeclarative::AddDeclAction(CorDeclSecurity action, PsetCacheEntry * break; case DS_UNION: -#ifdef FEATURE_CAS_POLICY - LinkNewDeclAction(ppActionList, action, SecurityAttributes::MergePermissionSets(pClassPCE, pMethodPCE, false, action), pMeth); -#else // FEATURE_CAS_POLICY _ASSERTE(!"Declarative permission sets may not be unioned together in CoreCLR. Are you attempting to have a declarative demand or deny on both a method and its enclosing class?"); -#endif // FEATURE_CAS_POLICY break; case DS_INTERSECT: -#ifdef FEATURE_CAS_POLICY - LinkNewDeclAction(ppActionList, action, SecurityAttributes::MergePermissionSets(pClassPCE, pMethodPCE, true, action), pMeth); -#else // FEATURE_CAS_POLICY _ASSERTE(!"Declarative permission sets may not be intersected in CoreCLR. Are you attempting to have a declarative permit only on both a method and its enclosing class?"); -#endif // FEATURE_CAS_POLICY break; case DS_APPLY_METHOD_THEN_CLASS: @@ -269,14 +258,7 @@ DeclActionInfo* SecurityDeclarative::DetectDeclActions(MethodDesc *pMeth, DWORD if (pClass->HasSuppressUnmanagedCodeAccessAttr()) { -#ifdef FEATURE_CORECLR hr = S_OK; -#else - hr = pInternalImport->GetCustomAttributeByName(pMT->GetCl(), - COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI, - NULL, - NULL); -#endif // FEATURE_CORECLR if (hr != S_OK) { g_IBCLogger.LogEEClassCOWTableAccess(pMT); @@ -536,15 +518,7 @@ HRESULT SecurityDeclarative::GetDeclarationFlags(IMDInternalImport *pInternalImp BOOL hasSuppressUnmanagedCodeAccessAttr; if (pfHasSuppressUnmanagedCodeAccessAttr == NULL) { -#ifdef FEATURE_CORECLR hasSuppressUnmanagedCodeAccessAttr = TRUE; -#else - hasSuppressUnmanagedCodeAccessAttr = - (pInternalImport->GetCustomAttributeByName(token, - COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI, - NULL, - NULL) == S_OK); -#endif } else hasSuppressUnmanagedCodeAccessAttr = *pfHasSuppressUnmanagedCodeAccessAttr; @@ -605,175 +579,10 @@ void SecurityDeclarative::MethodInheritanceCheck(MethodDesc *pMethod, MethodDesc // //----------------------------------------------------------------------------- -#ifdef FEATURE_APTCA -void DECLSPEC_NORETURN SecurityDeclarative::ThrowAPTCAException(Assembly *pCaller, MethodDesc *pCallee) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - MethodDescCallSite throwSecurityException(METHOD__SECURITY_ENGINE__THROW_SECURITY_EXCEPTION); - - OBJECTREF callerObj = NULL; - if (pCaller != NULL && pCaller->GetDomain() == GetAppDomain()) - callerObj = pCaller->GetExposedObject(); - - ARG_SLOT args[7]; - args[0] = ObjToArgSlot(callerObj); - args[1] = ObjToArgSlot(NULL); - args[2] = ObjToArgSlot(NULL); - args[3] = PtrToArgSlot(pCallee); - args[4] = (ARG_SLOT)dclLinktimeCheck; - args[5] = ObjToArgSlot(NULL); - args[6] = ObjToArgSlot(NULL); - throwSecurityException.Call(args); - - UNREACHABLE(); -} -#endif // FEATURE_APTCA - -#ifdef FEATURE_CAS_POLICY -void DECLSPEC_NORETURN SecurityDeclarative::ThrowHPException(EApiCategories protectedCategories, EApiCategories demandedCategories) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - OBJECTREF hpException = NULL; - GCPROTECT_BEGIN(hpException); - - MethodTable* pMT = MscorlibBinder::GetClass(CLASS__HOST_PROTECTION_EXCEPTION); - hpException = (OBJECTREF) AllocateObject(pMT); - - - MethodDescCallSite ctor(METHOD__HOST_PROTECTION_EXCEPTION__CTOR); - - ARG_SLOT arg[3] = { - ObjToArgSlot(hpException), - protectedCategories, - demandedCategories - }; - ctor.Call(arg); - - COMPlusThrow(hpException); - - GCPROTECT_END(); -} -#endif // FEATURE_CAS_POLICY - -#ifdef FEATURE_APTCA -BOOL SecurityDeclarative::IsUntrustedCallerCheckNeeded(MethodDesc *pCalleeMD, Assembly *pCallerAssem) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - Assembly *pCalleeAssembly = pCalleeMD->GetAssembly(); - _ASSERTE(pCalleeAssembly != NULL); - - // ATPCA is only enforced for cross-assembly calls, so if the target is not accessable from outside - // the assembly, or if the caller and callee are both within the same assembly, we do not need to - // do any APTCA checks - if (pCallerAssem == pCalleeAssembly) - { - return FALSE; - } - - if (!MethodIsVisibleOutsideItsAssembly(pCalleeMD)) - { - return FALSE; - } - - // If the target assembly allows untrusted callers unconditionally, then the call should be allowed - if (pCalleeAssembly->AllowUntrustedCaller()) - { - return FALSE; - } - - // Otherwise, we need to ensure the caller is fully trusted - return TRUE; -} -#endif // FEATURE_APTCA - -#ifdef FEATURE_APTCA -// Do a fulltrust check on the caller if the callee is fully trusted and -// callee did not enable AllowUntrustedCallerChecks -/*static*/ -void SecurityDeclarative::DoUntrustedCallerChecks( - Assembly *pCaller, MethodDesc *pCallee, - BOOL fFullStackWalk) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - BOOL fRet = TRUE; -#ifdef _DEBUG - if (!g_pConfig->Do_AllowUntrustedCaller_Checks()) - return; -#endif - - if (!IsUntrustedCallerCheckNeeded(pCallee, pCaller)) - return; - - // Expensive calls after this point, this could end up resolving policy - - if (fFullStackWalk) - { - // It is possible that wrappers like VBHelper libraries that are - // fully trusted, make calls to public methods that do not have - // safe for Untrusted caller custom attribute set. - // Like all other link demand that gets transformed to a full stack - // walk for reflection, calls to public methods also gets - // converted to full stack walk - - OBJECTREF permSet = NULL; - GCPROTECT_BEGIN(permSet); - - GetPermissionInstance(&permSet, SECURITY_FULL_TRUST); - EX_TRY - { - SecurityStackWalk::DemandSet(SSWT_LATEBOUND_LINKDEMAND, permSet); - } - EX_CATCH - { - fRet = FALSE; - } - EX_END_CATCH(RethrowTerminalExceptions); - - GCPROTECT_END(); - } - else - { - _ASSERTE(pCaller); - - // Link Demand only, no full stack walk here - if (!pCaller->GetSecurityDescriptor()->IsFullyTrusted()) - fRet = FALSE; - } - - if (!fRet) - { - ThrowAPTCAException(pCaller, pCallee); - } -} -#endif // FEATURE_APTCA // Retrieve all linktime demands sets for a method. This includes both CAS and // non-CAS sets for LDs at the class and the method level, so we could get up to @@ -791,17 +600,6 @@ void SecurityDeclarative::RetrieveLinktimeDemands(MethodDesc *pMD, INJECT_FAULT(COMPlusThrowOM();); } CONTRACTL_END; -#ifdef FEATURE_CAS_POLICY - MethodTable * pMT = pMD->GetMethodTable(); - - // Class level first. - if (pMT->GetClass()->RequiresLinktimeCheck()) - *pClassCas = TypeSecurityDescriptor::GetLinktimePermissions(pMT, pClassNonCas); - - // Then the method level. - if (IsMdHasSecurity(pMD->GetAttrs())) - *pMethodCas = MethodSecurityDescriptor::GetLinktimePermissions(pMD, pMethodNonCas); -#endif } // @@ -841,7 +639,7 @@ LinktimeCheckReason SecurityDeclarative::GetLinktimeCheckReason(MethodDesc *pMD, LinktimeCheckReason reason = LinktimeCheckReason_None; -#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) +#if defined(FEATURE_CORESYSTEM) ModuleSecurityDescriptor *pMSD = ModuleSecurityDescriptor::GetModuleSecurityDescriptor(pMD->GetAssembly()); // If the method does not allow partially trusted callers, then the check is because we need to ensure all @@ -850,7 +648,7 @@ LinktimeCheckReason SecurityDeclarative::GetLinktimeCheckReason(MethodDesc *pMD, { reason |= LinktimeCheckReason_AptcaCheck; } -#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) +#endif // defined(FEATURE_CORESYSTEM) // // If the method has a LinkDemand on it for either CAS or non-CAS permissions, get those and set the @@ -952,688 +750,5 @@ LinktimeCheckReason SecurityDeclarative::GetLinktimeCheckReason(MethodDesc *pMD, return reason; } -#ifdef FEATURE_CAS_POLICY -// Issue an inheritance demand against the target assembly - -// static -void SecurityDeclarative::InheritanceDemand(Assembly *pTargetAssembly, OBJECTREF refDemand) -{ - CONTRACTL - { - THROWS; - MODE_COOPERATIVE; - GC_TRIGGERS; - PRECONDITION(CheckPointer(pTargetAssembly)); - PRECONDITION(refDemand != NULL); - } - CONTRACTL_END; - - struct - { - OBJECTREF refDemand; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - gc.refDemand = refDemand; - - GCPROTECT_BEGIN(gc); - - IAssemblySecurityDescriptor *pTargetASD = pTargetAssembly->GetSecurityDescriptor(); - SecurityStackWalk::LinkOrInheritanceCheck(pTargetASD, - gc.refDemand, - pTargetAssembly, - dclInheritanceCheck); - GCPROTECT_END(); -} - -// static -void SecurityDeclarative::InheritanceLinkDemandCheck(Assembly *pTargetAssembly, MethodDesc * pMDLinkDemand) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pTargetAssembly)); - PRECONDITION(CheckPointer(pMDLinkDemand)); - } - CONTRACTL_END; - - GCX_COOP(); - struct - { - OBJECTREF refClassCas; - OBJECTREF refClassNonCas; - OBJECTREF refMethodCas; - OBJECTREF refMethodNonCas; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - - Security::RetrieveLinktimeDemands(pMDLinkDemand, - &gc.refClassCas, - &gc.refClassNonCas, - &gc.refMethodCas, - &gc.refMethodNonCas); - - if (gc.refClassCas != NULL) - { - InheritanceDemand(pTargetAssembly, gc.refClassCas); - } - - if (gc.refMethodCas != NULL) - { - InheritanceDemand(pTargetAssembly, gc.refMethodCas); - } - - GCPROTECT_END(); -} - -// Issue a FullTrust inheritance demand against the target assembly - -// static -void SecurityDeclarative::FullTrustInheritanceDemand(Assembly *pTargetAssembly) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pTargetAssembly)); - } - CONTRACTL_END; - - GCX_COOP(); - - struct - { - OBJECTREF refFullTrust; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - - gc.refFullTrust = Security::CreatePermissionSet(TRUE); - InheritanceDemand(pTargetAssembly, gc.refFullTrust); - - GCPROTECT_END(); -} - -// Issue a FullTrust link demand against the target assembly - -// static -void SecurityDeclarative::FullTrustLinkDemand(Assembly *pTargetAssembly) -{ - CONTRACTL - { - THROWS; - MODE_COOPERATIVE; - GC_TRIGGERS; - PRECONDITION(CheckPointer(pTargetAssembly)); - } - CONTRACTL_END; - - struct - { - OBJECTREF refFullTrust; - } - gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - - gc.refFullTrust = Security::CreatePermissionSet(TRUE); - IAssemblySecurityDescriptor *pTargetASD = pTargetAssembly->GetSecurityDescriptor(); - SecurityStackWalk::LinkOrInheritanceCheck(pTargetASD, - gc.refFullTrust, - pTargetAssembly, - dclLinktimeCheck); - GCPROTECT_END(); -} - -// Used by interop to simulate the effect of link demands when the caller is -// in fact script constrained by an appdomain setup by IE. -void SecurityDeclarative::CheckLinkDemandAgainstAppDomain(MethodDesc *pMD) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - if (!pMD->RequiresLinktimeCheck()) - return; - - // Find the outermost (closest to caller) appdomain. This - // represents the domain in which the unmanaged caller is - // considered to "live" (or, at least, be constrained by). - AppDomain *pDomain = GetThread()->GetInitialDomain(); - - // The link check is only performed if this app domain has - // security permissions associated with it, which will be - // the case for all IE scripting callers that have got this - // far because we automatically reported our managed classes - // as "safe for scripting". - // - // We also can't do the check if the AppDomain isn't fully - // setup yet, since we might not have a domain grant set. - // This is acceptable, since the only code that should run - // during AppDomain creation is fully trusted. - IApplicationSecurityDescriptor *pSecDesc = pDomain->GetSecurityDescriptor(); - if (pSecDesc == NULL || pSecDesc->IsInitializationInProgress() || pSecDesc->IsDefaultAppDomain()) - return; - - struct _gc - { - OBJECTREF refGrant; - OBJECTREF refRefused; - OBJECTREF refClassNonCasDemands; - OBJECTREF refClassCasDemands; - OBJECTREF refMethodNonCasDemands; - OBJECTREF refMethodCasDemands; - OBJECTREF refAssembly; - } gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - -#ifdef FEATURE_APTCA - // Do a fulltrust check on the caller if the callee did not enable - // AllowUntrustedCallerChecks. Pass a NULL caller assembly: - // DoUntrustedCallerChecks needs to be able to cope with this. - SecurityDeclarative::DoUntrustedCallerChecks(NULL, pMD, TRUE); -#endif // FEATURE_APTCA - - // Fetch link demand sets from all the places in metadata where we might - // find them (class and method). These might be split into CAS and non-CAS - // sets as well. - SecurityDeclarative::RetrieveLinktimeDemands(pMD, - &gc.refClassCasDemands, - &gc.refClassNonCasDemands, - &gc.refMethodCasDemands, - &gc.refMethodNonCasDemands); - - // Check CAS link demands. - bool fGotGrantSet = false; - if (gc.refClassCasDemands != NULL || gc.refMethodCasDemands != NULL) - { - // Get grant (and possibly denied) sets from the app - // domain. - gc.refGrant = pSecDesc->GetGrantedPermissionSet(NULL); - fGotGrantSet = true; - gc.refAssembly = pMD->GetAssembly()->GetExposedObject(); - - if (gc.refClassCasDemands != NULL) - SecurityStackWalk::CheckSetHelper(&gc.refClassCasDemands, - &gc.refGrant, - &gc.refRefused, - pDomain, - pMD, - &gc.refAssembly, - dclLinktimeCheck); - - if (gc.refMethodCasDemands != NULL) - SecurityStackWalk::CheckSetHelper(&gc.refMethodCasDemands, - &gc.refGrant, - &gc.refRefused, - pDomain, - pMD, - &gc.refAssembly, - dclLinktimeCheck); - - } - - // Non-CAS demands are not applied against a grant - // set, they're standalone. - if (gc.refClassNonCasDemands != NULL) - CheckNonCasDemand(&gc.refClassNonCasDemands); - - if (gc.refMethodNonCasDemands != NULL) - CheckNonCasDemand(&gc.refMethodNonCasDemands); - -#ifndef FEATURE_CORECLR - // On CORECLR, we do this from the JIT callouts if the caller is transparent: if caller is critical, no checks needed - - // We perform automatic linktime checks for UnmanagedCode in three cases: - // o P/Invoke calls (shouldn't get these here, but let's be paranoid). - // o Calls through an interface that have a suppress runtime check - // attribute on them (these are almost certainly interop calls). - // o Interop calls made through method impls. - // Just walk the stack in these cases, they'll be extremely rare and the - // perf delta isn't that huge. - if (pMD->IsNDirect() || - (pMD->IsInterface() && - (pMD->GetMDImport()->GetCustomAttributeByName(pMD->GetMethodTable()->GetCl(), - COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI, - NULL, - NULL) == S_OK || - pMD->GetMDImport()->GetCustomAttributeByName(pMD->GetMemberDef(), - COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI, - NULL, - NULL) == S_OK) ) || - (pMD->IsComPlusCall() && !pMD->IsInterface())) - SecurityStackWalk::SpecialDemand(SSWT_LATEBOUND_LINKDEMAND, SECURITY_UNMANAGED_CODE); -#endif // FEATURE_CORECLR - - GCPROTECT_END(); -} - - - - - - - - - - - - - - - - - - - - - - - - - -//----------------------------------------------------------------------------- -// -// -// CODE FOR PERFORMING RUN-TIME CHECKS -// -// -//----------------------------------------------------------------------------- - -void SecurityDeclarative::EnsureAssertAllowed(MethodDesc *pMeth, MethodSecurityDescriptor *pMSD) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - PRECONDITION(CheckPointer(pMeth)); - PRECONDITION(pMSD == NULL || pMSD->GetMethod() == pMeth); - } CONTRACTL_END; - - // Check if this Assembly has permission to assert - if (pMSD == NULL || !pMSD->CanAssert()) // early out if we have an MSD and we already have checked this permission - { - Module* pModule = pMeth->GetModule(); - PREFIX_ASSUME_MSG(pModule != NULL, "Should be a Module pointer here"); - - if (!Security::CanAssert(pModule)) - SecurityPolicy::ThrowSecurityException(g_SecurityPermissionClassName, SPFLAGSASSERTION); - } - - // Check if the Method is allowed to assert based on transparent/critical classification - if (!SecurityTransparent::IsAllowedToAssert(pMeth) && Security::IsTransparencyEnforcementEnabled()) - { -#ifdef _DEBUG - if (g_pConfig->LogTransparencyErrors()) - { - SecurityTransparent::LogTransparencyError(pMeth, "Transparent method using a security assert"); - } -#endif // _DEBUG - // if assembly is transparent fail the ASSERT operations - COMPlusThrow(kInvalidOperationException, W("InvalidOperation_AssertTransparentCode")); - } - - return; -} - -void SecurityDeclarative::InvokeDeclarativeActions (MethodDesc *pMeth, DeclActionInfo *pActions, MethodSecurityDescriptor *pMSD) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - OBJECTREF refPermSet = NULL; - ARG_SLOT arg = 0; - - // If we get a real PermissionSet, then invoke the action. - switch (pActions->dwDeclAction) - { - case DECLSEC_DEMANDS: - SecurityStackWalk::DemandSet(SSWT_DECLARATIVE_DEMAND, pActions->pPCE, dclDemand); - break; - - case DECLSEC_ASSERTIONS: - EnsureAssertAllowed(pMeth, pMSD); - GetThread()->IncrementAssertCount(); - break; - - case DECLSEC_DENIALS: - case DECLSEC_PERMITONLY: - GetThread()->IncrementOverridesCount(); - break; - - case DECLSEC_NONCAS_DEMANDS: - refPermSet = pActions->pPCE->CreateManagedPsetObject (dclNonCasDemand); - if (refPermSet == NULL) - break; - if(!((PERMISSIONSETREF)refPermSet)->CheckedForNonCas() ||((PERMISSIONSETREF)refPermSet)->ContainsNonCas()) - { - GCPROTECT_BEGIN(refPermSet); - MethodDescCallSite demand(METHOD__PERMISSION_SET__DEMAND_NON_CAS, &refPermSet); - - arg = ObjToArgSlot(refPermSet); - demand.Call(&arg); - GCPROTECT_END(); - } - break; - - default: - _ASSERTE(!"Unknown action requested in InvokeDeclarativeActions"); - break; - - } // switch -} - - -// -// CODE FOR PERFORMING RUN-TIME CHECKS -// -extern LPVOID GetSecurityObjectForFrameInternal(StackCrawlMark *stackMark, INT32 create, OBJECTREF *pRefSecDesc); - -namespace -{ - inline void UpdateFrameSecurityObj(DWORD dwAction, OBJECTREF *refPermSet, OBJECTREF * pSecObj) - { - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - GetSecurityObjectForFrameInternal(NULL, true, pSecObj); - - FRAMESECDESCREF fsdRef = (FRAMESECDESCREF)*pSecObj; - switch (dwAction) - { - // currently we require declarative security to store the data in both the fields in the FSD - case dclAssert: - fsdRef->SetDeclarativeAssertions(*refPermSet); - { - PERMISSIONSETREF psRef = (PERMISSIONSETREF)*refPermSet; - if (psRef != NULL && psRef->IsUnrestricted()) - fsdRef->SetAssertFT(TRUE); - } - break; - - case dclDeny: - fsdRef->SetDeclarativeDenials(*refPermSet); - break; - - case dclPermitOnly: - fsdRef->SetDeclarativeRestrictions(*refPermSet); - break; - - default: - _ASSERTE(0 && "Unreached, add code to handle if reached here..."); - break; - } - } -} - -void SecurityDeclarative::InvokeDeclarativeStackModifiers(MethodDesc * pMeth, DeclActionInfo * pActions, OBJECTREF * pSecObj) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - OBJECTREF refPermSet = NULL; - - // If we get a real PermissionSet, then invoke the action. - switch (pActions->dwDeclAction) - { - case DECLSEC_DEMANDS: - case DECLSEC_NONCAS_DEMANDS: - // Nothing to do for demands - break; - - case DECLSEC_ASSERTIONS: - refPermSet = pActions->pPCE->CreateManagedPsetObject (dclAssert); - if (refPermSet == NULL) - break; - GCPROTECT_BEGIN(refPermSet); - // Now update the frame security object - UpdateFrameSecurityObj(dclAssert, &refPermSet, pSecObj); - GCPROTECT_END(); - break; - - case DECLSEC_DENIALS: - // Update the frame security object - refPermSet = pActions->pPCE->CreateManagedPsetObject (dclDeny); - - if (refPermSet == NULL) - break; - - GCPROTECT_BEGIN(refPermSet); - -#ifdef FEATURE_CAS_POLICY - // Deny is only valid if we're in legacy CAS mode - IApplicationSecurityDescriptor *pSecDesc = GetAppDomain()->GetSecurityDescriptor(); - if (!pSecDesc->IsLegacyCasPolicyEnabled()) - { - COMPlusThrow(kNotSupportedException, W("NotSupported_CasDeny")); - } -#endif // FEATURE_CAS_POLICY - - UpdateFrameSecurityObj(dclDeny, &refPermSet, pSecObj); - - GCPROTECT_END(); - break; - - case DECLSEC_PERMITONLY: - // Update the frame security object - refPermSet = pActions->pPCE->CreateManagedPsetObject (dclPermitOnly); - - if (refPermSet == NULL) - break; - GCPROTECT_BEGIN(refPermSet); - UpdateFrameSecurityObj(dclPermitOnly, &refPermSet, pSecObj); - GCPROTECT_END(); - break; - - - default: - _ASSERTE(!"Unknown action requested in InvokeDeclarativeStackModifiers"); - break; - - } // switch -} - -void SecurityDeclarative::DoDeclarativeActions(MethodDesc *pMeth, DeclActionInfo *pActions, LPVOID pSecObj, MethodSecurityDescriptor *pMSD) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - -#ifndef FEATURE_CAS_POLICY - // In the CoreCLR, we don't support CAS actions outside mscorlib. - // However, we do have to expose certain types in mscorlib due to compiler requirements - // (c# compiler requires us to expose SecurityPermission/SecurityAction etc so that it can - // insert a RequestMinimum for SkipVerification). - // This means that code outside mscorlib could construct IL that has declarative security - // in it. This is not a security issue - even if they try to create IL that asserts for - // permissions they don't have, it's not going to work for the same reasons it didn't in the desktop. - // However, we could have bugs like DDB 120109 where they can cause Demands to fail etc. - // So for goodness, we're not going to do any runtime declarative work on assemblies other than mscorlib. - if (!pMeth->GetModule()->IsSystem()) - { - // Non-mscorlib code reached... exit - return; - } -#endif //!FEATURE_CAS_POLICY - - - // --------------------------------------------------------------------------- // - // D E C L A R A T I V E S E C U R I T Y D E M A N D S // - // --------------------------------------------------------------------------- // - // The frame is now fully formed, arguments have been copied into place, - // and synchronization monitors have been entered if necessary. At this - // point, we are prepared for something to throw an exception, so we may - // check for declarative security demands and execute them. We need a - // well-formed frame and synchronization domain to accept security excep- - // tions thrown by the SecurityManager. We MAY need argument values in - // the frame so that the arguments may be finalized if security throws an - // exception across them (unknown). - if (pActions != NULL && pActions->dwDeclAction == DECLSEC_UNMNGD_ACCESS_DEMAND && - pActions->pNext == NULL) - { - /* We special-case the security check on single pinvoke/interop calls - so we can avoid setting up the GCFrame */ - - SecurityStackWalk::SpecialDemand(SSWT_DECLARATIVE_DEMAND, SECURITY_UNMANAGED_CODE); - return; - } - else - { -#ifdef FEATURE_COMPRESSEDSTACK - // If this is an anonymously hosted dynamic method, there aren't any direct modifiers, but if it has a compressed stack that - // might have modifiers, mark that there are modifiers so we make sure to do a stack walk - if(SecurityStackWalk::MethodIsAnonymouslyHostedDynamicMethodWithCSToEvaluate(pMeth)) - { - // We don't know how many asserts or overrides might be in the compressed stack, - // but we just need to increment the counters to ensure optimizations don't skip CS evaluation - GetThread()->IncrementAssertCount(); - GetThread()->IncrementOverridesCount(); - } -#endif // FEATURE_COMPRESSEDSTACK - - for (/**/; pActions; pActions = pActions->pNext) - { - if (pActions->dwDeclAction == DECLSEC_UNMNGD_ACCESS_DEMAND) - { - SecurityStackWalk::SpecialDemand(SSWT_DECLARATIVE_DEMAND, SECURITY_UNMANAGED_CODE); - } - else - { - InvokeDeclarativeActions(pMeth, pActions, pMSD); - } - } - - } -} -void SecurityDeclarative::DoDeclarativeStackModifiers(MethodDesc *pMeth, AppDomain* pAppDomain, LPVOID pSecObj) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - -#ifndef FEATURE_CAS_POLICY - // In the CoreCLR, we don't support CAS actions outside mscorlib. - // However, we do have to expose certain types in mscorlib due to compiler requirements - // (c# compiler requires us to expose SecurityPermission/SecurityAction etc so that it can - // insert a RequestMinimum for SkipVerification). - // This means that code outside mscorlib could construct IL that has declarative security - // in it. This is not a security issue - even if they try to create IL that asserts for - // permissions they don't have, it's not going to work for the same reasons it didn't in the desktop. - // However, we could have bugs like DDB 120109 where they can cause Demands to fail etc. - // So for goodness, we're not going to do any runtime declarative work on assemblies other than mscorlib. - if (!pMeth->GetModule()->IsSystem()) - { - // Non-mscorlib code reached... exit - return; - } -#endif //!FEATURE_CAS_POLICY - - - AppDomain* pCurrentDomain = GetAppDomain(); - - if (pCurrentDomain != pAppDomain) - { - ENTER_DOMAIN_PTR(pAppDomain, ADV_RUNNINGIN) - { - DoDeclarativeStackModifiersInternal(pMeth, pSecObj); - } - END_DOMAIN_TRANSITION; - } - else - { - DoDeclarativeStackModifiersInternal(pMeth, pSecObj); - } - } - -void SecurityDeclarative::DoDeclarativeStackModifiersInternal(MethodDesc *pMeth, LPVOID pSecObj) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - INJECT_FAULT(COMPlusThrowOM();); - } CONTRACTL_END; - - Object** ppSecObject = (Object**) pSecObj; - _ASSERTE(pMeth->IsInterceptedForDeclSecurity() && !pMeth->IsInterceptedForDeclSecurityCASDemandsOnly()); - - MethodSecurityDescriptor MDSecDesc(pMeth); - MethodSecurityDescriptor::LookupOrCreateMethodSecurityDescriptor(&MDSecDesc); - DeclActionInfo* pActions = MDSecDesc.GetRuntimeDeclActionInfo(); - - OBJECTREF fsdRef = ObjectToOBJECTREF(*ppSecObject); - GCPROTECT_BEGIN(fsdRef); - - for (/**/; pActions; pActions = pActions->pNext) - { - InvokeDeclarativeStackModifiers(pMeth, pActions, &fsdRef); - } - // If we had just NON-CAS demands, we'd come here but not create an FSD. - if (fsdRef != NULL) - { - ((FRAMESECDESCREF)(fsdRef))->SetDeclSecComputed(TRUE); - - if (*ppSecObject == NULL) - { - // we came in with a NULL FSD and the FSD got created here...so we need to copy it back - // If we had come in with a non-NULL FSD, that would have been updated and this (shallow/pointer) copy - // would not be necessary - *ppSecObject = OBJECTREFToObject(fsdRef); - } -} - - GCPROTECT_END(); -} - - -void SecurityDeclarative::CheckNonCasDemand(OBJECTREF *prefDemand) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(IsProtectedByGCFrame (prefDemand)); - } CONTRACTL_END; - - if(((PERMISSIONSETREF)*prefDemand)->CheckedForNonCas()) - { - if(!((PERMISSIONSETREF)*prefDemand)->ContainsNonCas()) - return; - } - MethodDescCallSite demand(METHOD__PERMISSION_SET__DEMAND_NON_CAS, prefDemand); - ARG_SLOT arg = ObjToArgSlot(*prefDemand); - demand.Call(&arg); -} - -#endif // FEATURE_CAS_POLICY #endif // CROSSGEN_COMPILE |