Capability-based security is a concept in the
design of
secure computing systems.
A
capability (known in some systems as a
key) is a communicable, unforgeable token of
authority. It refers to a value that
references an
object along with an associated
set of
access rights. A
user program on a capability-based
operating system must use a capability to
access an object. Capability-based security refers to the principle
of designing user programs such that they directly share
capabilities with each other according to the
principle of least privilege,
and to the operating system infrastructure necessary to make such
transactions efficient and secure.
Although most operating systems implement a facility which
resembles capabilities, they typically do not provide enough
support to allow for the exchange of capabilities among possibly
mutually untrusting entities to be the primary means of granting
and distributing access rights throughout the system. A
capability-based system, in contrast, is designed with that goal in
mind.
Capabilities as discussed in this article should not be confused
with
POSIX 1e/2c . The latter are
coarse-grained privileges that cannot be transferred between
processes.
Capabilities and capability-based security
Capabilities achieve their objective of improving system security
by being used in place of forgeable
references. A forgeable
reference (for example, a
path
name) identifies an object, but does not specify which access
rights are appropriate for that object and the user program which
holds that reference. Consequently, any attempt to access the
referenced object must be validated by the operating system,
typically via the use of an
access
control list (ACL). Instead, in a system with capabilities, the
mere fact that a user program possesses that capability entitles it
to use the referenced object in accordance with the rights that are
specified by that capability. In theory, a system with capabilities
removes the need for any access control list or similar mechanism
by giving all entities all and only the capabilities they will
actually need.
A capability is typically implemented as a
privileged data structure that consists of a section
that specifies access rights, and a section that uniquely
identifies the object to be accessed. In practice, it is used much
like a
file descriptor in a
traditional operating system, but to access every object on the
system. Capabilities are typically stored by the operating system
in a list, with some mechanism in place to prevent the program from
directly modifying the contents of the capability (so as to forge
access rights or change the object it points to). Some systems have
also been based on
capability-based addressing
(hardware support for capabilities), such as
Plessey System 250.
Programs possessing capabilities can perform functions on them,
such as passing them on to other programs, converting them to a
less-privileged version, or deleting them. The operating system
must ensure that only specific operations can occur to the
capabilities in the system, in order to maintain the integrity of
the security policy.
Introduction to capability-based security
(The following introduction assumes some basic knowledge of
Unix systems.)
A
capability is
defined to be a protected
object reference which, by virtue
of its possession by a user process, grants that process the
capability (hence the name) to interact with an object in certain
ways. Those ways might include reading data associated with an
object, modifying the object, executing the data in the object as a
process, and other conceivable access rights. The capability
logically consists of a reference that uniquely identifies a
particular object and a set of one or more of these rights.
Suppose that, in a user process's memory space, there exists the
following string:
/etc/passwd
Although this identifies a unique object on the system, it does not
specify access rights and hence is not a capability. Suppose there
is instead the following two values:
/etc/passwd
O_RDWR
This identifies an object along with a set of access rights. It,
however, is still not a capability because the user process's
possession of these values says nothing about whether that
access would actually be legitimate.
Now suppose that the user program successfully executes the
following statement:
int fd = open("/etc/passwd", O_RDWR);
The variable
fd now contains the index of a file
descriptor in the process's file descriptor table. This file
descriptor
is a capability. Its existence in the process's
file descriptor table is sufficient to know that the process does
indeed have legitimate access to the object. A key feature of this
arrangement is that the file descriptor table is in
kernel memory and cannot be
directly manipulated by the user program.
Sharing of capabilities between processes
In traditional operating systems, programs often communicate with
each other and with storage using references like those in the
first two examples. Path names are often passed as command-line
parameters, sent via sockets, and stored on disk. These references
are not capabilities, and must be validated before they can be
used. In these systems, a central question is "on whose
authority is a given reference to be evaluated?" This
becomes a critical issue especially for processes which must act on
behalf of two different authority-bearing entities. They become
susceptible to a programming error known as the
Confused deputy problem, very
frequently resulting in a
security
hole.
In a capability-based system, the capabilities themselves are
passed between processes and storage using a mechanism that is
known by the operating system to maintain the integrity of those
capabilities.
Although many operating systems implement facilities very similar
to capabilities through the use of
file
descriptors or
file handles — for
example, in
UNIX, file descriptors can be
discarded (closed), inherited by child processes, and even sent to
other processes via
sockets — there are
several obstacles that prevent all of the benefits of a
capability-based addressing
system from being realized in a traditional operating system
environment. Chief among these obstacles is the fact that entities
which might hold capabilities (such as
processes and
file) cannot be made
persistent in such a way that
maintains the integrity of the secure information that a capability
represents. The operating system cannot trust a user program to
read back a capability and not tamper with the object reference or
the access rights, and has no built-in facilities to control such
tampering. Consequently, when a program wishes to regain access to
an object that is referenced on disk, the operating system must
have some way of validating that access request, and an access
control list or similar mechanism is mandated.
One novel approach to solving this problem involves the use of an
orthogonally persistent
operating system. (This was realised in the
Flex machine. See
Ten15).
In such a system, there is no need for entities to be discarded and
their capabilities be invalidated, and hence require an ACL-like
mechanism to restore those capabilities at a later time. The
operating system maintains the integrity and security of the
capabilities contained within all storage, both volatile and
nonvolatile, at all times; in part by performing all
serialization tasks by itself, rather than
requiring user programs to do so, as is the case in most operating
systems. Because user programs are relieved of this responsibility,
there is no need to trust them to reproduce only legal
capabilities, nor to validate requests for access using an
access control mechanism.
POSIX Capabilities
POSIX draft 1003.1e specifies concept of permissions called
“capabilities”. However POSIX capabilities differ from capabilities
in this article — POSIX capability is not associated with any
object — a process having CAP_NET_BIND_SERVICE capability can
listen on any TCP port under 1024.
Research and commercial systems
References
- Levy, Henry M., * Capability-Based Computer Systems, Digital
Equipment Corporation 1984. ISBN 0-932376-22-3. An electronic
version is available here.
- The EROS
Project
- E, a programming language
based around capability security ( ERights.org)
- Mark S. Miller, Ka-Ping Yee, Jonathan Shapiro. Capability
Myths Demolished, Technical Report SRL2003-02, Systems
Research Laboratory, Johns Hopkins University. Available online.
- The Cambridge CAP Computer, Levy, 1988
not currently used:
POSIX "capabilities" in Linux:
External links