Customizing the Microsoft .NET Framework Common Language Runtime

In Chapter 8, I wrote a CLR host called runcocoon.exe that executes applications contained in OLE-structured storage files called cocoons. In this section, I extend runcocoon.exe to use host protection to prevent the assemblies contained in cocoon files from using any of the .NET Framework APIs that are annotated with HostProtectionAttribute. Remember that only partially trusted assemblies are prevented from accessing members blocked by host protection, so the extensions I made to runcocoon.exe in Chapter 10 apply here as well. In that chapter, I used an application domain CAS policy tree to assign a partial level of trust to all assemblies loaded from a cocoon. Because those assemblies are only partially trusted, they're subject to the host protection settings I'll add to runcocoon.exe in this section. I won't list the entire source for the runcocoon.exe host again here. Instead, I'll just provide those portions of the implementation that are specific to host protection. A complete source code listing can be found on this book's companion Web site.

Enabling host protection in runcocoon.exe requires two steps:

1.

Obtaining the ICLRHostProtectionManager interface from the CLR

2.

Using SetProtectedCategories to specify which categories to block

These two steps are described in more detail in the next sections.

Step 1: Obtaining the ICLRHostProtectionManager Interface Pointer

As described in Chapter 2, all of the primary hosting interfaces implemented by the CLR are obtained using the GetCLRManager method on ICLRControl. The following code snippet initializes the CLR with CorBindToRuntimeEx, and then uses ICLRControl::GetCLRManager to get the CLR's implementation of ICLRHostProtectionManager:

int wmain(int argc, wchar_t* argv[]) { HRESULT hr = S_OK; // Start the .NET Framework 2.0 version of the CLR ICLRRuntimeHost *pCLR = NULL; hr = CorBindToRuntimeEx( L"v2.0.41013", L"wks", STARTUP_CONCURRENT_GC, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*) &pCLR); assert(SUCCEEDED(hr)); // Get the CLRControl object. ICLRControl *pCLRControl = NULL; hr = pCLR->GetCLRControl(&pCLRControl); assert(SUCCEEDED(hr)); // Ask the CLR for its implementation of ICLRHostProtectionManager. ICLRHostProtectionManager *pCLRHostProtectionManager = NULL; hr = pCLRControl->GetCLRManager(IID_ICLRHostProtectionManager, (void **)&pCLRHostProtectionManager); assert(SUCCEEDED(hr)); // Rest of the host's code omitted... }

Step 2: Specifying Which Host Protection Categories to Block

Now that I have a pointer of type ICLRHostProtectionManager, I simply need to call its SetProtectedCategories method to specify which categories I'd like to block. The following call to SetProtectedCategories blocks the full set of host protection categories:

// Block all host protection categories. hr = pCLRHostProtectionManager->SetProtectedCategories ( (EApiCategories)( eSelfAffectingProcessMgmt | eSelfAffectingThreading | eSynchronization | eSharedState | eExternalProcessMgmt | eExternalThreading | eSelfAffectingProcessMgmt | eSelfAffectingThreading | eSecurityInfrastructure | eMayLeakOnAbort | eUI)); assert(SUCCEEDED(hr));

Now that I've enabled host protection, all attempts by cocoon assemblies to access protected APIs will result in an exception of type System.Security.HostProtectionException. The HostProtectionException has fields that describe which categories the host has blocked and which category contains the method that caused the exception to be thrown. For example, the following exception text resulted from a cocoon assembly attempting to call Console.WriteLine, which belongs to the UI host protection category:

System.Security.HostProtectionException: Attempted to perform an operation that was forbidden by the CLR host. The protected resources (only available with full trust) were: All The demanded resources were: UI

Note

Just as host protection and CAS appear similar on the surface, their implementations are very similar as well. The fact that HostProtectionAttribute is in the System.Security.Permissions namespace and that HostProtectionException is in System.Security gives a clear hint that their underlying implementations are very similar to CAS. In fact, both host protection and demands for CAS permissions are implemented using the same infrastructure within the CLR. When a host enables host protection using ICLRHostProtectionManager, the CLR introduces a link demand for a permission of type System.Security.Permissions.HostProtectionPermission into the code that is jit-compiled for each protected method. The failure of this link demand is what causes the HostProtectionException to be thrown.

    Категории