3.1. The Kernel ArchitectureSELinux provides enhanced access control over all kernel resources. In its current form, SELinux is incorporated into the kernel via the LSM framework. 3.1.1. LSM FrameworkThe idea behind the LSM framework is to allow security modules to plug into the kernel that can further restrict the default Linux identity-based discretionary access control (DAC) security. LSM provides a set of hooks in the kernel system call logic. These hooks are usually placed after the standard Linux access checks but before the actual resource is accessed by the kernel on behalf of the caller. Figure 3-1 illustrates the basic LSM framework. Figure 3-1. LSM hook architecture[1]
SELinux is loaded into the kernel as an LSM module and is consulted for additional access validation before the access attempt is allowed. One of the ramifications of the LSM framework is that SELinux is consulted only if standard Linux access checks succeed. In practice, this has no negative affect on the access control policy because SELinux access control can be more restrictive than standard Linux DAC and not override the DAC decision. However, the LSM framework can affect the audit data collected by SELinux. For example, if you want to use the SELinux audit data to observe all access denials, be aware that in most cases SELinux will not be consulted, and therefore cannot audit, if the denial is a result of standard Linux security. The LSM framework is comprehensive, and the hooks are scattered throughout the kernel. Each LSM hook translates into one or more access permissions for one or more object classes. Understanding object access permissions in SELinux is in large part related to understanding the LSM hooks. Chapter 4, "Object Classes and Permissions," discusses object classes and permissions in detail. 3.1.2. SELinux LSM ModuleThe SELinux kernel architecture reflects the Flask architecture, which was designed for a microkernel environment. The Flask architecture has three primary components, as illustrated in Figure 3-2: security server, object managers, and the access vector cache. Figure 3-2. SELinux LSM module architectureThe Flask design makes a strong distinction between security policy decision making and enforcement functions. Policy decision making is the job of the security server. The name security server reflects SELinux's micorkenel roots, where the policy decision role was encapsulated in a userspace server. In Linux, the security server for kernel objects is located in the SELinux LSM module. The policy used for the security server is embodied in a set of rules that is loaded via the policy management interface. These rules can differ from system to system, making SELinux highly adaptable to various organizational security goals. The architecture is designed such that the security server could be completely replaced with logic that implements an entirely new access control policy without changing the rest of the architecture. In practice, new security servers are not needed because type enforcement provides sufficient flexibility for almost any access control security policy. Object managers are responsible for enforcing the policy decisions of the security server for the set of resources they manage. For the kernel, you can think of object managers as kernel subsystems that create and manage kernel-level objects. Examples of kernel object managers include the filesystem, process management, and System V interprocess communication (IPC). In the LSM architecture, the object managers are represented by the LSM hooks; these hooks are scattered throughout the kernel subsystems and call the SELinux LSM module for access decisions. The LSM hooks then enforce those decisions by allowing or denying access to the kernel resource. The third component of the SELinux architecture is the access vector cache (AVC). The AVC caches decisions made by the security server for subsequent access checks and thus provides significant performance improvements for access validation. The AVC also provides the SELinux interfaces for the LSM hooks and hence with the kernel object managers. The AVC is invalidated when a policy is loaded, thereby keeping the cache coherent. However, SELinux does not fully implement access revocation on policy change. This is no worse than standard Linux, which does not access revocation at all. In standard Linux, if you have a file descriptor, you can use it regardless of the change in file access mode. In SELinux, for objects such as files where access is validated on all attempts to use (for example, every read system call is checked against the policy and not just open calls), access revocation works fine. Just having a file descriptor does not mean access to the file will be granted. For some resources, however, such as memory mapped-files and connection-oriented sockets, access is validated only when the resource is initially accessed and not on subsequent use. In these cases, existing access is not revoked. We expect that there will be further research to improve access revocation in SELinux. |