Why is my application coughing up a SecurityException after my code stops running?

Odd exceptions at odd times

If you apply a PrincipalPermission attribute to a class in order to restrict the users and/or roles that are permitted to use the class, you may start seeing security exceptions like the following being thrown at unexpected times (like, say, when your application is quitting):

System.Security.SecurityException was unhandled
Message=”Request for principal permission failed.”
at System.Security.Permissions.PrincipalPermission.ThrowSecurityException()
at System.Security.Permissions.PrincipalPermission.Demand()
at System.Security.PermissionSet.DemandNonCAS()
at YourNamespace.YourClass.Finalize()

What’s up with that?

The basic gist of the above exception that the demand for your specified PrincipalPermission is failing when the finalizer for your class is invoked. If your class also happens to be disposable, and disposition suppresses its finalization, you might be tempted to believe that this problem occurs because the thread principal couldn’t satisfy the original PrincipalPermission demand at construction. However, things are a wee bit more complicated than that…

Finalization is triggered by the garbage collector and runs on a separate thread controlled by the garbage collector. This means that the principal that you set on your application’s thread won’t be applied to the thread on which an instance of your finalizable type gets finalized. Your PrincipalPermission demand will always fail at finalization, regardless of the thread principal set within your application.

Another surprise might be that there’s an object available for finalization at all if the PrincipalPermission demand fails when the constructor is invoked. What you actually end up with in such a case is a partially constructed instance of your type. This instance won’t be available to the invoking code, so it won’t be subject to disposition, but the garbage collector will still attempt to finalize it despite the fact that it isn’t fully constructed.

So what can I do about all this?

The simple answer is you need to make it possible for the finalizer (and any other methods it calls) to run despite the fact that the finalizer thread cannot satisfy the class-level PrincipalPermission demand. You can do this by applying a PrincipalPermission attribute that allows unauthenticated callers to the finalizer (and any methods it calls). The C# form of this attribute would be:

[PrincipalPermission(SecurityAction.Demand, Authenticated = false)]

The VB form would be:

<PrincipalPermission(SecurityAction.Demand, Authenticated:=False)>

Obviously, if you’re going to be removing the requirement for the class-level PrincipalPermission from the finalizer or any other methods, you should also ensure that these methods don’t perform any actions that should require whatever user identity or role membership specified by the original PrincipalPermission.

You may want to also consider applying the same PrincipalPermission reversal on any methods used for disposition, even if these are not invoked from your finalizer. (This would be a bit of an odd design choice in most cases, but if that’s what you’re using, you should be addressing the consequences.) The main reason for this is that disposition might not be invoked under the same principal as was in place at construction. As with finalization, you should ensure that your disposition methods don’t perform any “high-privilege” actions if you do choose to reverse the PrincipalPermission requirement.

If that was the simple answer…

The good news is that the above approach is pretty much the only approach. It’s reasonably clear-cut, and there’s not much that you can do in terms of variation on the theme. The bad news is that, if you’re running into this particular problem, chances are pretty good that you should perhaps be concerned about some of the finer details of finalization and disposition. If you’re interested in learning more about these, I’d recommend reading Chris Brumme’s blog entry on finalization. If you’re implementing disposition as well as a finalizer, you should probably take a look at the recommended disposition pattern, and maybe even the whitepaper on .NET Framework Resource Management.

Leave a Reply

Your email address will not be published. Required fields are marked *