| ======================================================== | |
| Linux Security Modules: General Security Hooks for Linux | |
| ======================================================== | |
| :Author: Stephen Smalley | |
| :Author: Timothy Fraser | |
| :Author: Chris Vance | |
| .. note:: | |
| The APIs described in this book are outdated. | |
| Introduction | |
| ============ | |
| In March 2001, the National Security Agency (NSA) gave a presentation | |
| about Security-Enhanced Linux (SELinux) at the 2.5 Linux Kernel Summit. | |
| SELinux is an implementation of flexible and fine-grained | |
| nondiscretionary access controls in the Linux kernel, originally | |
| implemented as its own particular kernel patch. Several other security | |
| projects (e.g. RSBAC, Medusa) have also developed flexible access | |
| control architectures for the Linux kernel, and various projects have | |
| developed particular access control models for Linux (e.g. LIDS, DTE, | |
| SubDomain). Each project has developed and maintained its own kernel | |
| patch to support its security needs. | |
| In response to the NSA presentation, Linus Torvalds made a set of | |
| remarks that described a security framework he would be willing to | |
| consider for inclusion in the mainstream Linux kernel. He described a | |
| general framework that would provide a set of security hooks to control | |
| operations on kernel objects and a set of opaque security fields in | |
| kernel data structures for maintaining security attributes. This | |
| framework could then be used by loadable kernel modules to implement any | |
| desired model of security. Linus also suggested the possibility of | |
| migrating the Linux capabilities code into such a module. | |
| The Linux Security Modules (LSM) project was started by WireX to develop | |
| such a framework. LSM is a joint development effort by several security | |
| projects, including Immunix, SELinux, SGI and Janus, and several | |
| individuals, including Greg Kroah-Hartman and James Morris, to develop a | |
| Linux kernel patch that implements this framework. The patch is | |
| currently tracking the 2.4 series and is targeted for integration into | |
| the 2.5 development series. This technical report provides an overview | |
| of the framework and the example capabilities security module provided | |
| by the LSM kernel patch. | |
| LSM Framework | |
| ============= | |
| The LSM kernel patch provides a general kernel framework to support | |
| security modules. In particular, the LSM framework is primarily focused | |
| on supporting access control modules, although future development is | |
| likely to address other security needs such as auditing. By itself, the | |
| framework does not provide any additional security; it merely provides | |
| the infrastructure to support security modules. The LSM kernel patch | |
| also moves most of the capabilities logic into an optional security | |
| module, with the system defaulting to the traditional superuser logic. | |
| This capabilities module is discussed further in | |
| `LSM Capabilities Module <#cap>`__. | |
| The LSM kernel patch adds security fields to kernel data structures and | |
| inserts calls to hook functions at critical points in the kernel code to | |
| manage the security fields and to perform access control. It also adds | |
| functions for registering and unregistering security modules, and adds a | |
| general :c:func:`security()` system call to support new system calls | |
| for security-aware applications. | |
| The LSM security fields are simply ``void*`` pointers. For process and | |
| program execution security information, security fields were added to | |
| :c:type:`struct task_struct <task_struct>` and | |
| :c:type:`struct linux_binprm <linux_binprm>`. For filesystem | |
| security information, a security field was added to :c:type:`struct | |
| super_block <super_block>`. For pipe, file, and socket security | |
| information, security fields were added to :c:type:`struct inode | |
| <inode>` and :c:type:`struct file <file>`. For packet and | |
| network device security information, security fields were added to | |
| :c:type:`struct sk_buff <sk_buff>` and :c:type:`struct | |
| net_device <net_device>`. For System V IPC security information, | |
| security fields were added to :c:type:`struct kern_ipc_perm | |
| <kern_ipc_perm>` and :c:type:`struct msg_msg | |
| <msg_msg>`; additionally, the definitions for :c:type:`struct | |
| msg_msg <msg_msg>`, struct msg_queue, and struct shmid_kernel | |
| were moved to header files (``include/linux/msg.h`` and | |
| ``include/linux/shm.h`` as appropriate) to allow the security modules to | |
| use these definitions. | |
| Each LSM hook is a function pointer in a global table, security_ops. | |
| This table is a :c:type:`struct security_operations | |
| <security_operations>` structure as defined by | |
| ``include/linux/security.h``. Detailed documentation for each hook is | |
| included in this header file. At present, this structure consists of a | |
| collection of substructures that group related hooks based on the kernel | |
| object (e.g. task, inode, file, sk_buff, etc) as well as some top-level | |
| hook function pointers for system operations. This structure is likely | |
| to be flattened in the future for performance. The placement of the hook | |
| calls in the kernel code is described by the "called:" lines in the | |
| per-hook documentation in the header file. The hook calls can also be | |
| easily found in the kernel code by looking for the string | |
| "security_ops->". | |
| Linus mentioned per-process security hooks in his original remarks as a | |
| possible alternative to global security hooks. However, if LSM were to | |
| start from the perspective of per-process hooks, then the base framework | |
| would have to deal with how to handle operations that involve multiple | |
| processes (e.g. kill), since each process might have its own hook for | |
| controlling the operation. This would require a general mechanism for | |
| composing hooks in the base framework. Additionally, LSM would still | |
| need global hooks for operations that have no process context (e.g. | |
| network input operations). Consequently, LSM provides global security | |
| hooks, but a security module is free to implement per-process hooks | |
| (where that makes sense) by storing a security_ops table in each | |
| process' security field and then invoking these per-process hooks from | |
| the global hooks. The problem of composition is thus deferred to the | |
| module. | |
| The global security_ops table is initialized to a set of hook functions | |
| provided by a dummy security module that provides traditional superuser | |
| logic. A :c:func:`register_security()` function (in | |
| ``security/security.c``) is provided to allow a security module to set | |
| security_ops to refer to its own hook functions, and an | |
| :c:func:`unregister_security()` function is provided to revert | |
| security_ops to the dummy module hooks. This mechanism is used to set | |
| the primary security module, which is responsible for making the final | |
| decision for each hook. | |
| LSM also provides a simple mechanism for stacking additional security | |
| modules with the primary security module. It defines | |
| :c:func:`register_security()` and | |
| :c:func:`unregister_security()` hooks in the :c:type:`struct | |
| security_operations <security_operations>` structure and | |
| provides :c:func:`mod_reg_security()` and | |
| :c:func:`mod_unreg_security()` functions that invoke these hooks | |
| after performing some sanity checking. A security module can call these | |
| functions in order to stack with other modules. However, the actual | |
| details of how this stacking is handled are deferred to the module, | |
| which can implement these hooks in any way it wishes (including always | |
| returning an error if it does not wish to support stacking). In this | |
| manner, LSM again defers the problem of composition to the module. | |
| Although the LSM hooks are organized into substructures based on kernel | |
| object, all of the hooks can be viewed as falling into two major | |
| categories: hooks that are used to manage the security fields and hooks | |
| that are used to perform access control. Examples of the first category | |
| of hooks include the :c:func:`alloc_security()` and | |
| :c:func:`free_security()` hooks defined for each kernel data | |
| structure that has a security field. These hooks are used to allocate | |
| and free security structures for kernel objects. The first category of | |
| hooks also includes hooks that set information in the security field | |
| after allocation, such as the :c:func:`post_lookup()` hook in | |
| :c:type:`struct inode_security_ops <inode_security_ops>`. | |
| This hook is used to set security information for inodes after | |
| successful lookup operations. An example of the second category of hooks | |
| is the :c:func:`permission()` hook in :c:type:`struct | |
| inode_security_ops <inode_security_ops>`. This hook checks | |
| permission when accessing an inode. | |
| LSM Capabilities Module | |
| ======================= | |
| The LSM kernel patch moves most of the existing POSIX.1e capabilities | |
| logic into an optional security module stored in the file | |
| ``security/capability.c``. This change allows users who do not want to | |
| use capabilities to omit this code entirely from their kernel, instead | |
| using the dummy module for traditional superuser logic or any other | |
| module that they desire. This change also allows the developers of the | |
| capabilities logic to maintain and enhance their code more freely, | |
| without needing to integrate patches back into the base kernel. | |
| In addition to moving the capabilities logic, the LSM kernel patch could | |
| move the capability-related fields from the kernel data structures into | |
| the new security fields managed by the security modules. However, at | |
| present, the LSM kernel patch leaves the capability fields in the kernel | |
| data structures. In his original remarks, Linus suggested that this | |
| might be preferable so that other security modules can be easily stacked | |
| with the capabilities module without needing to chain multiple security | |
| structures on the security field. It also avoids imposing extra overhead | |
| on the capabilities module to manage the security fields. However, the | |
| LSM framework could certainly support such a move if it is determined to | |
| be desirable, with only a few additional changes described below. | |
| At present, the capabilities logic for computing process capabilities on | |
| :c:func:`execve()` and :c:func:`set\*uid()`, checking | |
| capabilities for a particular process, saving and checking capabilities | |
| for netlink messages, and handling the :c:func:`capget()` and | |
| :c:func:`capset()` system calls have been moved into the | |
| capabilities module. There are still a few locations in the base kernel | |
| where capability-related fields are directly examined or modified, but | |
| the current version of the LSM patch does allow a security module to | |
| completely replace the assignment and testing of capabilities. These few | |
| locations would need to be changed if the capability-related fields were | |
| moved into the security field. The following is a list of known | |
| locations that still perform such direct examination or modification of | |
| capability-related fields: | |
| - ``fs/open.c``::c:func:`sys_access()` | |
| - ``fs/lockd/host.c``::c:func:`nlm_bind_host()` | |
| - ``fs/nfsd/auth.c``::c:func:`nfsd_setuser()` | |
| - ``fs/proc/array.c``::c:func:`task_cap()` |