Silverlight Security II: What Makes a Method Critical
Yesterday we talked about the CoreCLR security model, and how it is built upon the transparency model introduced in the v2.0 .NET Framework. The quick summary was that all Silverlight application code is transparent, and transparent code may only call other transparent code and safe critical code. With that in mind, lets take a look at figuring out how can tell which platform APIs fall into each category ... allowing us to know which APIs our applications are allowed to call.
In Silverlight, by default all code is transparent. (This is different from the desktop CLR, where all code is critical by default). For application code, that's the end of the story -- as we said yesterday, a fundamental tenant of the CoreCLR security model is that all application code is transparent.
Platform code can be either transparent, safe critical, or critical however. CoreCLR will detect platform code by knowing where the assembly is loaded from (platform assemblies must be loaded from the Silverlight installation directory), and also by checking the assembly's public key. Only assemblies signed with specific Microsoft's public keys will be considered platform assemblies; because of this public key requirement, no Silverlight application code can ever be considered a platform assembly.
We can tell if a method is security critical or transparent by looking at the attributes on the method in question (and on the class that contains the method). To simplify this discussion, I'll talk directly about attributes on methods, however if the class containing the method has one of the security attributes, then this attribute will apply to every method within the class.
If a method in a platform assembly is marked with the SecurityCriticalAttribute, this means that it contains critical code. Even if the method is public, no application code can call it since transparent code may never directly call into critical code. Any attempt to break this rule will lead to a MethodAccessException at runtime.
For example, the constructor for FileStream in the Silverlight 1.1 alpha bits (snipped below) is security critical which we can see from the SecurityCriticalAttribute on line 5:
1 .method public hidebysig specialname rtspecialname
2 instance void .ctor(string path,
3 valuetype System.IO.FileMode mode) cil managed
4 {
5 .custom instance void System.Security.SecurityCriticalAttribute::.ctor() = ( 01 00 00 00 )
6
7 // ...
8 }
Similarly, every method in the Marshal class is also critical, since the entire class is marked with the SecurityCriticalAttribute on line 4:
1 .class public abstract auto ansi sealed beforefieldinit System.Runtime.InteropServices.Marshal
2 extends System.Object
3 {
4 .custom instance void System.Security.SecurityCriticalAttribute::.ctor() = ( 01 00 00 00 )
5
6 // ...
7 } // end of class System.Runtime.InteropServices.Marshal
A method in a platform assembly marked with the SecuritySafeCriticalAttribute is, of course, safe critical. Application code may call into these methods, since transparent code may call safe critical code. And since safe critical code is critical, it can then turn around and call critical APIs on behalf of the application.
One example of a safe critical API is the IsolatedStorageFileStream.Write, which we can see on line 6 of its disassembly:
1 .method public hidebysig virtual instance void
2 Write(uint8[] buffer,
3 int32 offset,
4 int32 count) cil managed
5 {
6 .custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 )
7
8 // ...
9 }
An interesting note is that the SecuritySafeCriticalAttribute is really just a combination of the desktop framework's SecurityCriticalAttribute and SecurityTreatAsSafeAttribute. If you're familiar with the desktop CLR's transparency model, then you'll know that the TreatAsSafe attribute is implied for all public critical methods. This is not true in the CoreCLR security model for Silverlight -- instead, safe critical methods must be explicitly marked.
Since there are no more implicit treat as safe methods, the need to explicitly annotate a method with both the SecurityCritical and the SecurityTreatAsSafe attributes became much more common, so SecuritySafeCritical was introduced as a shortcut; it saves time when typing and also reduces metadata size. However, if you are familiar with the desktop CLR transparency model, it's safe to read "SecuritySafeCritical" as "SecurityCritical, SecurityTreatAsSafe" when reasoning about an API set.
If a method has neither the SecurityCritical attribute nor the SecuritySafeCritical attribute applied to it, then the method must be transparent (since we said above that all code is transparent by default). If this method is visible to the application code, that means that the application can call into it because transparent code is always allowed to call other transparent code.
Incidentally, if a Silverlight application tries to be tricky and mark itself with one of the SecurityCritical or SecuritySafeCritical attributes nothing will happen. The CLR knows that application code must be transparent, so it doesn't even bother to look for those two attributes when examining a method from a non-platform assembly. Instead, the method with the disallowed attributes will continue to be treated as transparent, and if they try to do anything that is not allowed from a transparent method, an exception will be thrown.
Finally, it's important to note that these rules do not replace the standard public / private / protected / internal access rules for the runtime; instead they supplement them. So application code may not call an internal method in a platform assembly, even if the method is transparent.
To summarize:
Security Attribute | Means | Directly callable by application code(if the method is visible) | |
Application Code | - | Transparent | Yes |
Platform | None | Transparent | Yes |
Platform | SecuritySafeCritical | Safe critical | Yes |
Platform | SecurityCritical | Critical | No |
Next time, we'll look at how this security model interacts with inheritance.
Comments
Anonymous
May 10, 2007
Shawn continues his yesterday post with a new one that explains why you might get a MethodAccessExceptionAnonymous
May 10, 2007
Today at MIX07 we announced the availability of Microsoft Silverlight 1.1 Alpha, a cross-browser, cross-platformAnonymous
May 10, 2007
...transparent code may only call other transparent code and critical code. shouldn't that be "safe critical code" ? p.s. Keep the good stuff coming :)Anonymous
May 10, 2007
Why yes it should :-) Thanks! -ShawnAnonymous
May 11, 2007
Over the last few days we've looked at the basics of the CoreCLR security model in Silverlight , andAnonymous
May 12, 2007
Is there a list of safe critical APIs somewhere handy? Is it similar to the (default) range of APIs that are available to .NET 2.0 controls hosted in internet explorer?Anonymous
May 14, 2007
Over the last week we took a look at the new Silverlight security model. When you're writing a SilverlightAnonymous
May 14, 2007
Hi Max, Yep, you're right on the mark there. What we tried to do when making our first cut at what APIs would be transparent and safe critical was to expose things which were available in the Internet permission set on v2.0 of the framework. -ShawnAnonymous
May 14, 2007
The Silverlight Security Model Silverlight Security II: What Makes a Method Critical Silverlight Security...Anonymous
June 05, 2007
a {color : #0033CC;} a:link {color: #0033CC;} a:visited.local {color: #0033CC;} a:visited {color : #800080;}Anonymous
August 30, 2009
Hi, The security model has been explained rightly. What I need to know is how we can use SecuritySafeCritical code, like if i need to do like accessing a file for readonly purposes : FileInfo fi = new FileInfo("some_file"); NadeemAnonymous
November 05, 2009
Hi Nadeem, In Silverlight, there is no way for your user application to use critical code or contain safe critical code. The Silverlight sandbox does not allow extension in this way, so you will not be able to write a Silverlight application that opens arbitrary files. -ShawnAnonymous
February 14, 2010
Has this changed with the options in SL4 to run "Out of Browser" and with "Elevated Trust"Anonymous
February 24, 2010
Hi Adriaan, Good question. Nope - none of this has changed for SL4 out of browser applications. Those applications are still entirely transparent from a security point of view. Instead, we've exposed additional SecuritySafeCritical APIs that do a check against the AppDomain to see if they are allowed (for instance, the File IO APIs now do an AppDomain check instead of simply being security critical). If the AppDomain is running out of browser, then it will be setup to accept those requests and they will succeed. -Shawn