File: Linker.Steps\RemoveSecurityStep.cs
Web Access
Project: src\src\tools\illink\src\linker\Mono.Linker.csproj (illink)
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
using System.Linq;
using Mono.Cecil;
 
namespace Mono.Linker.Steps
{
	public static class RemoveSecurity
	{
		public static void ProcessAssembly (AssemblyDefinition assembly, LinkContext context)
		{
			if (context.Annotations.GetAction (assembly) == AssemblyAction.Link) {
				ClearSecurityDeclarations (assembly);
				RemoveCustomAttributesThatAreForSecurity (assembly);
 
				RemoveCustomAttributesThatAreForSecurity (assembly.MainModule);
 
				foreach (var type in assembly.MainModule.Types)
					ProcessType (type);
			}
		}
 
		static void ProcessType (TypeDefinition type)
		{
			ClearSecurityDeclarations (type);
			RemoveCustomAttributesThatAreForSecurity (type);
			type.HasSecurity = false;
 
			foreach (var field in type.Fields)
				RemoveCustomAttributesThatAreForSecurity (field);
 
			foreach (var method in type.Methods) {
				ClearSecurityDeclarations (method);
				RemoveCustomAttributesThatAreForSecurity (method);
				method.HasSecurity = false;
			}
 
			foreach (var nested in type.NestedTypes)
				ProcessType (nested);
		}
 
		static void ClearSecurityDeclarations (ISecurityDeclarationProvider provider)
		{
			if (provider.HasSecurityDeclarations)
				provider.SecurityDeclarations.Clear ();
		}
 
		/// <summary>
		/// We have to remove some security attributes, otherwise pe verify will complain that a type has HasSecurity = false
		/// </summary>
		/// <param name="provider"></param>
		static void RemoveCustomAttributesThatAreForSecurity (ICustomAttributeProvider provider)
		{
			if (!provider.HasCustomAttributes)
				return;
 
			var attrsToRemove = provider.CustomAttributes.Where (IsCustomAttributeForSecurity).ToArray ();
			foreach (var remove in attrsToRemove)
				provider.CustomAttributes.Remove (remove);
		}
 
		static bool IsCustomAttributeForSecurity (CustomAttribute attr)
		{
			var attr_type = attr.AttributeType;
			if (attr_type.Namespace == "System.Security") {
				switch (attr_type.Name) {
				case "SecurityCriticalAttribute":
				case "SecuritySafeCriticalAttribute":
				case "SuppressUnmanagedCodeSecurityAttribute":
				case "DynamicSecurityMethodAttribute":
				case "UnverifiableCodeAttribute":
				case "AllowPartiallyTrustedCallersAttribute":
				case "SecurityTransparentAttribute":
				case "SecurityRulesAttribute":
					return true;
				}
			}
 
			return false;
		}
	}
}