202 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
========================================================
 | 
						|
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()`
 |