Documentation: LSM: Correct the basic LSM description

This is a first pass at updating the basic documentation on
Linux Security Modules (LSM), which is frighteningly out of date.
Remove untrue statements about the LSM framework. Replace them
with true statements where it is convenient to do so. This is
the beginnig of a larger effort to bring the LSM documentation
up to date.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Link: https://lore.kernel.org/r/4c053d72-2d58-612f-6d6b-f04226d0181e@schaufler-ca.com
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
This commit is contained in:
Casey Schaufler 2020-04-21 14:48:34 -07:00 committed by Jonathan Corbet
parent cea0fad0f8
commit e2d467de34
1 changed files with 62 additions and 132 deletions

View File

@ -35,47 +35,50 @@ 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
such a framework. LSM was 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.
Linux kernel patch that implements this framework. The work was
incorporated in the mainstream in December of 2003. This technical
report provides an overview of the framework and the capabilities
security module.
LSM Framework
=============
The LSM kernel patch provides a general kernel framework to support
The LSM framework 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
likely to address other security needs such as sandboxing. 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.
the infrastructure to support security modules. The LSM framework is
optional, requiring `CONFIG_SECURITY` to be enabled. The capabilities
logic is implemented as a security module.
This capabilities module is discussed further in
`LSM Capabilities Module`_.
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 framework includes security fields in kernel data structures and
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 security modules.
An interface `/sys/kernel/security/lsm` reports a comma separated list
of security modules that are active on the system.
The LSM security fields are simply ``void*`` pointers. For process and
program execution security information, security fields were added to
The LSM security fields are simply ``void*`` pointers.
The data is referred to as a blob, which may be managed by
the framework or by the individual security modules that use it.
Security blobs that are used by more than one security module are
typically managed by the framework.
For process and
program execution security information, security fields are included in
: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
:c:type:`struct cred <cred>`.
For filesystem
security information, a security field is included in :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,
information, security fields are included in :c:type:`struct inode
<inode>` and :c:type:`struct file <file>`.
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
@ -84,118 +87,45 @@ 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->".
For packet and
network device security information, security fields were added to
:c:type:`struct sk_buff <sk_buff>` and
:c:type:`struct scm_cookie <scm_cookie>`.
Unlike the other security module data, the data used here is a
32-bit integer. The security modules are required to map or otherwise
associate these values with real security attributes.
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.
LSM hooks are maintained in lists. A list is maintained for each
hook, and the hooks are called in the order specified by CONFIG_LSM.
Detailed documentation for each hook is
included in the `include/linux/lsm_hooks.h` header file.
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.
The LSM framework provides for a close approximation of
general security module stacking. It defines
security_add_hooks() to which each security module passes a
:c:type:`struct security_hooks_list <security_hooks_list>`,
which are added to the lists.
The LSM framework does not provide a mechanism for removing hooks that
have been registered. The SELinux security module has implemented
a way to remove itself, however the feature has been deprecated.
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
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.
of hooks include the security_inode_alloc() and security_inode_free()
These hooks are used to allocate
and free security structures for inode objects.
An example of the second category of hooks
is the security_inode_permission() hook.
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()`
The POSIX.1e capabilities logic is maintained as a security module
stored in the file ``security/commoncap.c``. The capabilities
module uses the order field of the :c:type:`lsm_info` description
to identify it as the first security module to be registered.
The capabilities security module does not use the general security
blobs, unlike other modules. The reasons are historical and are
based on overhead, complexity and performance concerns.