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
super_block. For pipe, file, and socket security
information, security fields were added to
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
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
unregister_security hooks in the
security_operations structure and provides
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.