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 pro­tection mechanisms. These come in many different forms, ranging from hardware which prevents the exe­cution 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 state­ments 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 environ­ment created by M, just as does a program running in supervisor state on a machine unequipped with soft­ware. 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 reg­isters 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 capa­bility 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 an­other (in a suitably restricted fashion) the capa­bilities 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 prop­erty 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 implemen­tation 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 soft­ware 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 rotat­ing 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 auto­matically 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 auto­matically 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 unneces­sary 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, how­ever, to allow a process to control the level in the memo­ry 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 com­puting 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 pro­tection information associated with them.

Domains in action

Before plunging into a detailed analysis of capa­bilities and domains, we will look at some of the practi­cal 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 con­trol others, in the sense that the capabilities of a con­trolled 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 in­cluded in the command. To do this, CP must set up a suitable environment for X to function in. In par­ticular, 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 inter­vene 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

Text Box: Command inputText Box: X: commandText Box: Capabilities
required by
X
Return to CP
Text Box: CP
(r)
0
Calls
Text Box: DomainsText Box:  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 oper­ation, 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 addition­al 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, FOR­TRANTE:\ 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

Text Box: CP
0
CP
ED
CP, command processor        X: Command       Y: Command

Text Box: Capabilities required byText Box: Capabilities required by XText Box: Call CP
Return to CP
Text Box: Return to CPText Box: Command input
Command output
Directory of commands
Domain X
Text Box: Domain YText Box: Return to XFigure 2—A recursive command processor


Text Box: Call CplText Box: Call CP2Text Box: Call MCText Box: Return to Xtraffic 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-inter­active 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