This document was made by
OCR from a scan of the technical report. It has not been edited or proofread
and is not meant for human consumption, but only for search engines. To see the
scanned original, replace OCR.htm with Abstract.htm or Abstract.html in the URL
that got you here.
Dynamic
protection structures
by B. W. LAMPSON
Berkeley Computer Corporation
Berkeley, California
INTRODUCTION
A
very general problem which pervades the entire field of operating system design
is the construction of protection
mechanisms. These come in many different forms, ranging from hardware
which prevents the execution of input/output
instructions by user programs, to
password schemes for identifying customers when they log onto a time-sharing system. This paper deals with one aspect of the subject, which might be
called the meta-theory of protection
systems: how can the information which specifies protection and
authorizes access, itself be protected and manipulated. Thus, for example, a memory protection system decides
whether a program P is allowed to store into location T. We are concerned with how P obtains this permission and
how he passes it on to other programs.
In order to lend immediacy to the
discussion, it Nvill be helpful to have some examples. To provide some background for the examples, we
imagine a computation C running on a general
multi-access system M. The computation
responds to inputs from a terminal or a card reader. Some of these look
like commands: to compile file A, load B and
print the output double-spaced. Others
may be program statements or data.
As C goes about its business, it executes a large number of different programs and requires at various times a large number of different kinds of access to the resources of the system and to the
various objects which exist in it. It is necessary to have some way of knowing at each instant what privileges
the computation
has, and of establishing and changing these privileges in a flexible way. We
will establish a fairly general conceptual framework for this situation,and consider the
details of implementation in a specific system.
Part
of this framework is common to most modern operating systems; we will summarize
it briefly. A program running on the system M exists in an environment created by M, just as does a program running
in supervisor state on a machine
unequipped with software. In the
latter case the environment is simply the available memory and the
available complement of machine instructions
and input/output commands; since these appear in just the form provided
by the hardware designers, we call this environment the bare machine. By contrast, the, environment
created by M for a
program is called a virtual or user machine.6 It normally
has less memory, differently organized, and an instruction set. in which the input/output at least has been greatly changed. Besides the machine registers and memory, a user machine provides a set
of objects which can be
manipulated by the program. The instructions for manipulating objects are probably implemented in software, but this is of no concern
to the user machine program, which is
generally not able to tell how a given feature is implemented.
The basic object which executes programs
is called a task or process;6
it
corresponds to one copy of the user machine. What we are primarily concerned
with in
this paper is the management of the objects which a process has
access to: how are they identified, passed around, created, destroyed, used and shared.
Beyond this point, three ideas are fundamental to the framework being developed:
1: Objects are named by capabilities,' which are names that are protected by the system in the
sense that
programs can move them around but not change them or create them in an
arbitrary way. As a consequence, possession of a capability can be
taken as prima facie proof of the right to access the object it names.
2.
A
new kind of object called a domain is used to group capabilities. At any
time a process is executing in some domain and hence can exercise the capabilities which belong to the domain. When
control passes from one domain to another
(in a suitably restricted fashion) the capabilities of the process will
change.
3.
Capabilities are usually obtained by presenting domains which possess them with
suitable authorization, in the form of a special kind of capability called an access key. Since a domain can possess
capabilities, including access keys, it can carry its own identification.
A key property of this framework is that
it does not distinguish
any particular part of the computation. In other words; a program
running in one domain can execute, expand the computation, access files and in
general exercise its capabilities without regard to who created it or how far
down in any hierarchy it is. Thus, for
example, a user program running under a debugging system is quite free to create another incarnation
of the debugging system underneath him, which may in turn create another user program which is not
aware in any way of its position in the scheme of things. In particular, it is possible to reset things to a
standard state in one domain without disrupting higher ones.
The reason for placing so much weight on this property is two-fold. First of all, it provides a
guarantee that programs can be glued
together to make larger programs
without elaborate pre-arrangements about the nature of the common environment. Large systems with active user communities quickly build up
sizable collections of valuable routines. The large ones in the collections, such as compilers, often prove useful
as sub-routines of other programs.
Thus, to implement language X it may be convenient to translate it into language Y, for which a compiler already exists.
The X implementor is probably unaware
that Y's implementation involves a
further call on an assembler. If the basic
system organization does not allow an arbitrarily complex structure to be built up from any point,
this kind of operation will not be feasible.
The second reason for concern about
extendibility is that it allows deficiencies in the design of the system to be made up
without changes in the basic system itself, simply by interposing another
layer between the basic system and the user. This is especially importantwhen we realize
that different people may have different ideas about the nature of a deficiency.
We now have outlined the main ideas of the paper. The remainder of the discussion is
devoted to filling them out with examples
and explanations. The entire scheme has been developed as part of the
operating system for the Berkeley Computer
Corporation Model I. Since many details and specific mechanisms are dependent on the characteristics of the
surrounding system and underlying
hardware, we digress briefly at this point to describe them.
Environment
The BCC Model I is an integrated hardware and software system
designed to support a large number (up to 500)
of time-sharing users. This system consists of two central processors, several small processors, a large central (core and integrated circuit) memory, and
rotating magnetic memory. The latter
contains more than 500 X 106
bytes, including approximately 12 X 106 bytes of drum having a transfer rate of more than 5 x 106
bytes per second.
The
hardware allows each process more than 512k bytes of virtual memory. The
central processors can accommodate operands
of various sizes including 48-and p6-bit floating point
numbers. The addressing structure allows
characters, part-word fields and array elements
to be referenced directly. The subroutine-calling instruction passes parameters and allocates stack space
automatically. System calls are handled exactly like ordinary function calls.;
when arrays or labels are passed to the
system they are checked automatically
by the hardware so that they can be used by the system without further
ado.
The memory management system organizes memory into pages. A
page is identified by a 48-bit unique name which
is guaranteed different for each page ever created in the system. Tables
are maintained in the central memory which
allow the page to be found in the various levels of the memory system.
These tables are automatically accessed by
the address mapping hardware the first time the page is referenced after
the processor starts to run a new process. Thereafter its real core address is
kept in fast registers. It is therefore unnecessary for any program other than a small part of the basic system to be
concerned about the lccation of a page in the memory system; when it is
referenced, it will be brought into the central memory if it is not already there. Extensive facilities are provided,
however, to allow a process to
control the level in the memory
hierarchy of the pages it is interested in. The work of managing the
memory is done by a processor with
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
read-only program memory and data
access to the central
memory; this processor has a 100 ns cycle time, so that it can handle the large amount of computing required to keep up with demands placed on the memory system. Another small processor handles the remote terminals, which are multiplexed in
groups of 20 to 100 at remote concentrators and brought into
the system over high-speed lines.
Pages are grouped into files, which are treated as randomly addressable sequences of
pages. The only mechanism provided to access
the data in a file is to put a page of
the file into the virtual memory of a process. Files and processes are
named and have protection information associated with them.
Domains in
action
Before plunging into
a detailed analysis of capabilities and domains, we will look at some of the practical situations which these
facilities are designed to serve. They all have the same general character: several programs with
different privileges exist. Each program corresponds to one domain. Some of the domains control others, in the sense that the capabilities of a
controlled domain are a subset of those of its controlling domain. As a first
example, consider the command process CP of
an operating system. This program accepts
a command, perhaps from a remote terminal, and attempts to recognize it
as a call on a program X which CP knows
about. If it succeeds, CP calls on X for execution, passing it any
parameters which were included in the
command. To do this, CP must set up a suitable environment for X to
function in. In particular, enough memory
must be provided for X to run, X must be loaded properly, and suitable input/ output must be available. When X is finished, it
will return and CP can process a new command.
The key point is that
we want CP to be protected from X, to ensure that the user's commands continue to be processed even if X has bugs. In particular, we
want to be sure that
1. X does not destroy CP's memory or
files, so that CP can continue to run
when X returns.
2.
CP can stop X if it goes wild. Usually we want the ability to set a time limit and also to intervene
from the terminal.
In other words, we want CP and X
to run in separate domains, as
illustrated in Figure 1 (since this is an informal discussion, we do not
trouble to distinguish carefully between the program X and the domain in which
it runs). Here we have shown the call from CP


![]()
![]()

![]()
![]()
Figure
1—A command processor and its command
to X in two forms: in
the picture on the right, and as a return capability in X. The reason for the capability is that X cannot return with a
simple branch operation,
since it would then be able to start CP running at any point, which would destroy the protection.
Suppose now that we
want to allow X to get additional
commands executed. X might, for example, be a Fortran
compiler whose output must be passed through
an assembler. A simple way to do this is to put the assembler input on a
file called, say, FORTRANTE:\ IP, and issue the command.
ASSEMBLE
FORTRANTEMP, BINARY
This command is just a string, which can
easily be constructed by the compiler X. To get it executed, however, X must be able to call CP. This situation is
illustrated in Figure 2; note the call capability in X, which is quite different from the return capability. We are ignoring for the moment the question of how CP
knows that X is authorized to call the assembler.
If the idea of the preceding paragraph is
pursued, it suggests the value of being able to switch the source of command input and the destination of command output
in a flexible way. By these terms we mean the
CP, command processor X:
Command Y: Command




![]()

![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
Figure 2—A recursive command processor

![]()
![]()
![]()

![]()
![]()
![]()
![]()
traffic between a program and the
entity by which it is
directed. In a time-sharing system this is normally a terminal at which the imer is
sitting; in a non-interactive system it will be a file of control cards. It is
often desirable,
however, to switch between the two, so that routine processing can be done automatically when the user's attention is
elsewhere, yet he can regain control when
things go awry. Again, it is not uncommon to wish to capture a complete record of
a conversation between user and machine for
later analysis and replay. More
radical, it may be of interest to
replace the user at his terminal with a program which can manipulate the
strings of characters which constitute
commands and responses. In this way major changes in the external appearance of a system can be obtained
with little effort.
All of these things can be accomplished by
giving interactions with the command I/O
device the form of calls to a different domain which acts as a switch. A
generalization to include the possibility of different command devices for different domains is easy. Thus, a user may initiate a program in a domain X which,
while continuing to communicate with him, starts a
|
CP1: command |
|
|
MC: macro command |
|
CP2: command |
|
|
|
|
|
|
|
|
p rocessor 2 |
|
|
|
p rocessor 1 |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
call cr0 |
|
|
Call
cio |
|
|
Call
CIO |
|
|
Domain MC |
|
|
Domain
CP2 |
|
|
Domain
X |
|
|
|
|
|
|
|
|
|
|
|
Directory of commands |
|
|
Return
to CPI. |
|
|
Return
to MC |
|
|
Domain CIO |
|
|
Return
to CIO |
|
|
|
|
|
|
|
||||||