diff options
Diffstat (limited to 'src/vm/securitymeta.inl')
-rw-r--r-- | src/vm/securitymeta.inl | 1272 |
1 files changed, 1272 insertions, 0 deletions
diff --git a/src/vm/securitymeta.inl b/src/vm/securitymeta.inl new file mode 100644 index 0000000000..adb6faa5ac --- /dev/null +++ b/src/vm/securitymeta.inl @@ -0,0 +1,1272 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//-------------------------------------------------------------------------- +// securitymeta.inl +// +// pre-computes various security information, declarative and runtime meta-info +// + + +// +//-------------------------------------------------------------------------- + + +#include "typestring.h" + +#include "securitypolicy.h" +#include "securitydeclarative.h" + +#ifndef __SECURITYMETA_INL__ +#define __SECURITYMETA_INL__ + +inline TokenSecurityDescriptorFlags operator|(TokenSecurityDescriptorFlags lhs, + TokenSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<TokenSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); +} + +inline TokenSecurityDescriptorFlags operator|=(TokenSecurityDescriptorFlags& lhs, + TokenSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<TokenSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); + return lhs; +} + +inline TokenSecurityDescriptorFlags operator&(TokenSecurityDescriptorFlags lhs, + TokenSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<TokenSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); +} + +inline TokenSecurityDescriptorFlags operator&=(TokenSecurityDescriptorFlags& lhs, + TokenSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<TokenSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); + return lhs; +} + +inline TokenSecurityDescriptorFlags operator~(TokenSecurityDescriptorFlags flags) +{ + LIMITED_METHOD_CONTRACT; + + // Invert all the bits which aren't part of the rules version number + DWORD flagBits = flags & ~static_cast<DWORD>(TokenSecurityDescriptorFlags_RulesVersionMask); + return static_cast<TokenSecurityDescriptorFlags>( + (EncodeSecurityRuleSet(GetSecurityRuleSet(flags)) << 24 ) | + (~flagBits)); +} + +// Get the version of the security rules that token security descriptor flags are requesting +inline SecurityRuleSet GetSecurityRuleSet(TokenSecurityDescriptorFlags flags) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<SecurityRuleSet>((flags & TokenSecurityDescriptorFlags_RulesMask) >> 24); +} + +// Encode a security rule set into token flags - this reverses GetSecurityRuleSet +inline TokenSecurityDescriptorFlags EncodeSecurityRuleSet(SecurityRuleSet ruleSet) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<TokenSecurityDescriptorFlags>(static_cast<DWORD>(ruleSet) << 24); +} + +inline TokenSecurityDescriptor::TokenSecurityDescriptor(PTR_Module pModule, mdToken token) + : m_pModule(pModule), + m_token(token), + m_flags(TokenSecurityDescriptorFlags_None) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(pModule); +} + +inline TokenSecurityDescriptorFlags TokenSecurityDescriptor::GetFlags() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return m_flags; +} + +// Get the attributes that were set on the token +inline TokenSecurityDescriptorFlags TokenSecurityDescriptor::GetMetadataFlags() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return m_flags & TokenSecurityDescriptorFlags_RawAttributeMask; +} + +inline BOOL TokenSecurityDescriptor::IsSemanticCritical() +{ + WRAPPER_NO_CONTRACT; + VerifySemanticDataComputed(); + return !!(m_flags & TokenSecurityDescriptorFlags_IsSemanticCritical); +} + +inline BOOL TokenSecurityDescriptor::IsSemanticTreatAsSafe() +{ + WRAPPER_NO_CONTRACT; + VerifySemanticDataComputed(); + return !!(m_flags & TokenSecurityDescriptorFlags_IsSemanticTreatAsSafe); +} + +inline BOOL TokenSecurityDescriptor::IsSemanticExternallyVisible() +{ + WRAPPER_NO_CONTRACT; + VerifySemanticDataComputed(); + return !!(m_flags & TokenSecurityDescriptorFlags_IsSemanticExternallyVisible); +} + +// Determine if the type represented by the token in this TokenSecurityDescriptor is participating in type +// equivalence. +inline BOOL TokenSecurityDescriptor::IsTypeEquivalent() +{ + WRAPPER_NO_CONTRACT; + + _ASSERTE(TypeFromToken(m_token) == mdtTypeDef); + return IsTypeDefEquivalent(m_token, m_pModule); +} + +#ifndef DACCESS_COMPILE + +inline TokenSecurityDescriptor::TokenSecurityDescriptorTransparencyEtwEvents::TokenSecurityDescriptorTransparencyEtwEvents(const TokenSecurityDescriptor *pTSD) + : m_pTSD(pTSD) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + } + CONTRACTL_END + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TokenTransparencyComputationStart)) + { + LPCWSTR module = m_pTSD->m_pModule->GetPathForErrorMessages(); + + ETW::SecurityLog::FireTokenTransparencyComputationStart(m_pTSD->m_token, + module, + ::GetAppDomain()->GetId().m_dwId); + } +} + +inline TokenSecurityDescriptor::TokenSecurityDescriptorTransparencyEtwEvents::~TokenSecurityDescriptorTransparencyEtwEvents() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + } + CONTRACTL_END + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TokenTransparencyComputationEnd)) + { + LPCWSTR module = m_pTSD->m_pModule->GetPathForErrorMessages(); + + ETW::SecurityLog::FireTokenTransparencyComputationEnd(m_pTSD->m_token, + module, + !!(m_pTSD->m_flags & TokenSecurityDescriptorFlags_IsSemanticCritical), + !!(m_pTSD->m_flags & TokenSecurityDescriptorFlags_IsSemanticTreatAsSafe), + ::GetAppDomain()->GetId().m_dwId); + } +} + +#endif //!DACCESS_COMPILE + +inline MethodSecurityDescriptor::MethodSecurityDescriptor(MethodDesc* pMD, BOOL fCanCache /* = TRUE */) : + m_pMD(pMD), + m_pRuntimeDeclActionInfo(NULL), + m_pTokenDeclActionInfo(NULL), + m_flags(MethodSecurityDescriptorFlags_None), + m_declFlagsDuringPreStub(0) +{ + WRAPPER_NO_CONTRACT; + + if (fCanCache) + { + SetCanCache(); + } +} + +inline BOOL MethodSecurityDescriptor::CanAssert() +{ + // No need to do a VerifyDataComputed here -> this value is set by SecurityDeclarative::EnsureAssertAllowed as an optmization + LIMITED_METHOD_CONTRACT; + return !!(m_flags & MethodSecurityDescriptorFlags_AssertAllowed); +} + +inline void MethodSecurityDescriptor::SetCanAssert() +{ + LIMITED_METHOD_CONTRACT; + FastInterlockOr(reinterpret_cast<DWORD *>(&m_flags), MethodSecurityDescriptorFlags_AssertAllowed); +} + +inline BOOL MethodSecurityDescriptor::CanCache() +{ + LIMITED_METHOD_CONTRACT; + return !!(m_flags & MethodSecurityDescriptorFlags_CanCache); +} + +inline void MethodSecurityDescriptor::SetCanCache() +{ + LIMITED_METHOD_CONTRACT; + FastInterlockOr(reinterpret_cast<DWORD *>(&m_flags), MethodSecurityDescriptorFlags_CanCache); +} + +inline BOOL MethodSecurityDescriptor::HasRuntimeDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return m_pMD->IsInterceptedForDeclSecurity(); +} + +inline BOOL MethodSecurityDescriptor::HasLinkOrInheritanceDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return HasLinktimeDeclarativeSecurity() || HasInheritanceDeclarativeSecurity(); +} + +inline BOOL MethodSecurityDescriptor::HasLinktimeDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return m_pMD->RequiresLinktimeCheck(); +} + +inline BOOL MethodSecurityDescriptor::HasInheritanceDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return m_pMD->RequiresInheritanceCheck(); +} + +inline mdToken MethodSecurityDescriptor::GetToken() +{ + WRAPPER_NO_CONTRACT; + return m_pMD->GetMemberDef(); +} + +inline MethodDesc *MethodSecurityDescriptor::GetMethod() +{ + WRAPPER_NO_CONTRACT; + return m_pMD; +} + +inline IMDInternalImport *MethodSecurityDescriptor::GetIMDInternalImport() +{ + WRAPPER_NO_CONTRACT; + return m_pMD->GetMDImport(); +} + + +inline BOOL MethodSecurityDescriptor::ContainsBuiltInCASDemandsOnly() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return ((m_flags & MethodSecurityDescriptorFlags_IsBuiltInCASPermsOnly) && + (m_flags & MethodSecurityDescriptorFlags_IsDemandsOnly)); +} + +inline DeclActionInfo* MethodSecurityDescriptor::GetRuntimeDeclActionInfo() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return m_pRuntimeDeclActionInfo; +} + +inline DWORD MethodSecurityDescriptor::GetDeclFlagsDuringPreStub() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return m_declFlagsDuringPreStub; +} + +inline TokenDeclActionInfo* MethodSecurityDescriptor::GetTokenDeclActionInfo() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return m_pTokenDeclActionInfo; +} + +inline BOOL MethodSecurityDescriptor::IsCritical() +{ + WRAPPER_NO_CONTRACT; + + if (!m_pMD->HasCriticalTransparentInfo()) + ComputeCriticalTransparentInfo(); + return m_pMD->IsCritical(); +} + +inline BOOL MethodSecurityDescriptor::IsTreatAsSafe() +{ + WRAPPER_NO_CONTRACT; + + if (!m_pMD->HasCriticalTransparentInfo()) + ComputeCriticalTransparentInfo(); + return m_pMD->IsTreatAsSafe(); +} + +inline BOOL MethodSecurityDescriptor::IsOpportunisticallyCritical() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + TypeSecurityDescriptor typeSecDesc(m_pMD->GetMethodTable()); + return typeSecDesc.IsOpportunisticallyCritical(); +} + +inline HRESULT MethodSecurityDescriptor::GetDeclaredPermissionsWithCache(IN CorDeclSecurity action, + OUT OBJECTREF *pDeclaredPermissions, + OUT PsetCacheEntry **pPCE) +{ + WRAPPER_NO_CONTRACT; + return GetTokenDeclActionInfo()->GetDeclaredPermissionsWithCache(action, pDeclaredPermissions, pPCE); +} + +// static +inline HRESULT MethodSecurityDescriptor::GetDeclaredPermissionsWithCache(MethodDesc* pMD, + IN CorDeclSecurity action, + OUT OBJECTREF *pDeclaredPermissions, + OUT PsetCacheEntry **pPCE) +{ + WRAPPER_NO_CONTRACT; + MethodSecurityDescriptor methodSecurityDesc(pMD); + LookupOrCreateMethodSecurityDescriptor(&methodSecurityDesc); + return methodSecurityDesc.GetDeclaredPermissionsWithCache(action, pDeclaredPermissions, pPCE); +} + +// static +inline OBJECTREF MethodSecurityDescriptor::GetLinktimePermissions(MethodDesc* pMD, + OBJECTREF *prefNonCasDemands) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + if (!pMD->RequiresLinktimeCheck()) + return NULL; + + MethodSecurityDescriptor methodSecurityDesc(pMD); + LookupOrCreateMethodSecurityDescriptor(&methodSecurityDesc); + return methodSecurityDesc.GetTokenDeclActionInfo()->GetLinktimePermissions(prefNonCasDemands); +} + +inline void MethodSecurityDescriptor::InvokeLinktimeChecks(Assembly* pCaller) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + if (!HasLinktimeDeclarativeSecurity()) + return; + + GetTokenDeclActionInfo()->InvokeLinktimeChecks(pCaller); +} + +// staitc +inline void MethodSecurityDescriptor::InvokeLinktimeChecks(MethodDesc* pMD, Assembly* pCaller) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + if (!pMD->RequiresLinktimeCheck()) + return; + + MethodSecurityDescriptor methodSecurityDesc(pMD); + LookupOrCreateMethodSecurityDescriptor(&methodSecurityDesc); + methodSecurityDesc.InvokeLinktimeChecks(pCaller); +} + +// static +inline BOOL MethodSecurityDescriptor::IsDeclSecurityCASDemandsOnly(DWORD dwMethDeclFlags, + mdToken _mdToken, + IMDInternalImport *pInternalImport) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + +#ifdef FEATURE_CORECLR + // Non-CAS demands are not supported in CoreCLR + return TRUE; +#else + GCX_COOP(); + + PsetCacheEntry *tokenSetIndexes[dclMaximumValue + 1]; + SecurityDeclarative::DetectDeclActionsOnToken(_mdToken, dwMethDeclFlags, tokenSetIndexes, pInternalImport); + SecurityProperties sp(dwMethDeclFlags); + if (!sp.FDemandsOnly()) + return FALSE; + + DWORD dwLocalAction; + bool builtInCASPermsOnly = true; + for (dwLocalAction = 0; dwLocalAction <= dclMaximumValue && builtInCASPermsOnly; dwLocalAction++) + { + if (tokenSetIndexes[dwLocalAction] != NULL) + { + builtInCASPermsOnly = builtInCASPermsOnly && (tokenSetIndexes[dwLocalAction]->ContainsBuiltinCASPermsOnly(dwLocalAction)); + } + } + + return (builtInCASPermsOnly); // we only get here if there are only demands...so it suffices to return this value directly +#endif +} + +#ifndef DACCESS_COMPILE + +inline MethodSecurityDescriptor::MethodSecurityDescriptorTransparencyEtwEvents::MethodSecurityDescriptorTransparencyEtwEvents(const MethodSecurityDescriptor *pMSD) + : m_pMSD(pMSD) +{ + WRAPPER_NO_CONTRACT; + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, MethodTransparencyComputationStart)) + { + LPCWSTR module = m_pMSD->m_pMD->GetModule()->GetPathForErrorMessages(); + + SString method; + m_pMSD->m_pMD->GetFullMethodInfo(method); + + ETW::SecurityLog::FireMethodTransparencyComputationStart(method.GetUnicode(), + module, + ::GetAppDomain()->GetId().m_dwId); + } +} + +inline MethodSecurityDescriptor::MethodSecurityDescriptorTransparencyEtwEvents::~MethodSecurityDescriptorTransparencyEtwEvents() +{ + WRAPPER_NO_CONTRACT; + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, MethodTransparencyComputationEnd)) + { + LPCWSTR module = m_pMSD->m_pMD->GetModule()->GetPathForErrorMessages(); + + SString method; + m_pMSD->m_pMD->GetFullMethodInfo(method); + + BOOL fIsCritical = FALSE; + BOOL fIsTreatAsSafe = FALSE; + + if (m_pMSD->m_pMD->HasCriticalTransparentInfo()) + { + fIsCritical = m_pMSD->m_pMD->IsCritical(); + fIsTreatAsSafe = m_pMSD->m_pMD->IsTreatAsSafe(); + } + + ETW::SecurityLog::FireMethodTransparencyComputationEnd(method.GetUnicode(), + module, + ::GetAppDomain()->GetId().m_dwId, + fIsCritical, + fIsTreatAsSafe); + } +} + +#endif //!DACCESS_COMPILE + +inline FieldSecurityDescriptorFlags operator|(FieldSecurityDescriptorFlags lhs, + FieldSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<FieldSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); +} + +inline FieldSecurityDescriptorFlags operator|=(FieldSecurityDescriptorFlags& lhs, + FieldSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<FieldSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); + return lhs; +} + +inline FieldSecurityDescriptorFlags operator&(FieldSecurityDescriptorFlags lhs, + FieldSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<FieldSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); +} + +inline FieldSecurityDescriptorFlags operator&=(FieldSecurityDescriptorFlags& lhs, + FieldSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<FieldSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); + return lhs; +} + +inline FieldSecurityDescriptor::FieldSecurityDescriptor(FieldDesc* pFD) : + m_pFD(pFD), + m_flags(FieldSecurityDescriptorFlags_None) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(pFD); +} + +inline BOOL FieldSecurityDescriptor::IsCritical() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & FieldSecurityDescriptorFlags_IsCritical); +} + +inline BOOL FieldSecurityDescriptor::IsTreatAsSafe() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & FieldSecurityDescriptorFlags_IsTreatAsSafe); +} + +#ifndef DACCESS_COMPILE + +inline FieldSecurityDescriptor::FieldSecurityDescriptorTransparencyEtwEvents::FieldSecurityDescriptorTransparencyEtwEvents(const FieldSecurityDescriptor *pFSD) + : m_pFSD(pFSD) +{ + WRAPPER_NO_CONTRACT; + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FieldTransparencyComputationStart)) + { + LPCWSTR module = m_pFSD->m_pFD->GetModule()->GetPathForErrorMessages(); + + SString field; + TypeString::AppendType(field, TypeHandle(m_pFSD->m_pFD->GetApproxEnclosingMethodTable())); + field.AppendUTF8("::"); + field.AppendUTF8(m_pFSD->m_pFD->GetName()); + + ETW::SecurityLog::FireFieldTransparencyComputationStart(field.GetUnicode(), + module, + ::GetAppDomain()->GetId().m_dwId); + } +} + +inline FieldSecurityDescriptor::FieldSecurityDescriptorTransparencyEtwEvents::~FieldSecurityDescriptorTransparencyEtwEvents() +{ + WRAPPER_NO_CONTRACT; + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FieldTransparencyComputationEnd)) + { + LPCWSTR module = m_pFSD->m_pFD->GetModule()->GetPathForErrorMessages(); + + SString field; + TypeString::AppendType(field, TypeHandle(m_pFSD->m_pFD->GetApproxEnclosingMethodTable())); + field.AppendUTF8("::"); + field.AppendUTF8(m_pFSD->m_pFD->GetName()); + + ETW::SecurityLog::FireFieldTransparencyComputationEnd(field.GetUnicode(), + module, + ::GetAppDomain()->GetId().m_dwId, + !!(m_pFSD->m_flags & FieldSecurityDescriptorFlags_IsCritical), + !!(m_pFSD->m_flags & FieldSecurityDescriptorFlags_IsTreatAsSafe)); + } +} + +#endif //!DACCESS_COMPILE + +inline TypeSecurityDescriptor::TypeSecurityDescriptor(MethodTable *pMT) : + m_pMT(pMT->GetCanonicalMethodTable()), + m_pTokenDeclActionInfo(NULL), + m_fIsComputed(FALSE) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(pMT); +} + +inline BOOL TypeSecurityDescriptor::HasLinkOrInheritanceDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return HasLinktimeDeclarativeSecurity() || HasInheritanceDeclarativeSecurity(); +} + +inline BOOL TypeSecurityDescriptor::HasLinktimeDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return m_pMT->GetClass()->RequiresLinktimeCheck(); +} + +inline BOOL TypeSecurityDescriptor::HasInheritanceDeclarativeSecurity() +{ + WRAPPER_NO_CONTRACT; + return m_pMT->GetClass()->RequiresInheritanceCheck(); +} + +inline BOOL TypeSecurityDescriptor::IsCritical() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + EEClass *pClass = m_pMT->GetClass(); + if (!pClass->HasCriticalTransparentInfo()) + { + ComputeCriticalTransparentInfo(); + } + + return pClass->IsAllCritical() +#ifndef FEATURE_CORECLR + || pClass->IsCritical() +#endif // !FEATURE_CORECLR + ; +} + +inline BOOL TypeSecurityDescriptor::IsOpportunisticallyCritical() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + ModuleSecurityDescriptor *pModuleSecDesc = ModuleSecurityDescriptor::GetModuleSecurityDescriptor(m_pMT->GetAssembly()); + return pModuleSecDesc->IsOpportunisticallyCritical(); +} + +inline BOOL TypeSecurityDescriptor::IsAllCritical() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + EEClass *pClass = m_pMT->GetClass(); + if (!pClass->HasCriticalTransparentInfo()) + ComputeCriticalTransparentInfo(); + return pClass->IsAllCritical(); +} + +inline BOOL TypeSecurityDescriptor::IsAllTransparent() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + EEClass *pClass = m_pMT->GetClass(); + if (!pClass->HasCriticalTransparentInfo()) + ComputeCriticalTransparentInfo(); + return pClass->IsAllTransparent(); +} + +inline BOOL TypeSecurityDescriptor::IsTreatAsSafe() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + EEClass *pClass = m_pMT->GetClass(); + if (!pClass->HasCriticalTransparentInfo()) + ComputeCriticalTransparentInfo(); + return pClass->IsTreatAsSafe(); +} + +inline mdToken TypeSecurityDescriptor::GetToken() +{ + WRAPPER_NO_CONTRACT; + return m_pMT->GetCl(); +} + +inline IMDInternalImport *TypeSecurityDescriptor::GetIMDInternalImport() +{ + WRAPPER_NO_CONTRACT; + return m_pMT->GetMDImport(); +} + +inline TokenDeclActionInfo* TypeSecurityDescriptor::GetTokenDeclActionInfo() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return m_pTokenDeclActionInfo; +} + +inline TypeSecurityDescriptorFlags operator|(TypeSecurityDescriptorFlags lhs, + TypeSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<TypeSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); +} + +inline TypeSecurityDescriptorFlags operator|=(TypeSecurityDescriptorFlags& lhs, + TypeSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<TypeSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); + return lhs; +} + +inline TypeSecurityDescriptorFlags operator&(TypeSecurityDescriptorFlags lhs, + TypeSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<TypeSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); +} + +inline TypeSecurityDescriptorFlags operator&=(TypeSecurityDescriptorFlags& lhs, + TypeSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<TypeSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); + return lhs; +} + +inline HRESULT TypeSecurityDescriptor::GetDeclaredPermissionsWithCache(IN CorDeclSecurity action, + OUT OBJECTREF *pDeclaredPermissions, + OUT PsetCacheEntry **pPCE) +{ + WRAPPER_NO_CONTRACT; + return GetTokenDeclActionInfo()->GetDeclaredPermissionsWithCache(action, pDeclaredPermissions, pPCE); +} + +// static +inline HRESULT TypeSecurityDescriptor::GetDeclaredPermissionsWithCache(MethodTable *pTargetMT, + IN CorDeclSecurity action, + OUT OBJECTREF *pDeclaredPermissions, + OUT PsetCacheEntry **pPCE) +{ + WRAPPER_NO_CONTRACT; + TypeSecurityDescriptor* pTypeSecurityDesc = GetTypeSecurityDescriptor(pTargetMT); + _ASSERTE(pTypeSecurityDesc != NULL); + return pTypeSecurityDesc->GetDeclaredPermissionsWithCache(action, pDeclaredPermissions, pPCE); +} + +// static +inline OBJECTREF TypeSecurityDescriptor::GetLinktimePermissions(MethodTable *pMT, + OBJECTREF *prefNonCasDemands) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + if (!pMT->GetClass()->RequiresLinktimeCheck()) + return NULL; + + TypeSecurityDescriptor* pTypeSecurityDesc = GetTypeSecurityDescriptor(pMT); + _ASSERTE(pTypeSecurityDesc != NULL); + return pTypeSecurityDesc->GetTokenDeclActionInfo()->GetLinktimePermissions(prefNonCasDemands); +} + +inline void TypeSecurityDescriptor::InvokeLinktimeChecks(Assembly* pCaller) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + if (!HasLinktimeDeclarativeSecurity()) + return; + GetTokenDeclActionInfo()->InvokeLinktimeChecks(pCaller); +} + +// Determine if the type by this TypeSecurityDescriptor is participating in type equivalence. Note that this +// is only checking to see if the type would like to participate in equivalence, and not if it is actually +// equivalent to anything - which allows its transparency to be the same regardless of what other types have +// been loaded. +inline BOOL TypeSecurityDescriptor::IsTypeEquivalent() +{ + WRAPPER_NO_CONTRACT; + + return m_pMT->GetClass()->IsEquivalentType(); +} + +// static +inline void TypeSecurityDescriptor::InvokeLinktimeChecks(MethodTable *pMT, Assembly* pCaller) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + if (!pMT->GetClass()->RequiresLinktimeCheck()) + return; + GetTypeSecurityDescriptor(pMT)->InvokeLinktimeChecks(pCaller); +} + +inline void TypeSecurityDescriptor::VerifyDataComputed() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + if (m_fIsComputed) + { + return; + } + + BOOL canTypeSecDescCached = CanTypeSecurityDescriptorBeCached(m_pMT); + if (!canTypeSecDescCached) + { + VerifyDataComputedInternal(); + } + else + { + TypeSecurityDescriptor* pCachedTypeSecurityDesc = GetTypeSecurityDescriptor(m_pMT); + *this = *pCachedTypeSecurityDesc; // copy the struct + _ASSERTE(m_fIsComputed); + } + + return; +} + +inline TypeSecurityDescriptor& TypeSecurityDescriptor::operator=(const TypeSecurityDescriptor &tsd) +{ + LIMITED_METHOD_CONTRACT; + + m_pMT = tsd.m_pMT; + m_pTokenDeclActionInfo = tsd.m_pTokenDeclActionInfo; + m_fIsComputed = tsd.m_fIsComputed; + + return *this; +} + +#ifndef DACCESS_COMPILE + +inline TypeSecurityDescriptor::TypeSecurityDescriptorTransparencyEtwEvents::TypeSecurityDescriptorTransparencyEtwEvents(const TypeSecurityDescriptor *pTSD) + : m_pTSD(pTSD) +{ + WRAPPER_NO_CONTRACT; + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TypeTransparencyComputationStart)) + { + LPCWSTR module = m_pTSD->m_pMT->GetModule()->GetPathForErrorMessages(); + + SString type; + if (!IsNilToken(m_pTSD->m_pMT->GetCl())) + { + TypeString::AppendType(type, TypeHandle(m_pTSD->m_pMT)); + } + + ETW::SecurityLog::FireTypeTransparencyComputationStart(type.GetUnicode(), + module, + ::GetAppDomain()->GetId().m_dwId); + } + +} + +inline TypeSecurityDescriptor::TypeSecurityDescriptorTransparencyEtwEvents::~TypeSecurityDescriptorTransparencyEtwEvents() +{ + WRAPPER_NO_CONTRACT; + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TypeTransparencyComputationEnd)) + { + LPCWSTR module = m_pTSD->m_pMT->GetModule()->GetPathForErrorMessages(); + + SString type; + if (!IsNilToken(m_pTSD->m_pMT->GetCl())) + { + TypeString::AppendType(type, TypeHandle(m_pTSD->m_pMT)); + } + + BOOL fIsAllCritical = FALSE; + BOOL fIsAllTransparent = FALSE; + BOOL fIsCritical = FALSE; + BOOL fIsTreatAsSafe = FALSE; + + EEClass *pClass = m_pTSD->m_pMT->GetClass(); + if (pClass->HasCriticalTransparentInfo()) + { + fIsAllCritical = pClass->IsAllCritical(); + fIsAllTransparent = pClass->IsAllTransparent(); + fIsCritical = pClass->IsCritical(); + fIsTreatAsSafe = pClass->IsTreatAsSafe(); + } + + ETW::SecurityLog::FireTypeTransparencyComputationEnd(type.GetUnicode(), + module, + ::GetAppDomain()->GetId().m_dwId, + fIsAllCritical, + fIsAllTransparent, + fIsCritical, + fIsTreatAsSafe); + } + +} + +#endif //!DACCESS_COMPILE + +inline ModuleSecurityDescriptorFlags operator|(ModuleSecurityDescriptorFlags lhs, + ModuleSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<ModuleSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); +} + +inline ModuleSecurityDescriptorFlags operator|=(ModuleSecurityDescriptorFlags& lhs, + ModuleSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<ModuleSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); + return lhs; +} + +inline ModuleSecurityDescriptorFlags operator&(ModuleSecurityDescriptorFlags lhs, + ModuleSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<ModuleSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); +} + +inline ModuleSecurityDescriptorFlags operator&=(ModuleSecurityDescriptorFlags& lhs, + ModuleSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<ModuleSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); + return lhs; +} + +inline ModuleSecurityDescriptorFlags operator~(ModuleSecurityDescriptorFlags flags) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<ModuleSecurityDescriptorFlags>(~static_cast<DWORD>(flags)); +} + +inline ModuleSecurityDescriptor::ModuleSecurityDescriptor(PTR_Module pModule) : + m_pModule(pModule), + m_flags(ModuleSecurityDescriptorFlags_None), + m_tokenFlags(TokenSecurityDescriptorFlags_None) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(pModule); +} + +// static +inline BOOL ModuleSecurityDescriptor::IsMarkedTransparent(Assembly* pAssembly) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + return GetModuleSecurityDescriptor(pAssembly)->IsAllTransparent(); +} + +//--------------------------------------------------------------------------------------- +// +// Override the token flags that would be read from the metadata directly with a +// precomputed set of flags. This is used by reflection emit to create a dynamic assembly +// with security attributes given at creation time. +// + +inline void ModuleSecurityDescriptor::OverrideTokenFlags(TokenSecurityDescriptorFlags tokenFlags) +{ + CONTRACTL + { + LIMITED_METHOD_CONTRACT; + PRECONDITION(!(m_flags & ModuleSecurityDescriptorFlags_IsComputed)); + PRECONDITION(m_tokenFlags == TokenSecurityDescriptorFlags_None); + PRECONDITION(CheckPointer(m_pModule)); + PRECONDITION(m_pModule->GetAssembly()->IsDynamic()); // Token overrides should only be used by reflection + } + CONTRACTL_END; + + m_tokenFlags = tokenFlags; +} + +inline TokenSecurityDescriptorFlags ModuleSecurityDescriptor::GetTokenFlags() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + SO_INTOLERANT; + } + CONTRACTL_END; + + if (m_tokenFlags == TokenSecurityDescriptorFlags_None) + { + Assembly *pAssembly = m_pModule->GetAssembly(); + TokenSecurityDescriptor tsd(pAssembly->GetManifestModule(), pAssembly->GetManifestToken()); + EnsureWritablePages(&m_tokenFlags); + InterlockedCompareExchange(reinterpret_cast<LONG *>(&m_tokenFlags), + tsd.GetFlags(), + TokenSecurityDescriptorFlags_None); + } + + return m_tokenFlags; +} + +inline Module *ModuleSecurityDescriptor::GetModule() +{ + LIMITED_METHOD_CONTRACT; + return m_pModule; +} + +#ifdef DACCESS_COMPILE +inline ModuleSecurityDescriptorFlags ModuleSecurityDescriptor::GetRawFlags() +{ + LIMITED_METHOD_CONTRACT; + return m_flags; +} +#endif // DACCESS_COMPILE + +inline BOOL ModuleSecurityDescriptor::IsAllTransparent() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_IsAllTransparent); +} + +inline BOOL ModuleSecurityDescriptor::IsAllCritical() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_IsAllCritical); +} + +inline BOOL ModuleSecurityDescriptor::IsTreatAsSafe() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_IsTreatAsSafe); +} + +inline BOOL ModuleSecurityDescriptor::IsOpportunisticallyCritical() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_IsOpportunisticallyCritical); +} + +inline BOOL ModuleSecurityDescriptor::IsAllTransparentDueToPartialTrust() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_TransparentDueToPartialTrust); +} + +inline BOOL ModuleSecurityDescriptor::IsMixedTransparency() +{ + WRAPPER_NO_CONTRACT; + return !IsAllCritical() && !IsAllTransparent(); +} + +#ifndef FEATURE_CORECLR + +inline BOOL ModuleSecurityDescriptor::CanTransparentCodeSkipVerification() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_SkipFullTrustVerification); +} + +#endif // !FEATURE_CORECLR + +#if defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) +inline BOOL ModuleSecurityDescriptor::IsAPTCA() +{ + WRAPPER_NO_CONTRACT; + VerifyDataComputed(); + return !!(m_flags & ModuleSecurityDescriptorFlags_IsAPTCA); +} +#endif // defined(FEATURE_APTCA) || defined(FEATURE_CORESYSTEM) + +// Get the set of security rules that the assembly is using +inline SecurityRuleSet ModuleSecurityDescriptor::GetSecurityRuleSet() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + // If the assembly specified a rule set, then use that. If it's a v2 assembly, then use the v2 rules. + // Otherwise, use the default rule set. + TokenSecurityDescriptorFlags tokenFlags = GetTokenFlags(); + if (tokenFlags & TokenSecurityDescriptorFlags_SecurityRules) + { + return ::GetSecurityRuleSet(tokenFlags); + } +#ifndef FEATURE_CORECLR + else if (AssemblyVersionRequiresLegacyTransparency()) + { + return SecurityRuleSet_Level1; + } +#endif // !FEATURE_CORECLR + else + { + // The assembly hasn't specified the rule set that it needs to use. We'll just use the default rule + // set unless the environment is overriding that with another value. + DWORD dwDefaultRuleSet = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_Security_DefaultSecurityRuleSet); + + if (dwDefaultRuleSet == 0) + { + return SecurityRuleSet_Default; + } + else + { + return static_cast<SecurityRuleSet>(dwDefaultRuleSet); + } + } +} + +#ifndef DACCESS_COMPILE + +inline ModuleSecurityDescriptor::ModuleSecurityDescriptorTransparencyEtwEvents::ModuleSecurityDescriptorTransparencyEtwEvents(ModuleSecurityDescriptor *pMSD) + : m_pMSD(pMSD) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + } + CONTRACTL_END + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, ModuleTransparencyComputationStart)) + { + LPCWSTR module = m_pMSD->m_pModule->GetPathForErrorMessages(); + + ETW::SecurityLog::FireModuleTransparencyComputationStart(module, + ::GetAppDomain()->GetId().m_dwId); + } +} + +inline ModuleSecurityDescriptor::ModuleSecurityDescriptorTransparencyEtwEvents::~ModuleSecurityDescriptorTransparencyEtwEvents() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + } + CONTRACTL_END + + if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, ModuleTransparencyComputationEnd)) + { + LPCWSTR module = m_pMSD->m_pModule->GetPathForErrorMessages(); + + ETW::SecurityLog::FireModuleTransparencyComputationEnd(module, + ::GetAppDomain()->GetId().m_dwId, + !!(m_pMSD->m_flags & ModuleSecurityDescriptorFlags_IsAllCritical), + !!(m_pMSD->m_flags & ModuleSecurityDescriptorFlags_IsAllTransparent), + !!(m_pMSD->m_flags & ModuleSecurityDescriptorFlags_IsTreatAsSafe), + !!(m_pMSD->m_flags & ModuleSecurityDescriptorFlags_IsOpportunisticallyCritical), + m_pMSD->GetSecurityRuleSet()); + } +} + +#endif //!DACCESS_COMPILE + +inline MethodSecurityDescriptorFlags operator|(MethodSecurityDescriptorFlags lhs, + MethodSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<MethodSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); +} + +inline MethodSecurityDescriptorFlags operator|=(MethodSecurityDescriptorFlags& lhs, + MethodSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<MethodSecurityDescriptorFlags>(static_cast<DWORD>(lhs) | + static_cast<DWORD>(rhs)); + return lhs; +} + +inline MethodSecurityDescriptorFlags operator&(MethodSecurityDescriptorFlags lhs, + MethodSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + return static_cast<MethodSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); +} + +inline MethodSecurityDescriptorFlags operator&=(MethodSecurityDescriptorFlags& lhs, + MethodSecurityDescriptorFlags rhs) +{ + LIMITED_METHOD_CONTRACT; + lhs = static_cast<MethodSecurityDescriptorFlags>(static_cast<DWORD>(lhs) & + static_cast<DWORD>(rhs)); + return lhs; +} + +inline void MethodSecurityDescriptor::VerifyDataComputed() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + if (m_flags & MethodSecurityDescriptorFlags_IsComputed) + return; + + BOOL canMethSecDescCached = (CanCache() && CanMethodSecurityDescriptorBeCached(m_pMD)); + if (!canMethSecDescCached) + { + VerifyDataComputedInternal(); + } + else + { + LookupOrCreateMethodSecurityDescriptor(this); + _ASSERTE(m_flags & MethodSecurityDescriptorFlags_IsComputed); + } + + return; +} + +#endif // __SECURITYMETA_INL__ |