The Process class has a LinkDemand and an InheritenceDemand for FullTrust on it. This means that if your assembly is not fully trusted, it will be unable to kick off new Processes or get information about running processes. One implication is that assemblies which do not have SkipVerification permission will not be able to work with this class. Normally that’s fine, since most partial trust assemblies will be coming from the Internet or Local Intranet zones. However, there are some cases where you want your assembly to have everything but SkipVerification.
One instance that you would want to be running without SkipVerification is the case where you’re dynamically generating code. Applications which emit code via Reflection.Emit should run without SkipVerification to help to ensure that they’re emitting correct code. Since you can’t Deny SkipVerification with the effects you’d want, the way most people go about achieving this goal is using a RequestRefuse for SkipVerification. In the dynamic assembly case, this leads you to the unintuitive way that the declarative security parameters are handled, which often means that the emitting assembly will be outfitted with a RequestRefuse for SkipVerification as well.
Now you’re in a position where you’re unable to use the Process class, even though the only reason you’re not running in FullTrust is that you wanted to ensure that your code generation logic is correct. How can you enable the Process scenario again?
The easiest pattern is to create an intermediate assembly, which is FullTrust and acts as a proxy to the Process class. This intermediate assembly would satisfy the LinkDemand, and allow its callers to use the features it’s wrapping. The danger here is that this assembly will need to be APTCA since the calling code will be partially trusted. Combine that with the fact that this assembly’s whole purpose in life is to remove a security check from some classes, and you’ve got an elevation of privilege issue waiting to happen. Obviously you want to prevent that, and a good first step is regulating acccess to the assembly. First of all, don’t put it into the GAC unless your design requires it — this limits the availability of the code to partial trust. Second, you should have the assembly demand some sort of permission in exchange for removing the FullTrust demand … for instance, you could have a LinkDemand for a StrongNameIdentityPermission that your application would be granted. (Note that we don’t care about FullTrust Means FullTrust here, since that only applies to FullTrust callers, and they have access to the wrapped code anyway.) Finally, you might consider making the assembly Transparent with the SecurityCritical attribute, and then explicitly marking the methods which wrap the FullTrust methods as being Critical. This prevents you from accidentally raising the call stack privileges where you didn’t mean to.
Although I focused on Process here (since it seems to be the most common FullTrust demand that people run into), this pattern applies to other FullTrust demands that you want to allow partial trust code access to.
- Wrap the FullTrust methods, using an Assert if you’re wrapping a full demand.
- Demand something from the calling assembly in exchange for removing the demand
- Make the assembly transparent, and only mark your elevation wrappers as critical
- Apply APTCA, but do not put the assembly in the GAC unless you have to