How to Build APIs with Transparency in Mind – #17

June 23rd 2009 06:08 am

In the .NET Framework there are a few types which expose both "safe" and "unsafe" equivalents of the same method. Both methods achieve the same goal e.g. BinaryFormatter.Deserialize and BinaryFormatter.UnsafeDeserialize will both deserialize a stream into a .NET object, but the safe variant will do a full Demand for the appropriate permissions. This ensures that callers without proper permissions will fail when trying to call the safe method. The unsafe variant, on the other hand, ensures only that the immediate caller has the necessary permissions. Previous versions of the .NET Framework enforce these invariants with Demands and LinkDemands, as shown in the example below. (Note that this isn’t exactly what you’ll see for these methods in the BinaryFormatter class if you examine them in Reflector, but the permission Demand and LinkDemand are present.)

[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]

public object Deserialize(Stream serializationStream)

{

   return this.UnsafeDeserialize(serializationStream);

}

 

[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]

public object UnsafeDeserialize(Stream serializationStream)

{

    // Method body

}

The reason for the two different versions is that a permission Demand is expensive because it has to check the permissions of every frame in the call stack. If you know that you aren’t introducing a security hole by calling an unsafe method, then you can skip the permission Demand and avoid the performance hit.

In .NET 4 under the Level 2 security rules, LinkDemands have been replaced by the SecurityCriticalAttribute, which means the UnsafeDeserialize will look similar to this.

[SecurityCritical]

public object UnsafeDeserialize(Stream serializationStream)

{

    // Method body

}

Methods annotated with LinkDemands should migrate to use the SecurityCriticalAttribute because the whole purpose of security transparency is to promote this kind of safe/unsafe API layering. When a method is decorated with the SecurityCriticalAttribute, the CLR ensures that no security transparent code can call that method. When you consider that all code running in partial trust is security transparent, the SecurityCriticalAttribute is effectively the same as a LinkDemand for full trust.

Be careful though! This API layering works for the .NET Framework because the assemblies are installed in the GAC and are therefore fully trusted, even in a partial trust sandbox. If the assembly you create is loaded into a partial trust sandbox but is not fully trusted, then the SecurityCriticalAttribute will not enforce anything. Remember, all partial trust code is security transparent, even code annotated with the SecurityCriticalAttribute.

Finally, if your assembly is not intended for partially trusted callers, then do you don’t need to worry about any of this. :)

Check out the .NET 4 documentation on Demands vs. LinkDemands for more information.

Posted by David DeWinter under .NET4/VS2010 & Security Tips | No Comments »

Trackback URI | Comments RSS

Leave a Reply