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;
34 using Mono.Linker.Steps;
38 namespace Mono.Tuner {
40 public class InjectSecurityAttributes : BaseStep {
52 const string _safe_critical = "System.Security.SecuritySafeCriticalAttribute";
53 const string _critical = "System.Security.SecurityCriticalAttribute";
55 const string sec_attr_folder = "secattrs";
57 AssemblyDefinition _assembly;
59 MethodDefinition _safe_critical_ctor;
60 MethodDefinition _critical_ctor;
64 protected override bool ConditionToProcess ()
66 if (!Context.HasParameter (sec_attr_folder))
69 data_folder = Context.GetParameter (sec_attr_folder);
73 protected override void ProcessAssembly (AssemblyDefinition assembly)
75 if (Annotations.GetAction (assembly) != AssemblyAction.Link)
78 string secattr_file = Path.Combine (
80 assembly.Name.Name + ".secattr");
82 if (!File.Exists (secattr_file))
87 // remove existing [SecurityCritical] and [SecuritySafeCritical]
88 RemoveSecurityAttributes ();
90 // add [SecurityCritical] and [SecuritySafeCritical] from the data file
91 ProcessSecurityAttributeFile (secattr_file);
94 void RemoveSecurityAttributes ()
96 foreach (TypeDefinition type in _assembly.MainModule.Types) {
97 RemoveSecurityAttributes (type);
99 if (type.HasConstructors)
100 foreach (MethodDefinition ctor in type.Constructors)
101 RemoveSecurityAttributes (ctor);
104 foreach (MethodDefinition method in type.Methods)
105 RemoveSecurityAttributes (method);
109 static void RemoveSecurityAttributes (ICustomAttributeProvider provider)
111 if (!provider.HasCustomAttributes)
114 CustomAttributeCollection attributes = provider.CustomAttributes;
115 for (int i = 0; i < attributes.Count; i++) {
116 CustomAttribute attribute = attributes [i];
117 switch (attribute.Constructor.DeclaringType.FullName) {
120 attributes.RemoveAt (i--);
126 void ProcessSecurityAttributeFile (string file)
128 using (StreamReader reader = File.OpenText (file)) {
130 while ((line = reader.ReadLine ()) != null)
135 void ProcessLine (string line)
137 if (line == null || line.Length < 6)
140 int sep = line.IndexOf (": ");
144 string marker = line.Substring (0, sep);
145 string target = line.Substring (sep + 2);
147 ProcessSecurityAttributeEntry (
148 DecomposeAttributeType (marker),
149 DecomposeTargetKind (marker),
153 static AttributeType DecomposeAttributeType (string marker)
155 if (marker.StartsWith ("SC"))
156 return AttributeType.Critical;
157 else if (marker.StartsWith ("SSC"))
158 return AttributeType.SafeCritical;
160 throw new ArgumentException ();
163 static TargetKind DecomposeTargetKind (string marker)
165 switch (marker [marker.Length - 1]) {
167 return TargetKind.Type;
169 return TargetKind.Method;
171 throw new ArgumentException ();
175 void ProcessSecurityAttributeEntry (AttributeType type, TargetKind kind, string target)
177 ICustomAttributeProvider provider = GetTarget (kind, target);
178 if (provider == null)
182 case AttributeType.Critical:
183 AddCriticalAttribute (provider);
185 case AttributeType.SafeCritical:
186 AddSafeCriticalAttribute (provider);
191 void AddCriticalAttribute (ICustomAttributeProvider provider)
193 // a [SecurityCritical] replaces a [SecuritySafeCritical]
194 if (HasSecurityAttribute (provider, AttributeType.SafeCritical))
195 RemoveSecurityAttributes (provider);
197 AddSecurityAttribute (provider, AttributeType.Critical);
200 void AddSafeCriticalAttribute (ICustomAttributeProvider provider)
202 // a [SecuritySafeCritical] is ignored if a [SecurityCritical] is present
203 if (HasSecurityAttribute (provider, AttributeType.Critical))
206 AddSecurityAttribute (provider, AttributeType.SafeCritical);
209 void AddSecurityAttribute (ICustomAttributeProvider provider, AttributeType type)
211 if (HasSecurityAttribute (provider, type))
214 CustomAttributeCollection attributes = provider.CustomAttributes;
216 case AttributeType.Critical:
217 attributes.Add (CreateCriticalAttribute ());
219 case AttributeType.SafeCritical:
220 attributes.Add (CreateSafeCriticalAttribute ());
225 static bool HasSecurityAttribute (ICustomAttributeProvider provider, AttributeType type)
227 if (!provider.HasCustomAttributes)
230 foreach (CustomAttribute attribute in provider.CustomAttributes) {
231 switch (attribute.Constructor.DeclaringType.Name) {
233 if (type == AttributeType.Critical)
238 if (type == AttributeType.SafeCritical)
248 ICustomAttributeProvider GetTarget (TargetKind kind, string target)
251 case TargetKind.Type:
252 return GetType (target);
253 case TargetKind.Method:
254 return GetMethod (target);
256 throw new ArgumentException ();
260 TypeDefinition GetType (string fullname)
262 return _assembly.MainModule.Types [fullname];
265 MethodDefinition GetMethod (string signature)
267 int pos = signature.IndexOf (" ");
269 throw new ArgumentException ();
271 string tmp = signature.Substring (pos + 1);
273 pos = tmp.IndexOf ("::");
275 throw new ArgumentException ();
277 string type_name = tmp.Substring (0, pos);
279 int parpos = tmp.IndexOf ("(");
281 throw new ArgumentException ();
283 string method_name = tmp.Substring (pos + 2, parpos - pos - 2);
285 TypeDefinition type = GetType (type_name);
289 return method_name.StartsWith (".c") ?
290 GetMethod (type.Constructors, signature) :
291 GetMethod (type.Methods.GetMethod (method_name), signature);
294 static MethodDefinition GetMethod (IEnumerable methods, string signature)
296 foreach (MethodDefinition method in methods)
297 if (method.ToString () == signature)
303 static MethodDefinition GetDefaultConstructor (TypeDefinition type)
305 foreach (MethodDefinition ctor in type.Constructors)
306 if (ctor.Parameters.Count == 0)
312 MethodDefinition GetSafeCriticalCtor ()
314 if (_safe_critical_ctor != null)
315 return _safe_critical_ctor;
317 _safe_critical_ctor = GetDefaultConstructor (Context.GetType (_safe_critical));
318 return _safe_critical_ctor;
321 MethodDefinition GetCriticalCtor ()
323 if (_critical_ctor != null)
324 return _critical_ctor;
326 _critical_ctor = GetDefaultConstructor (Context.GetType (_critical));
327 return _critical_ctor;
330 MethodReference Import (MethodDefinition method)
332 return _assembly.MainModule.Import (method);
335 CustomAttribute CreateSafeCriticalAttribute ()
337 return new CustomAttribute (Import (GetSafeCriticalCtor ()));
340 CustomAttribute CreateCriticalAttribute ()
342 return new CustomAttribute (Import (GetCriticalCtor ()));