LSM Overview

This section provides an overview of the Linux Security Modules (LSM) framework. This section contains an edited excerpt from the Documentation/DocBook/lsm.tmpl file in the kernel tree, updated to reflect recent changes made for the Linux 2.6 integration.

LSM provides a general kernel framework to support security modules. In particular, the LSM framework is primarily focused on supporting access control modules. By itself, the framework does not provide any additional security; it merely provides the infrastructure to support security modules. The LSM framework also moves most of the capabilities logic into an optional capabilities security module, with the system defaulting to a dummy security module that implements the traditional superuser logic.

The LSM framework 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. Extended attribute handlers for a new security namespace were added to filesystems to support new file security attributes, and a /proc/pid/attr subdirectory was introduced to provide userspace access to new process security attributes.

The LSM security fields are simply void* pointers. For process and program execution security information, security fields were added to struct task_struct and struct linux_binprm. For filesystem security information, a security field was added to struct super_block. For pipe, file, and socket security information, security fields were added to struct inode and struct file. Unix domain sockets may also use a security field added to the struct sock. For System V IPC security information, security fields were added to struct kern_ipc_perm and struct msg_msg.

Each LSM hook is a function pointer in a global table, security_ops. This table is a security_operations structure as defined by include/linux/security.h. Detailed documentation for each hook is included in this header file. The hooks are grouped into logical sets based on the kernel object (e.g. task, inode, file, sock, etc) as well as some miscellaneous hooks for system operations. A static inline function is defined for each hook, so that most of the hook calls can easily be compiled away if desired, in which case only the default capabilities logic is included.

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 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 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 register_security and unregister_security hooks in the security_operations structure and provides mod_reg_security and 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 defers the problem of composition to the module.

Although the LSM hooks are organized 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 alloc_security and 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 d_instantiate hook. This hook is used to set security information for inodes, e.g. by calling getxattr to obtain an attribute value, when all the necessary object information is available. An example of the second category of hooks is the inode_permission hook. This hook checks permissions when accessing an inode.

Although LSM originally included a new security system call, this call was subsequently removed. Most of its functionality can now be implemented using the extended attribute support and /proc/pid/attr interface, as mentioned above.