|
The host protection categories are defined by the HostProtectionResource enumeration from the System.Security.Permissions namespace: [Flags, Serializable] public enum HostProtectionResource { None = 0x0, Synchronization = 0x1, SharedState = 0x2, ExternalProcessMgmt = 0x4, SelfAffectingProcessMgmt = 0x8, ExternalThreading = 0x10, SelfAffectingThreading = 0x20, SecurityInfrastructure = 0x40, UI = 0x80, MayLeakOnAbort = 0x100, All = 0x1ff, } Given that host protection has initially been designed with SQL Server 2005 in mind, the best way to understand the motivation behind the host protection categories is to think of them in the context of the SQL Server programming model. Two aspects of the SQL Server programming model drove the definition of these categories: reliability and scalability. Recall from Chapter 11 that the basis of the CLR's reliability design in .NET Framework 2.0 is the ability to shut down an application domain without leaking any resources, so one of the host protection categories (MayLeakOnAbort) is used to annotate code that cannot be guaranteed to free all resources when an application domain is unloaded. In addition, many of the host protection categories are aimed at preventing an add-in from inadvertently limiting the scalability of the host process. The SQL Server scheduler is highly tuned toward providing the highest degree of scalability possible. Any attempts by an add-in to block synchronizing access to shared state, or to affect how threads behave in the process, can limit the ability of SQL Server to scale. SQL Server add-ins such as user-defined types and stored procedures that are written in native code (using the T-SQL programming language) don't have the ability to perform operations that limit scalability in this way. Many of the host protection categories are designed to ensure that SQL Server add-ins written in managed code don't have those capabilities either. The next several sections describe the individual host protection categories in detail. For each category, I describe the motivation for the category and the characteristics of the .NET Framework APIs that belong to that category. Each section also includes a full list of the .NET Framework APIs that belong to the particular category. SynchronizationThe synchronization host protection category includes APIs that allow an add-in to synchronize access to a particular resource explicitly across multiple threads. For example, many of the collection classes in the System.Collections namespace have a method called Synchronized that returns an instance of the collection to which only one thread can have access at a time. In addition, the System.Threading namespace includes several types that can be used to create and hold various types of operating system locks such as mutexes and semaphores. Synchronizing access to a resource means that at least one thread must wait if multiple threads are trying to access the resource simultaneously. Waiting on a resource limits scalability and should be avoided when possible in scenarios requiring high throughput. Hosts can block access to the APIs in the synchronization category to prevent an add-in from limiting scalability by waiting for access to a resource. In addition, synchronization can also hurt both scalability and reliability by causing the host to terminate an entire application domain instead of just an individual thread. Chapter 11 discusses how a host can specify policy that will cause the CLR to unload an entire application domain when a thread that is holding a lock receives a ThreadAbortException, for example. The set of .NET Framework APIs that belongs to the synchronization host protection category is listed in Table 12-1.
Shared StateThe sharing of state between threads is related to synchronization in that access to the shared state must be synchronized for that state to remain consistent, so the shared state host protection category exists for many of the same reasons that the synchronization category does. The most obvious example of an API that allows you to share state between threads is the AllocDataSlot (and related) APIs on System.Threading.Thread. These APIs essentially provide a managed-code view of the thread local store feature of Win32. The complete set of APIs in the shared state category is listed in Table 12-2.
External Process ManagementThe external process management category contains APIs that add-ins can use to manipulate processes other than the host process itself. The APIs in this category can't affect the integrity or the reliability of the host process specifically, but they can have an indirect effect through the ability to create and manipulate other processes on the system. For example, SQL Server runs best when it is one of just a few processes on a system and it can therefore take advantage of the majority of the system's resources, including memory. The presence of many other processes competing for the same resources can adversely affect SQL Server performance. The Process class in the System.Diagnostics namespace is a great example of a class that can be used to affect other processes. Process has methods that allow an add-in to create and kill processes, interact with processes through the standard input and output streams, and so on. Table 12-3 lists the types in the external process management category.
Self-Affecting Process ManagementWhereas the APIs in the external process management category cannot affect the host's process directly, the APIs in the self-affecting process management category can, so the APIs in this category can directly affect the stability of the host. The APIs in the self-affecting process management category are all in the System.Diagnostics namespace and are all either on the Process class or its relatives. The self-affecting process APIs allow an add-in to affect characteristics of the host process, including its priority and the processor affinity of threads running in the process. The full list of self-affecting process APIs is given in Table 12-4.
Self-Affecting ThreadingWhereas the APIs in the self-affecting process management category can directly affect various aspects of the host's process, the APIs in the self-affecting threading category can affect specific threads running within the host process. Examples of APIs in this category are those on System.Threading.Thread that allow a thread's priority to be altered, its COM apartment state to be set, and so on. As I mentioned in the beginning of this chapter, the line between which APIs are blocked using CAS and which are blocked using host protection can often be blurry. For example, the System.Threading.Thread.Abort method can clearly be used to affect the threads in a process, so you'd expect Abort to be annotated with HostProtectionAttribute, identifying it as belonging to the self-affecting threading category. It is not, however. Instead, to be called, Abort demands a CAS permission (SecurityPermission.ControlThread). In this particular case, Abort was not annotated with HostProtectionAttribute because it already has a CAS demand. There are many cases in which a method or type that was protected using CAS wasn't annotated with HostProtectionAttribute even though it logically belonged to one of the host protection categories, so a host must use a combination of CAS, as described in Chapter 10, and host protection to ensure that no inappropriate APIs can be used in the process. The list of APIs in the self-affecting threading category is given in Table 12-5.
External ThreadingThe external threading category contains those APIs that can affect threads in the host process but cannot directly impact the host's stability. In most cases, the external threading APIs are those that allow an add-in to start an asynchronous operation such as reading from a network socket or a file. Many of the types in the System.Threading namespace are also included in the external threading category, as shown in Table 12-6.
Security InfrastructureThere are only two types in the security infrastructure host protection category, as shown in Table 12-7. These types allow an add-in to manipulate different aspects of the underlying Windows security system, including how impersonation is done and how security principals are managed.
User InterfaceThe number of types and methods in the user interface category is surprisingly small given the breadth of UI-related class libraries in the .NET Framework. There are two reasons for this. First, many of the types that allow the display of user interface are already protected by CAS permissions. In many cases, those types have not been annotated with HostProtectionAttribute as well. Also, recall that only the .NET Framework assemblies that SQL Server 2005 allows in its process have been annotated with the HostProtectionAttribute. This automatically eliminates System. Windows.Forms, one of the primary class libraries for building applications with user interfaces. As it stands in .NET Framework 2.0, only the user interfacerelated classes in the System.Console class are included in the user interface host protection category, as shown in Table 12-8.
"May Leak on Abort"As discussed in Chapter 11, the ability to unload an application domain without leaking any resources is a core concept in the CLR's design to provide a system that can execute predictably in scenarios requiring high availability. The "may leak on abort" host protection category is used to identify those types and methods that are not guaranteed to be leakproof when an application domain is unloaded. A type or method can leak resources if it doesn't adhere to the guidelines for writing reliable managed code that were outlined in Chapter 11. For example, if a type maintains a handle to an operating system resource without wrapping it using the SafeHandle class, the CLR cannot guarantee that the handle will not be leaked in all abort and shutdown scenarios. Hosts should be aware that they must block the "may leak on abort" host protection category if they require a highly available system. The list of methods and types that can leak resources on abort or shutdown is given in Table 12-9.
|
|