.NH 2 Implementation of labels .XL y7 .PP The label check performed at a system call depends on whether the call involves a file name or a file descriptor (the handle by which a process accesses an open file), whether the call is write-like or read-like, and so on. Most checks fall into a few classes that can be dispatched by a table. The classes differ mainly in what dominance relations may be affected. For example, the .I read system call must respect seven dominance relations among five labels: file label, process label, seek pointer label, process ceiling, and file system ceiling. The process and seek pointer labels may possibly be adjusted to preserve the relationships. The dominance relations and adjustabilities are recorded in tables that are interpreted by a single generalized label-check subroutine, which finds the minimum legal adjustment needed to satisfy the checks, or backs out gracefully if adjustment is impossible. .PP Continual rechecking of labels in this degree of generality is a time-consuming matter (\*(yp). Fortunately labels don't change often, so we use a check-caching scheme to avoid unacceptably large overhead from comparisons. Every file descriptor is endowed with two `safe bits,' one for safe-to-read and one for safe-to-write. A network of pointers, some of which exist in traditional .UX implementations, and some of which are new, connects files, file descriptors, and processes. Whenever a file label rises, associated safe bits in all processes can be located quickly and turned off. Subsequent accesses via other file descriptors will find the safe bits cleared and cause the label relations to be checked in detail. The label relations will be reestablished if possible, and the safe bits turned back on. Similarly, when the label of a process rises, safe-to-write bits are turned off throughout the process. .PP Typically the safe-to-read bit in a file descriptor will be turned on by the first read after file opening and stay on thereafter. As long as the safe-to-read bit doesn't change, label checking amounts to a one-bit test in each read (or in each atomic data transfer of a long read that the system chooses to do in pieces). Thus dynamic label checking costs imperceptibly more in time than would static label checking at file open, which suffices in Bell-LaPadula systems. Space costs, however, are significant (\*(yr). .NH 2 Representation of labels .XL y9 .PP Labels in IX comprise lattice values, privilege bits (\*(y0), two bits for fixity (modifiable, frozen, rigid, unmodifiable; \*(y6), and an indicator for $YES$ and $NO$. Lattice values are represented as bit vectors; lattice domination is represented as set inclusion. No further structure is predefined. Notions such as security level, compartment, or Biba integrity (\*(yc) are trivial to encode, however. .PP Labels account for about half of all the descriptive information kept permanently with each file. The labels of open files occupy appreciable space in main memory and take appreciable time to compare. .PP We considered, and for several reasons rejected, a scheme of indirect labels in which each file bears a pointer into a table of all existing label values. .SP .IP 1.\ It could be harder to recover from an inconsistent state induced by a crash or otherwise. .IP 2.\ The corruption of one table entry would mislabel a bundle of files at once. .IP 3.\ To fit with existing backup schemes, backup files would carry full labels anyway. .IP 4.\ To realize the full benefits of indirect labels, there should be a separate coding table for each removable file system. .IP 5.\ With dynamic labels, the encoding of labels would evolve differently on every system, even systems under common administration. .SP .PP The first reason was the most compelling. With directly labeled files, inconsistencies between label and data are confined to individual files. Moreover, the inconsistencies are harmless because we force each rise in label to disk before transferring the data that caused the rise. Thus labels are robust against crashes; they are at risk only to wild scribbling in a file system, as by a berserk disk controller. .PP Direct labeling of files is not a panacea. Removable file systems can be moved only among systems that agree on label encodings. Moreover, labels will probably have to be translated between remotely communicating systems; but this is also true with indirect labels. (Indirect labels have been used in System V, where reason 5 does not pertain, and inode compatibility is of concern. |reference(bendet)|reference(SVMLS tech)) .PP These considerations do not apply to labels that reside in main memory, where indirection is used. In system tables labels are shared via pointers to save space, to speed copying, and to speed comparisons. A further level of sharing guarantees that coupled labels, such as the labels on the two ends of a pipe or on a process and its associated process file vary together. .ig .NH 2 External media, session labels .XL ya .PP It is easy to maintain labels correctly through the course of computation, as all labels are under the control of the system. It is harder to assure the correct handling of classified information in external transactions, where one party is beyond the control of the system. Data must be labeled properly on entering the system from outside and data leaving the system must go only to appropriate destinations. .PP Something must be known about the other party in an external transaction, perhaps by the identity of the external port being used, perhaps by an authentication protocol. Then the medium can be assigned an appropriate label. As security behavior depends on it, the validation of external media cannot be left to untrusted processes. Thus only trusted processes may initiate external connections. .PP When not open in any process, an external medium bears label $NO$. A trusted process may open it, determine an appropriate label, and set the label away from $NO$. While the file is open in any process, untrusted processes can access it, but cannot cause its label to change. At last close the label automatically reverts to $NO$. .PP The association of a file with a single label for both read and write implies that, while a port is presenting highly classified information, all the users' inputs, no matter how trivial, are automatically classified high as well. This annoying effect can be mitigated by using multiple terminals, usually in the form of virtual terminals (windows) on a single trusted device (\*(yn). It might be well, however, for terminal ports to be treated as two separately labeled data streams for input and output. .. .ig .NH 2 Imported and exported file systems .XL yb .PP When an entire file system is carried to an untrusted recipient, the file system should contain no information that the recipient is not cleared for. To create an IX file system for export, the medium should be erased or degaussed and then mounted with a file system ceiling appropriate to the clearance of the recipient. The ceiling will assure that only data below the ceiling get written on the file system. Once written, the file system can be demounted and shipped with confidence that it contains only safe labels. .PP The file system ceiling may also be used to protect against dangers in a file system imported from an untrusted source, either by carrying or by cross-mounting. One such danger is spuriously overclassified data. Another is spurious privilege marks on programs. Both can be masked out by the file system ceiling. .. .NH 2 The floor, integrity labels .XL yc .PP Biba pointed out that a secrecy lattice, where a highly cleared program can read almost any file and write almost none, is just the opposite of an `integrity' lattice, where a highly trusted program can modify almost any file but can read almost none for fear of becoming contaminated with bad data.|reference(denning)|reference(biba) IX labels can be used in Biba fashion, by starting untrusted users high, and keeping trusted software low. Any change to trusted software caused by untrusted users will be reflected in a raised label. By running with a low ceiling, trusted applications may be immunized against using the corrupt software. .PP To get integrity and secrecy controls simultaneously, we simply regard some of the bits in a label as integrity bits, others as secrecy bits. All users log in at an administratively defined middle, or .I floor label, which has ones in its integrity bits and zeros in its secrecy bits. System source, utilities, and other important universally available files are labeled below the floor, typically at bottom. .PP In illustration, suppose that a project has one integrity bit and one secrecy bit. The floor label at which everybody\(emincluding project members\(emlogs in is 10, with a 1 for low integrity and a 0 for low clearance. Project members are entitled to raise their ceiling to 11. Having begun at 10, their process labels can change to 11 but not to 00 or 01. The project administrator, who is entitled to `downgrade' (i.e. upgrade in integrity) the integrity bit, may set the label on critical project data to 01. Should any ordinary project member succeed in writing the file, the integrity bit will change and the file label will become 11. The loss of integrity is thus recorded in the file label and optionally in a system audit trail (\*(yj). .PP Marking data as high-integrity does not protect the data from compromise. It does, however, protect against false belief in the high integrity. By setting the ceiling to cut off access to low-integrity data, a high-integrity process may be immunized against unwittingly using corrupted data. Of course low-integrity processes may still use the corrupted data, but as their outputs would have low integrity anyway, the integrity policy has been respected. The only real hazard is denial of service to high-integrity processes. .PP New system code will usually be tested at a normal label, at or above the floor. It will be installed by downgrading the source code to a label below the floor, rechecking for accuracy, and compiling afresh. To be really careful, one would place the trusted computing base (\*(yB) below everything else. Then no untrusted tools could be invoked inadvertently while working on trusted code. .NH 1 PRIVILEGES .XL yd .PP The data-flow policy, which covers normal operations, is insufficient for administrative purposes. For example, establishing a user session at a non-floor label may involve changing the process label down or the ceiling up, in contradiction to normal policy. Some other actions that violate the policy are document declassification, repair of multilevel file systems, opening of external media, and mounting of file systems. .PP Administrative actions that fall outside the data-flow policy are performed by privileged utilities, which are exempt in one way or another from kernel enforcement. As privileged code does not enjoy the guarantees of the policy, it must be written with great care to assure that it maintains intended security. Because such code is exempted from normal checks in the expectation that it will do no wrong, it is called `trusted.' Privilege can be exercised only through trusted code. .PP Roughly speaking, the privilege mechanism partitions the supreme powers once accorded to the superuser. Superuser status itself is diminished. The superuser is fully bound by security labels and cannot ignore write permissions. To keep as much of the familiar .UX semantics as possible and to avoid rewriting masses of code, we have retained the association of other special powers with the superuser. When these powers break the security rules, superuser status must be augmented by privilege. .NH 2 Capabilities and licenses .XL y0 .PP Each privilege is governed by a one-bit .I capability and a one-bit .I license. A process possessing a capability has the actual right to exercise privilege. A process possessing a license has a potential right. Process licenses can be gained only with privilege, usually by application to the privilege server (\*(yl), are inheritable across file execution (the \fIexec\fR system call), and may be relinquished at will. In effect licenses identify trusted users. Capabilities depend on the program being executed and are not inherited. .PP We denote the vector of capabilities of a process or file $x$ by $Cap(x)$ and the vector of licenses by $Lic(x)$. In general, a process $p$ executing file $f$ will have a given capability if the file has the capability and the process is licensed for it. The vector of capabilities is computed by bitwise intersection: .EQ I Cap(p)~=~Cap(f)~meet~Lic(p). .EN .LP Other factors participate in the computation of capabilities. A program file has a license vector, $Lic(f)$, which may endow the executing process with capabilities regardless of the process's own licenses. Such a `self-licensed' program gets power in much the same way as does a set-user-id program in ordinary .UX systems, except that the power is not inherited on executing further programs. When file system $FS$ is mounted it may be assigned privilege masks, $Cap(FS)$ and $Lic(FS)$ to exclude imports of spurious privilege, for example from untrusted remote machines in a network file system. Privilege masks may also be used to limit the locus of privilege to some well-managed region of the entire file space. If file $f$ lives in file system $FS(f)$, the complete formula for process capabilities is .EQ I Cap(p)~=~Cap(f)~meet~Cap(FS(f)) ~meet~(Lic(p)~join~(Lic(f) meet Lic(FS(f)))). .EN .PP Readers familiar with System V release 4ES will recognize homologies between IX capabilities and 4ES `working privileges,' licenses and `maximum privileges,' file capabilities and `inherited privileges,' self-licenses and `fixed privileges.'|reference(user's guide) Local control is somewhat stronger in System V, where a process can turn its working privileges on and off. Global control is somewhat stronger in IX, where licenses cannot propagate through execution of untrusted code. (The danger in licensing untrusted processes: a Trojan horse might be able to pass a license to a privileged program to do ill. To guard against this eventuality, a privileged program would have to assume the burden of verifying the legitimacy of each task it is asked to do.) .NH 2 Specific privileges .XL ye .PP Believing that too many privileges would be unmanageable, we have provided just six generic privileges, rather than a long list of specific privileges such as `register new users,' `repair file systems,' or `downgrade files.' The existence of broad privileges does not automatically imply broad powers for a user who is authorized to exercise privilege. In practice, even trusted administrators are not granted active licenses. Instead, one applies to the privilege server (\*(yl) to run each privileged command. If a user is authorized to run the command with the given arguments, the server grants the necessary licenses and executes the command. The six privileges, listed in roughly descending order of power, are .SP .IP .I "Set privileges. Change file capabilities and licenses. .IP .I "Set licenses. Increase the license or ceiling of a process. .IP .I Extern. Mount file systems, change labels away from $NO$, or change labels of external media. .IP .I Nocheck. Read or write data without regard to security label. .IP .I "Control auditing. Adjust the intensity of auditing, nominate auditing files, or perform related actions. .IP .I "Write uarea. Change system-maintained data such as userid, which may be read by other processes. .SP .PP The last-mentioned privilege is more an artifact of .UX than a corollary of the security mechanism (\*(yq). Otherwise each privilege overrides an identifiable aspect of that mechanism. .NH 2 Concerns in privileged code .XL yf .PP Privileged processes in effect administer their own security policy, and thus must be written with the same care as the kernel itself. As an example, we consider the privilege `nocheck,' which allows a process to circumvent automatic label checking on selected files. Nocheck is used in various trusted applications that have to read and write multilevel data. Among these applications are: checking, copying, and repairing multilevel file systems; managing a multilevel terminal over a single-level wire (\*(yn); delivering multilevel mail; and providing a centralized service (e.g. password authentication, \*(ym) for multilevel clients. .PP A nocheck process must take care to observe that file labels do not change underfoot in dangerous ways. Notification tools exist for this purpose. A new signal, .CW SIGLAB , may be used to detect changes in labels of open files; and a special system call (\fIunsafe\fR) identifies which files are involved. It is up to the process, however, to decide whether each particular label change is safe or not. .NH 2 The trusted computing base .XL yB .PP To a first approximation, the kernel and privileged programs constitute a trusted computing base (TCB).|reference(orange book) Nothing can join the TCB without the intervention of something that is already in it. Nothing in the TCB can change. The only way to modify a trusted program is to delete it from the TCB by removing its privilege, work on it, and then restore privilege. A paranoid protocol for modifying the TCB is given in \*(yA. .PP Anything that prepares or verifies components of the TCB should either have its effects vetted by a TCB program or itself be in the TCB. For example, a compiler whose correctness is taken on faith should be in the TCB, while a compiler whose output can be verified by an independent TCB tool need not be. A part of the TCB that does not need privilege must be made immutable in some other way. One way is to give the program a dummy license, but no capability. Such a program is formally privileged, but can exercise no privileges. Another way is to protect the TCB by integrity labeling (\*(y9). .NH 1 PRIVATE PATHS .XL yh .PP In some instances security may be compromised by simultaneous access of trusted or untrusted processes to one file. Consider, for example, the apparently simple matter of collecting a password at login time from a user at a physically secure port. Until authentication is complete the user's clearance is unknown, so the port cannot be honestly labeled at any ordinary security level. If the port were unclassified, other processes might be able to steal the password. If the port were highly classified, high data could be sent to it without the recipient having yet been authenticated. Thus to assure that passwords go only where they are supposed to, and that the port not be misused for other information, the port should be placed in a special dedicated state. As long as the port remains in this state no other process can read, write, or seek on any file descriptor associated with it. .PP A properly cautious user will demand assurance that the password is in fact being demanded by trusted code. Hence the special state of the port and the credentials of the communicating process should be discernible by the user as well (\*(yn). We call the arrangement a .I "private path. .PP Should other trustable communications processes be interposed in a private path, then the (two-way) assurances need to extend transitively to each segment of the channel. If the trust breaks at any point of the channel, data that started along the channel in trust must not be misdelivered, and data that is delivered in trust must not have been injected from an unintended source. .PP IX has two features for administering private paths: process-exclusive access and stream identifiers. These features are used mainly to insure the integrity of transactions performed by trusted processes. .NH 2 Pex .XL yC .PP A process can obtain a private path by asserting process exclusive, or .I pexed, access to a file or stream that is open in the process. Pex may be used to lock out interference when updating a file (\*(yA). If one end of a pipe is pexed, the pipe cannot be used unless the other end is pexed, too. Moreover, the pexing protocol provides to the process at each end of the pipe unforgeable indicia of trust (userid and capabilities) about the other. The indicia provide the basis for extending trust transitively along a multistep private path.* .FS * Thus realizing something like Boebert's `assured pipeline.'|reference(boebert integrity) .FE When either process breaks trust by unpexing its end, its partner is prevented from blindly continuing as if nothing had happened: the pipe becomes unusable until unpexed at both ends. .PP Transmissions on a pexed file or stream are understood to be immune to eavesdropping or injection of signals. Since such assurance is not necessarily available for external media, external media may be conditioned to allow or disallow pexing. Thus pexing might be denied on a communications port to an untrusted computer and permitted on a hard-wired line to a trusted terminal in a secured area. .PP Although pex is used almost entirely by privileged processes, it is available to any process. Herein lies a risk. By pexing a file, a malicious process can deny its use to others. The process can be forced to let go only by killing it. .NH 2 Stream identifier .XL yD .PP The destination of a file, particularly if that file connects to the outside world, may determine how it can be used. We have just explained one determining condition, the ability to use the stream as a private path. Others are the identity of the port's user, the tokens or passwords the user has presented, the stream's network source, etc. For recording such facts about a port, IX allows an arbitrary string, called a .I "stream identifier, to be associated with any .UX stream. Settable only with privilege, the stream identifier serves as a trustable repository of descriptive information. The stream identifier is usually set by the login program and may be augmented by the session supervisor (\*(yy). .PP Pexing and stream identifiers associate security-related properties with channels, not with subjects or objects. In a communications-based system, the relationship of a stream to a subject may be remote indeed. What if the stream leads to a multiplexer process, to an encrypter, to a data link, to another computer, to a decrypter, to a demultiplexer, to ...? It does not make sense to consider all stages in the path to be independent subjects ruled by the security policy. A multilevel demultiplexer, for example, must be able to violate the letter of the policy, while being trusted to carry out the intent. In order to do that it needs to know the security requirements of the data it is handling, even though it has no need to know about the origins of that data. Streams, not users, are what computer processes deal with. As streams become more complicated, it becomes increasingly important to characterize their properties, which may be only weakly correlated with the properties of the agents they connect. .NH 1 AUDITING .XL yj .PP Audit records are kept with selectable intensity by the kernel on special audit devices. Audit devices are also available for record-keeping by security-critical programs, such as the privilege server (\*(yl) or the login program. An audit device is associated with an ordinary .UX file by a privileged system call. The file itself becomes unreadable without privilege, but is universally writable. For maximum security, an audit device may be assigned to a data link to an off-line repository. .PP System events are classified into 11 independently auditable categories, selectable by one of four audit masks. All processes are audited at the level specified by a global mask. Individual files and processes may be invisibly .I poisoned to add auditing as specified by one of the other masks. A process that touches a poisoned file becomes poisoned. Poisoning is cumulative and inherited across processes. Poisoning allows the audit level to be cranked up in response to a sensitive or suspicious action or for selected users. .ig It is also important to assure that auditing cannot be bypassed or altered. That assurance might be strengthened by forbidding reductions in the global audit mask or in the complement of audit files. Then auditing could be turned off only by rebooting the system. ..