Internal Architecture

This section provides an overview of the SELinux security module internal architecture. The module code is located within the security/selinux subdirectory of the kernel tree. All subsequent pathnames in this section are relative to this subdirectory, unless otherwise noted. The module consists of five major components: the security server, the access vector cache (AVC), the persistent label mapping, the new system calls, and the hook function implementations.

The security server provides general interfaces for obtaining security policy decisions, enabling the rest of the module to remain independent of the specific security policies used. The specific implementation of the security server can be changed or completely replaced without requiring any changes to the rest of the module. The example security server provided with SELinux implements a combination of Role-Based Access Control (RBAC), a generalization of Type Enforcement (TE), and optionally Multi-Level Security (MLS). The RBAC and TE policies are highly configurable and can be used to meet many different security objectives. The example security server code can be found in the ss subdirectory. This code is largely unchanged from the original SELinux prototype, aside from some bug fixes, synchronization code, and preliminary devfs labeling support.

The AVC provides caching of access decision computations obtained from the security server to minimize the performance overhead of the SELinux security mechanisms. It provides interfaces to the hook functions for efficiently checking permissions and it provides interfaces to the security server for managing the cache. The AVC code can be found in the avc.c file. This code is also largely unchanged from the original SELinux prototype.

The persistent label mapping provides a mechanism for maintaining security contexts with persistent objects such as files and filesystems. It provides interfaces to the hook functions for getting and setting the security contexts for particular files. The persistent label mapping code can be found in the psid.c file. This code was derived from the original SELinux prototype, but was changed to store the inode-to-PSID mapping in a regular file rather than using a spare field in the on-disk inode, since LSM does not provide filesystem-specific hooks. This change should allow SELinux to support other filesystem types more easily, but has disadvantages in terms of performance and consistency. Additionally, several bug fixes were made and some new synchronization code was added.

The new system calls allow modified and new applications to be developed that have some degree of awareness of the new security features. One set of new calls is provided to allow applications to use the security server interfaces to obtain policy decisions for their own objects. The code for these calls can be found in the ss/syscalls.c file and is largely unchanged from the original SELinux prototype.

The other new system calls are typically extended forms of existing system calls that allow applications to obtain or specify security contexts for kernel objects or operations. The code for these calls can be found in the syscalls.c and include/asm-i386/flask/syscalls.c files. This code uses a different approach than the original SELinux prototype, which relied on the ability to generalize the existing internal kernel functions to support this functionality by directly patching it. The new code instead makes use of the existing system calls in combination with the ability to save state in the new security fields and the processing in the hook functions.

The hook function implementations manage the security information associated with kernel objects and perform the SELinux access controls for each kernel operation. The hook functions call the security server and access vector cache to obtain security policy decisions and apply those decisions to label and control kernel objects. The hook functions also call the persistent label mapping to obtain and set security contexts on files. The code for these hook functions is located in the file hooks.c, and the data structures for the security information associated with the kernel objects are defined in the file selinux_plug.h.

Abstractly, the hook function and data structure contents can be viewed as the same processing and data that was directly inserted into the kernel code and data structures by the original SELinux patch. However, in practice, it was often necessary to revisit the approach used by the original SELinux patch since the LSM hook locations did not always correspond to the insertion points of the original SELinux patch. In part, this was because the LSM project placed a heavier emphasis on minimizing hooks, especially outside of the core kernel code. For example, the lack of any filesystem-specific hooks required a different approach for labeling both persistent filesystems like ext2 and pseudo filesystems like procfs. Similarly, since LSM leverages the existing NetFilter framework to support hooking on many network operations, the implementation of the SELinux network access controls was changed. Nonetheless, it was possible to provide the desired security semantics with the LSM hooks.