2 // InjectSecurityAttributes.cs
5 // Jb Evain (jbevain@novell.com)
7 // (C) 2009 Novell, Inc.
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
35 using Mono.Linker.Steps;
39 namespace Mono.Tuner {
41 public class InjectSecurityAttributes : BaseStep {
53 const string _safe_critical = "System.Security.SecuritySafeCriticalAttribute";
54 const string _critical = "System.Security.SecurityCriticalAttribute";
56 const string sec_attr_folder = "secattrs";
58 AssemblyDefinition _assembly;
60 MethodDefinition _safe_critical_ctor;
61 MethodDefinition _critical_ctor;
65 protected override bool ConditionToProcess ()
67 if (!Context.HasParameter (sec_attr_folder))
70 data_folder = Context.GetParameter (sec_attr_folder);
74 protected override void ProcessAssembly (AssemblyDefinition assembly)
76 if (Annotations.GetAction (assembly) != AssemblyAction.Link)
79 string secattr_file = Path.Combine (
81 assembly.Name.Name + ".secattr");
83 if (!File.Exists (secattr_file)) {
84 Console.Error.WriteLine ("Warning: file '{0}' not found, skipping.", secattr_file);
90 // remove existing [SecurityCritical] and [SecuritySafeCritical]
91 RemoveSecurityAttributes ();
93 // add [SecurityCritical] and [SecuritySafeCritical] from the data file
94 ProcessSecurityAttributeFile (secattr_file);
97 void RemoveSecurityAttributes ()
99 foreach (TypeDefinition type in _assembly.MainModule.Types) {
100 RemoveSecurityAttributes (type);
102 if (type.HasConstructors)
103 foreach (MethodDefinition ctor in type.Constructors)
104 RemoveSecurityAttributes (ctor);
107 foreach (MethodDefinition method in type.Methods)
108 RemoveSecurityAttributes (method);
112 static void RemoveSecurityDeclarations (IHasSecurity provider)
114 // also remove already existing CAS security declarations
116 if (provider == null)
119 if (!provider.HasSecurityDeclarations)
122 provider.SecurityDeclarations.Clear ();
125 static void RemoveSecurityAttributes (ICustomAttributeProvider provider)
127 RemoveSecurityDeclarations (provider as IHasSecurity);
129 if (!provider.HasCustomAttributes)
132 CustomAttributeCollection attributes = provider.CustomAttributes;
133 for (int i = 0; i < attributes.Count; i++) {
134 CustomAttribute attribute = attributes [i];
135 switch (attribute.Constructor.DeclaringType.FullName) {
138 attributes.RemoveAt (i--);
144 void ProcessSecurityAttributeFile (string file)
146 using (StreamReader reader = File.OpenText (file)) {
148 while ((line = reader.ReadLine ()) != null)
153 void ProcessLine (string line)
155 if (line == null || line.Length < 6)
158 int sep = line.IndexOf (": ");
162 string marker = line.Substring (0, sep);
163 string target = line.Substring (sep + 2);
165 ProcessSecurityAttributeEntry (
166 DecomposeAttributeType (marker),
167 DecomposeTargetKind (marker),
171 static AttributeType DecomposeAttributeType (string marker)
173 if (marker.StartsWith ("SC"))
174 return AttributeType.Critical;
175 else if (marker.StartsWith ("SSC"))
176 return AttributeType.SafeCritical;
178 throw new ArgumentException ();
181 static TargetKind DecomposeTargetKind (string marker)
183 switch (marker [marker.Length - 1]) {
185 return TargetKind.Type;
187 return TargetKind.Method;
189 throw new ArgumentException ();
193 void ProcessSecurityAttributeEntry (AttributeType type, TargetKind kind, string target)
195 ICustomAttributeProvider provider = GetTarget (kind, target);
196 if (provider == null)
200 case AttributeType.Critical:
201 AddCriticalAttribute (provider);
203 case AttributeType.SafeCritical:
204 AddSafeCriticalAttribute (provider);
209 void AddCriticalAttribute (ICustomAttributeProvider provider)
211 // a [SecurityCritical] replaces a [SecuritySafeCritical]
212 if (HasSecurityAttribute (provider, AttributeType.SafeCritical))
213 RemoveSecurityAttributes (provider);
215 AddSecurityAttribute (provider, AttributeType.Critical);
218 void AddSafeCriticalAttribute (ICustomAttributeProvider provider)
220 // a [SecuritySafeCritical] is ignored if a [SecurityCritical] is present
221 if (HasSecurityAttribute (provider, AttributeType.Critical))
224 AddSecurityAttribute (provider, AttributeType.SafeCritical);
227 void AddSecurityAttribute (ICustomAttributeProvider provider, AttributeType type)
229 if (HasSecurityAttribute (provider, type))
232 CustomAttributeCollection attributes = provider.CustomAttributes;
234 case AttributeType.Critical:
235 attributes.Add (CreateCriticalAttribute ());
237 case AttributeType.SafeCritical:
238 attributes.Add (CreateSafeCriticalAttribute ());
243 static bool HasSecurityAttribute (ICustomAttributeProvider provider, AttributeType type)
245 if (!provider.HasCustomAttributes)
248 foreach (CustomAttribute attribute in provider.CustomAttributes) {
249 switch (attribute.Constructor.DeclaringType.Name) {
251 if (type == AttributeType.Critical)
256 if (type == AttributeType.SafeCritical)
266 ICustomAttributeProvider GetTarget (TargetKind kind, string target)
269 case TargetKind.Type:
270 return GetType (target);
271 case TargetKind.Method:
272 return GetMethod (target);
274 throw new ArgumentException ();
278 TypeDefinition GetType (string fullname)
280 return _assembly.MainModule.Types [fullname];
283 MethodDefinition GetMethod (string signature)
285 int pos = signature.IndexOf (" ");
287 throw new ArgumentException ();
289 string tmp = signature.Substring (pos + 1);
291 pos = tmp.IndexOf ("::");
293 throw new ArgumentException ();
295 string type_name = tmp.Substring (0, pos);
297 int parpos = tmp.IndexOf ("(");
299 throw new ArgumentException ();
301 string method_name = tmp.Substring (pos + 2, parpos - pos - 2);
303 TypeDefinition type = GetType (type_name);
307 return method_name.StartsWith (".c") ?
308 GetMethod (type.Constructors, signature) :
309 GetMethod (type.Methods.GetMethod (method_name), signature);
312 static MethodDefinition GetMethod (IEnumerable methods, string signature)
314 foreach (MethodDefinition method in methods)
315 if (GetFullName (method) == signature)
321 static string GetFullName (MethodReference method)
323 int sentinel = method.GetSentinel ();
325 StringBuilder sb = new StringBuilder ();
326 sb.Append (method.ReturnType.ReturnType.FullName);
328 sb.Append (method.DeclaringType.FullName);
330 sb.Append (method.Name);
331 if (method.HasGenericParameters) {
333 for (int i = 0; i < method.GenericParameters.Count; i++ ) {
336 sb.Append (method.GenericParameters [i].Name);
341 if (method.HasParameters) {
342 for (int i = 0; i < method.Parameters.Count; i++) {
349 sb.Append (method.Parameters [i].ParameterType.FullName);
353 return sb.ToString ();
356 static MethodDefinition GetDefaultConstructor (TypeDefinition type)
358 foreach (MethodDefinition ctor in type.Constructors)
359 if (ctor.Parameters.Count == 0)
365 MethodDefinition GetSafeCriticalCtor ()
367 if (_safe_critical_ctor != null)
368 return _safe_critical_ctor;
370 _safe_critical_ctor = GetDefaultConstructor (Context.GetType (_safe_critical));
371 return _safe_critical_ctor;
374 MethodDefinition GetCriticalCtor ()
376 if (_critical_ctor != null)
377 return _critical_ctor;
379 _critical_ctor = GetDefaultConstructor (Context.GetType (_critical));
380 return _critical_ctor;
383 MethodReference Import (MethodDefinition method)
385 return _assembly.MainModule.Import (method);
388 CustomAttribute CreateSafeCriticalAttribute ()
390 return new CustomAttribute (Import (GetSafeCriticalCtor ()));
393 CustomAttribute CreateCriticalAttribute ()
395 return new CustomAttribute (Import (GetCriticalCtor ()));