Every CLR has Independent CAS Policy

It’s relatively easy to find a set of instructions for using caspol or Admin UI to provide a CAS elevation for some managed code that’s hitting security exceptions. However, using the directions correctly gets complicated when multiple runtimes are on the machine. The reason is that each CLR has its own set of policy levels, and none of the runtimes look at the previous policy levels when making trust decisions.

This can bite you in the obvious way, for instance using the v1.1 caspol to trust an application, but the application runs against the v2.0 CLR. And it can bite in non-obvious ways; such as making a trust decision in the 32 bit v2.0 CLR, but having the application run against the 64 bit v2.0 CLR.

Most applications are going to float forward to the newest runtime on the machine, such as any managed application without a configuration file locking it to a specific runtime, or any application being invoked via COM interop. This means that installing a new runtime on the machine may have the effect of losing the trust decisions you’ve made for previous versions.

(Incidentally, if you’re writing a runtime host, this confusion is reason #5 to choose the simple sandboxing model vs the legacy AppDomain policy model)

If you need to know which CLR a process is using so that you can make the trust decision on the correct runtime, one way is to use a tool like Process Explorer or windbg to examine the modules loaded in the application. Check the path that mscorwks.dll or mscorsvr.dll is being loaded from – and that will point you at the CLR which is executing the application:

0:000> sxe ld mscorwks
0:000> g
ModLoad: 000007ff`7fee0000 000007ff`7ffe5000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 000007ff`7fd30000 000007ff`7fed9000 C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 000007ff`7ef60000 000007ff`7effb000 C:\WINDOWS\system32\SHLWAPI.dll
ModLoad: 000007ff`7fc90000 000007ff`7fd29000 C:\WINDOWS\system32\GDI32.dll
ModLoad: 00000000`78c30000 00000000`78d3c000 C:\WINDOWS\system32\USER32.dll
ModLoad: 000007ff`7fc00000 000007ff`7fc86000 C:\WINDOWS\system32\msvcrt.dll
ModLoad: 000007ff`7d320000 000007ff`7d359000 C:\WINDOWS\system32\IMM32.DLL
ModLoad: 000007ff`692e0000 000007ff`692ed000 C:\WINDOWS\system32\LPK.DLL
ModLoad: 000007ff`78cc0000 000007ff`78d4a000 C:\WINDOWS\system32\USP10.dll
ModLoad: 00000642`7f330000 00000642`7fd1d000 C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
ntdll!NtMapViewOfSection+0xa:
00000000`78ef14ea c3 ret
0:000> lm v m mscorwks
start end module name
00000642`7f330000 00000642`7fd1d000 mscorwks (deferred)
Image path: C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
Image name: mscorwks.dll
Timestamp: Fri Sep 23 02:17:48 2005 (4333C83C)
CheckSum: 009DA0C0
ImageSize: 009ED000
File version: 2.0.50727.42
Product version: 2.0.50727.42
File flags: 0 (Mask 3F)
File OS: 4 Unknown Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft® .NET Framework
InternalName: mscorwks.dll
OriginalFilename: mscorwks.dll
ProductVersion: 2.0.50727.42
FileVersion: 2.0.50727.42 (RTM.050727-4200)
FileDescription: Microsoft .NET Runtime Common Language Runtime - WorkStation
LegalCopyright: © Microsoft Corporation. All rights reserved.
Comments: Flavor=Retail

Of course, if you control the code, you can always insert a call to System.Environment.Version to get the currently loaded runtime.