|
|
|
Back to Index
|
The TrustedBSD MAC Framework permits kernel modules to extend the operating system
security policy, as well as providing infrastructure functionality required by many
access control modules. If multiple policies are simultaneously loaded, the MAC Framework
will usefully (for some definition of useful) compose the results of the policies.
The MAC Framework contains a number of kernel elements:
-
Framework management interfaces
-
Concurrency and synchronization primitives.
-
Policy registration
-
Extensible security label for kernel objects
-
Policy entry point composition operators
-
Label management primitives
-
Entry point API invoked by kernel services
-
Entry point API to policy modules
-
Entry points implementations (policy life cycle, object life cycle/label management,
access control checks).
-
Policy-agnostic label-management system calls
-
mac_syscall() multiplex system call
-
Various security policies implemented as MAC policy modules
The TrustedBSD MAC Framework may be directly managed using sysctls, loader tunables,
and system calls.
In most cases, sysctls and loader tunables modify the same parameters, and control
behavior such as enforcement of protections relating to various kernel subsystems. In
addition, if MAC debugging support is compiled into the kernel, a variety of counters
will be maintained tracking label allocation. In most cases, it is advised that
per-subsystem enforcement controls not be used to control policy behavior in production
environments, as they broadly impact the operation of all active policies. Instead,
per-policy controls should be preferred to ensure proper policy operation.
Loading and unloading of policy modules is performed using the system module
management system calls and other system interfaces, including loader variables.
As the set of active policies may change at run-time, and the invocation of entry
points is non-atomic, synchronization is required to prevent unloading or loading of new
policies while an entry point invocation is progress, freezing the list of policies for
the duration. This is accomplished by means of a Framework busy count. Whenever an entry
point is entered, the busy count is incremented; whenever it is exited, the busy count is
decremented. While the busy count is elevated, policy list changes are not permitted, and
threads attempting to modify the policy list will sleep until the list is not busy. The
busy count is protected by a mutex, and a condition variable is used to wake up sleepers
waiting on policy list modifications.
Various optimizations are used to reduce the overhead of the busy count, including
avoiding the full cost of incrementing and decrementing if the list is empty or contains
only static entries (policies that are loaded before the system starts, and cannot be
unloaded).
The MAC Framework maintains two lists of active policies: a static list, and a dynamic
list. The lists differ only with regards to their locking semantics: an elevated
reference count is not required to make use of the static list. When kernel modules
containing MAC Framework policies are loaded, the policy module will use SYSINIT to invoke a registration function; when a policy module is
unloaded, SYSINIT will likewise invoke a de-registration
function. Registration may fail if a policy module is loaded more than once, if
insufficient resources are available for the registration (for example, the policy might
require labeling and insufficient labeling state might be available), or other policy
prerequisites might not be met (some policies may only be loaded prior to boot).
Likewise, de-registration may fail if a policy refuses an unload.
Kernel services interact with the MAC Framework in two ways: they invoke a series of
APIs to notify the framework of relevant events, and they a policy-agnostic label
structure in security-relevant objects. This label structure is maintained by the MAC
Framework via label management entry points, and permits the Framework to offer a
labeling service to policy modules through relatively non-invasive changes to the kernel
subsystem maintaining the object. For example, label structures have been added to
processes, process credentials, sockets, pipes, vnodes, Mbufs, network interfaces, IP
reassembly queues, and a variety of other security-relevant structures. Kernel services
also invoke the MAC Framework when they perform important security decisions, permitting
policy modules to augment those decisions based on their own criteria (possibly including
data stored in security labels).
When more than one policy module is loaded into the kernel at a time, the results of
the policy modules will be composed by the framework using a composition operator. This
operator is currently hard-coded, and requires that all active policies must approve a
request for it to occur. As policies may return a variety of error conditions (success,
access denied, object doesn't exist, ...), a precedence operator selects the resulting
error from the set of errors returned by policies. While it is not guaranteed that the
resulting composition will be useful or secure, we've found that it is for many useful
selections of policies.
As many interesting access control extensions rely on security labels on objects, the
MAC Framework provides a set of policy-agnostic label management system calls covering a
variety of user-exposed objects. Common label types include partition identifiers,
sensitivity labels, integrity labels, compartments, domains, roles, and types. Policy
modules participate in the internalization and externalization of string-based labels
provides by user applications, and can expose multiple label elements to applications if
desired.
In-memory labels are stored in struct label, which
consists of a fixed-length array of unions, each holding a void
* pointer and a long. Policies registering for label
storage will be assigned a "slot" identifier, which may be used to dereference the label
storage. The semantics of the storage are left entirely up to the policy module: modules
are provided with a variety of entry points associated with the kernel object life cycle,
including initialization, association/creation, and destruction. Using these interfaces,
it is possible to implement reference counting and other storage mechanisms. Direct
access to the kernel object is generally not required by policy modules to retrieve a
label, as the MAC Framework generally passes both a pointer to the object and a direct
pointer to the object's label into entry points.
Initialization entry points frequently include a blocking disposition flag indicating
whether or not an initialization is permitted to block; if blocking is not permitted, a
failure may be returned to cancel allocation of the label. This may occur, for example,
in the network stack during interrupt handling, where blocking is not permitted. Due to
the performance cost of maintaining labels on in-flight network packets (Mbufs), policies
must specifically declare a requirement that Mbuf labels be allocated. Dynamically loaded
policies making use of labels must be able to handle the case where their init function
has not been called on an object, as objects may already exist when the policy is
loaded.
In the case of file system labels, special support is provided for the persistent
storage of security labels in extended attributes. Where available, EA transactions are
used to permit consistent compound updates of security labels on vnodes.
Note: Currently, if a labeled policy permits dynamic unloading, its state slot
cannot be reclaimed.
The MAC Framework implements a number of system calls: most of these calls support the
policy-agnostic label retrieval and manipulation APIs exposed to user applications.
The label management calls accept a label description structure, struct mac, which contains a series of MAC label elements. Each
element contains a character string name, and character string value. Each policy will be
given the chance to claim a particular element name, permitting policies to expose
multiple independent elements if desired. Policy modules perform the internalization and
externalization between kernel labels and user-provided labels via entry points,
permitting a variety of semantics. Label management system calls are generally wrapped by
user library functions to perform memory allocation and error handling.
In addition, mac_syscall() permits policy modules to
create new system calls without allocating system calls. mac_execve() permits an atomic process credential label change
when executing a new image.
|
|
|
|
© 2002-2004
Active-Venture.com
Website Hosting
Service
|
| |
|
Disclaimer: This
documentation is provided only for the benefits of our website hosting customers.
For authoritative source of the documentation, please refer to http://www.freebsd.org
|
|
|