. \"CW - constant width (typewriter-like) font; macro copied from .B .de CW .nr PQ \\n(.f .if t .ft CW .if t .if !"\\$1"" \&\\$1\\f\\n(PQ\\$2 .if n \{\ . ie "\\$1"" .ul 1000 . el .ul 1 . if \\n(.$=1 \&\\$1 . if \\n(.$>1 \&\\$1\\c . if \\n(.$>1 \\&\\$2\} .. .EQ delim $$ define YES % bold "YES" % define NO % bold "NO" % define cup % \(cu % define cap % \(ca % .EN .hy 14 .if t .ds em \(em .if n .ds em -- .if n .na .TL Multilevel Security with Fewer Fetters .AU M. D. McIlroy .AU J. A. Reeds .AI .MH .AB We have built an experimental .UX system that provides security labels (document classifications), where the security labels are calculated dynamically at the granularity of kernel activity, namely, at each data transfer between files and processes. Labels follow data through the system and maintain the lowest possible classification level consistent with the requirement that the labels of outputs dominate the labels of inputs from which they were computed. More rigid control is exerted over the labels of data passing out of reach of the system to and from tapes, communication lines, terminals, and the like. Necessary exceptions to the security rules (as for system administration, user authentication, or document declassification) are handled by a simple, but general, privilege mechanism that can restrict the exceptions to trusted programs run by ``licensed'' users. Privileges are subdivided; there is no omnipotent superuser. Carefully arranged data structures and checking algorithms accomplish this fine-grained security control at a cost of only a few percent in running time. .PP Dynamic labels should help mitigate the suffocating tendencies of multilevel security. At the same time dynamic labels admit covert channels by which dishonest, but authorized, users can leak data to unauthorized places at modest rates. The system is still highly resistant to other .hw cor-ruption kinds of threat: intrusion, corruption of data by unauthorized users, Trojan horses, administrative mistakes, and joyriding superusers. In most real settings, we believe, worries about potential leaks will be far outweighed by these latter concerns and by the overriding consideration of utility. .AE .PP The standard security mechanisms of the .UX system are, in military parlance, ``discretionary'': protection depends primarily upon the individual owners of data taking care to set permissions on files. Some automatic help is offered: the owner/group mechanism, .I umask, and clean files uncontaminated by old trash from shared disks. The responsibility for further precautions, such as setting owner-only permissions on files in the shared temporary directory, is delegated to programs. .PP A carefully administered .UX system can be quite resistant to penetration. But careful administration is not easy. Great reliance is placed on the probity, accuracy, and vigilance of superusers. It is all too easy for a busy superuser inadvertently to misset permission bits, to execute a Trojan horse[1], .FS .if n na [1] The hoariest of all: a bad guy feigns trouble, and asks a superuser for help. The first thing the superuser does is .CW "cd badguy; ls" . The game is up. The bad guy's own program named .CW ls has been executed by the superuser; it has silently bugged some setuid root program, removed itself, and then called the real .CW ls . .FE to make temporarily unprotected copies of secrets, or to promote unvetted files to trusted status. .PP Because .UX systems are simple enough to be administered by amateurs, whose first interest is in use, not operation, security holes are the rule, not the exception, in real life. A few famous security holes have been distributed in major software. And some add-ons, such as Berkeley's network file system, seem to have been deliberately designed for insecurity. .PP Is there, then, hope of running a .UX system securely? Of course. Lots of systems are run quite soundly today. Raising the question a notch, is there hope of making a .UX system that conforms to government-style security policies? .PP In a sense the answer is yes; .UX systems need less fundamental patching than most to achieve government security goals. But the yes must be qualified. In almost any production system it is difficult, if not impossible, to guarantee that many megabytes of code do not contain one fatal crack that can topple the whole edifice. Such guarantees are especially elusive in environments that change frequently, as do so many typical .UX installations. How can one be sure that no flaws are inserted by any of the software tools\*(emshell, editor, compiler, assembler, library\*(emthat touch new code as it is being installed? .PP In another sense the answer is not so clear. Rigid security measures must surely damage the plasticity that attracts users to the .UX system. Is the conflict so fundamental that a ``secured'' system will lose its appeal? The possibility is very real under ordinary security models; hence we have undertaken a somewhat more flexible approach. .PP We have built an experimental system with mandatory controls: security classification automatically follows data through the system. At the same time we have blunted the vulnerability of the system to mistakes by the superuser. In our system all data files have security classification .I labels, with ``higher'' labels designating more sensitive data. The normal flow of data must be .I up : in general output labels must be at least as high as input labels. A security system also needs escape hatches for declassifying data that is no longer sensitive, or extracting nonsensitive parts from sensitive documents. For this purpose we allow certain carefully designed .I trusted programs to violate the rules and produce output with labels lower than input. .PP We have attempted to provide mandatory, inescapable controls without utterly destroying the basic feel and productivity of the system. To obtain early warnings of snags caused by the controls, we are doing our development work under the system itself. At the time of writing we are working quite honestly and relatively comfortably within the confines of the system. .SH The main idea .PP Each file or process has a label, shared by all data in it[2]. .FS [2] For technical reasons, seek pointers also have labels of their own. Seek pointers are shared between processes; information can flow through a shared seek pointer (via .I lseek ) at a substantial rate\*(emthousands of bits per second. Since a seek pointer is ``written'' into by .I read as well as by .I write, the contents of a seek pointer, unlike the regular contents of a file open for reading, must have a label as high as that of the reading process. Hence the separate label. .FE Terminals and other devices such as tapes have labels that reflect the system's understanding of the clearance of the source to which the device is currently connected. The labels form\*(emalmost\*(ema mathematical lattice. Whenever a system call causes a transfer of data, the labels are checked to ensure that data flows only up the lattice. .PP The security of data explicitly passed among labeled entities is safeguarded. Examples of protected transfers are bytes transmitted by .I read and .I write and bits set by .I chmod . Implicitly set inode data, such as file modification times and link counts, are also protected as far as possible without making the system unusable. .PP Other ways of communicating information, including but not limited to arguments of .I exec , error returns from system calls, file access times, the identity of open files, and otherwise inferred knowledge, we declare to be ``covert channels.'' We have studied covert channels and arranged to throttle or stop completely covert channels of significant bandwidth. In effect we have divided information transfers into ``lawful'' transfers, which honor the US Department of Defense ``Orange Book''[3], .FS [3] .I Department of Defense Trusted Computer System Evaluation Criteria, .R Department of Defense Computer Security Center, Fort Meade, MD, 15 August 1983. This bible has set the terms of discussion for most current work in computer security. .FE and covert channels. Just which covert channels to leave unplugged we have decided by balancing risk versus utility and compatibility. .PP We keep all processes and files at their minimum allowable labels as long as possible. The label of a process will increase only when necessary and only as far as needed to allow reading of inputs. Similarly when the label of a process exceeds the labels of its output files, the file labels will rise. .PP A few system programs must be exempt from the usual label checking. Such programs are granted special privileges\(emfor instance to set the label on a user's terminal at login time, to read foreign tapes, or to perform backups. These privileges are zealously guarded: no program can pass its privileges intact to another or alter a privileged program in any way (aside from removal of privilege). .PP Thus we have three kinds of security mechanism in our system: (1) the usual discretionary permission scheme, based on userid and groupid and the familiar .CW rwxrwxrwx bits, but with the superuser stripped of the right to ignore permissions, (2) the mandatory label scheme, which strives only to maintain correct label relationships, and which pays no attention at all to userid or groupid, not even superuser, and (3) the privilege scheme, which guards the administration of labels and of the privilege scheme itself. .SH Labels .PP A label can be any element of a given finite lattice. In addition there are two nonlattice labels, $NO$ and $YES$. No data may flow to or from a file or inode labeled $NO$; it is effectively blocked out of the system, and can only be readmitted by special arrangement. ``External media,'' such as terminals, tape drives, and raw disks, where labeling is beyond the control of the usual mechanism, are normally marked $NO$. Label $YES$, on the other hand, is universally permissive. Only one file, .CW /dev/null , is marked $YES$. At the moment no other file can gain such blessing, but it might also be appropriate for an append-only audit file. .PP Our lattice is the lattice of subsets of 480 items, represented by 60-byte bit vectors. How these bits are used is arbitrary. For example, the first three bits might represent the customary classification levels\*(emunclassified, confidential, secret, top secret\*(emencoded as 000, 001, 011, 111 respectively. Further bits might represent compartments: 000 100 for Iran, 000 010 for Nicaragua, etc. Oliver North would have been cleared for 111 110. A possible history of a process initially labeled secret (011 000) is: .IP Create a new file .CW north/contragate ; it is labeled (000 000) by default, but writing in directory .CW north causes the label of .CW north to become at least secret (011 000). .br Read .CW iran.data , which, say, is confidential and compartmented (001 100). The process label rises to (011 000)\(cu(001 100) = (011 100). .br Read .CW nicaragua.data , top secret and compartmented (111 010). The process label rises again to (111 110). .br Write .CW north/contragate . The file label rises to (111 110). The directory label is unchanged. .PP Not all labels can change automatically. A label may be ``frozen'', which stops operations that would normally require a label change. In particular, labels of terminals are guaranteed to be frozen, typically at the value determined by login. Suppose our example process had been initiated from a terminal that had been cleared only for top secret Iran data (111 100) and attempted finally to write to the terminal. The write would fail, thus keeping Nicaragua data from a user not known to be cleared for it. Further attempts to launder the label, perhaps through a pipeline like .CW "cat north/contragate | grep ." , would meet the same fate. Only a properly authenticated fresh login (or subsession) can authorize the terminal for the higher label. .PP The idea of a lattice of labels is well known. Our deviation from the strict model, with $NO$ and $YES$, answers needs to regulate entry from places where labels are not under control of the system, and to deal with the important special case of .CW /dev/null . .SH Privileges .PP Our privilege mechanism is simple, but flexible. In its purest form it restricts special powers to trusted users using trusted tools. .PP To some extent the privilege mechanism may be understood as partitioning 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. Largely to avoid rewriting masses of code, the superuser retains most other powers. Thus the superuser can still do damage (to data he is cleared for), but mainly by tedious methods that leave tracks\(emchanging modes and owners. Superuser status must be augmented by privilege to execute powerful restricted system calls such as setting the userid or mounting a file system. .PP We have identified five distinct privileges, listed below, each governed by one-bit .I licenses and .I capabilities, which are separate from labels. A trusted process or file is one with some nonzero capability or license. In the strictest policy regime each privilege of a process $p$ executing file $f$ is determined by the intersection of the process's license for that privilege and the file's capability for the same privilege: .IP $Priv(p)~=~Lic(p)~cap~Cap(f)$. .LP Process licenses are assigned at login, are inherited across .I exec, and may be relinquished at will, never to be regained. Licenses effectively identify trusted users, while capabilities identify trusted programs. .PP The trusted-user-trusted-tool model of privilege may be eased in various ways. It is possible to grant a default ``system capability'', $Cap(s)$, to every file by the rule .IP $Priv(p)~=~Lic(p)~cap~(Cap(f)^cup^Cap(s))$. .LP By setting $Cap(s)~=~bold true$, we can make $Priv(p)~=~Lic(p)$, which means that any program can do magic provided its user is licensed. In such a regime a superuser possessing licenses for all privileges could act with the same impunity as a standard superuser. .PP It is also possible to give a program file a license, $Lic(f)$, making the program ``self-licensing'' for one or more of its capabilities. Then the effective license of a process $p$ executing program $f$ is $Lic(p)^cup^Lic(f)$. Self-licensing is limited by another policy constant, the ``system license'', $Lic(s)$, which is used as a mask. The full formula for determining each privilege of a process is .IP $Priv(p)~=~(Lic(p)~cup~(Lic(f)^cap^Lic(s)))~cap~(Cap(f)^cup^Cap(s))$. .LP In a typical self-licensing case, where $Cap(s)~=~bold false$, $Lic(f)~=~Cap(f)$, and $Lic(s)~=~bold true$, this reduces to $Priv(p)~=~Cap(f)$. In this regime a self-licensed program gets power in much the same way as does a setuid-root program in standard systems, except that the power is not inherited across .I exec. .PP With appropriate settings of the two (compile-time) system policy constants, $Lic(s)$ and $Cap(s)$, our privilege model is able to mimic the disparate privilege features of most current operating systems. In our experimental system we have set $Cap(s)~=~bold false$ for every privilege. We have also also set $Lic(s)~=~bold false$ for the most powerful privilege, ``set privileges''. Thus privileges can be set only by trusted users using trusted programs. .PP The five privileges are: .LP .I Mount. The right to make new data sources or sinks available to the system. One way is by changing a file label away from $NO$; a second is by the .I mount system call; a third is by changing the label on an external medium. A process with mount privilege would normally execute an authentication protocol before actually performing any of these operations. .LP .I Nocheck. The right to read or write data without regard to security label (but still respecting the standard permission scheme). Although mount and nocheck both provide extraordinary access to data, they are qualitatively different. Nocheck handles (and may censor) every suspect bit. Mount opens resources to the whole system\*(ema much more sensitive responsibility. .LP .I "Set licenses. The right to increase the license or ceiling of a process. The principle use for this is in setting up ``sessions'', where a user entitled to play more than one role wishes to suspend one role temporarily and switch to another. Sessions are merely a refinement of .CW su , which changes rights by the crude expedient of changing identity. .LP .I "Set privileges. The right to change file capabilities and licenses. We expect not more than one or two programs to be given this most powerful of all capabilities. In a thoroughly security-conscious installation, only an identified security administrator, different from the system administrator, would be licensed to set privilege. .LP .I "Write uarea. The right to change values, such as userid, that are remembered by the system for the benefit of the process and its offspring. This peculiar capability arises because a child process need not be as highly classified as its parent. Without some control, uarea items (especially BSD group permissions) would provide a covert channel of significant bandwidth. .PP By dividing privileges we promote safety from errors by an omnipotent superuser. At the same time we introduce complexity, which can cut the other way. Thus we have deliberately kept the number of identified privileges small. We have refrained from defining new special roles (for example system administrator, operator, or security administrator) in the superuser tradition. Notions of such roles did influence our choice of privileges and will guide the design of administrators' tools. But the notions seem inappropriate to build in at the ground level: no single administrative model makes sense across the spectrum of real installations. .SH System features .PP To implement the above facilities relatively few new system features are involved: .LP New system calls get and set file labels. Another new system call sets the process label. Privileges and frozenness are set along with labels. Unless executed by a trusted process, the system calls permit only safe changes: labels may not decrease; process privileges may not increase; file privileges may not be changed. .LP A special system call allows nocheck processes to confine their powers to certain files. For example, consider .CW df , which needs nocheck privilege to read the file system device. Its outputs, however, should be subject to ordinary security checks to prevent a mole from getting his message through[4]. .FS [4] If .CW df is exempt from all security checks, the mole can get a message to the standard output this way: .IP .CW df /dev/disk0 /dev/disk1 /dev/disk1 >unclassified .R .LP which produces binary code in the last character of the file names: .IP .CW .nf .ta \w'kbytes 'u +\w'kbytes 'u +\w'kbytes 'u +\w'kbytes 'u dev kbytes used free % disk0 5044 4124 920 82% disk1 4984 4420 564 89% disk1 4984 4420 564 89% .R .LP or, much more quickly, in the clear on the standard error: .IP .CW df secret news 2>unclassified .IP .CW .nf .ta \w'kbytes 'u +\w'kbytes 'u +\w'kbytes 'u +\w'kbytes 'u dev kbytes used free %use cannot open /dev/secret cannot open /dev/news .R .FE .LP Every process has an inherited .I ceiling label, above which the process cannot do any business. This has little to do with stopping ordinary leaks: if a lowly process raises its label high, its output will be high and thus protected anyway. It does, however, cut off some possibilities for mischief with covert channels. And it prevents unauthorized userids from injecting noise in high places. .LP Mounted file systems also have ceilings, both on labels and privileges. File system ceilings may be used to restrict the content of file systems being prepared for export, or to prevent contamination, especially by unknown privileged files, from imported file systems. .LP A directory may be ``blinded.'' Blind directories are immune to automatic label changes and thus provide a convenient way to gather, yet keep hidden, data of disparate labels, as for the temporary directory .CW /tmp. Untrusted processes cannot open a blind directory for reading, and every new file created in such a directory is assigned a random name. A new system call retrieves the name. .SH Implementation .PP Dynamic label changing involves considerable overhead of implementation. It is insufficient simply to add label checks at file open. In principle, labels must be checked on every read, every directory search, and every write, including writes of new entries into directories. When a write check fails, the file label is raised if possible; for a read the process label is raised. Every other process dealing with the file must become aware of the change on a fine time scale; in the worst case a label may change between disk blocks of a long IO transaction. A carefully designed data structure for intra- and inter-process notification of label changes has accomplished this with only a few percent time overhead. .PP Space overhead is another matter. A production-size kernel is considerably bigger than before: about 16K of extra text and nearly 400K extra data for a 500-process system. In partial compensation, uareas are smaller. To accommodate labels, inodes on disk have been doubled to 128 bytes. .PP In effect labels flow along with data. Upon .I exec a process begins with the lowest label possible: the least label that dominates both that of the executed file and that of the arguments. The arguments, of course, have the label of the parent process. However, if no arguments are supplied, as for an ordinary filter, the argument label is taken to be the minimum, or bottom element of the lattice. Thereafter the label of a process changes to keep up with the data that it reads. (Notice that the .I open system call does not read; .I stat does.) In particular labels may propagate through pipes. .PP Similarly files are created with the bottom label. (We accept a narrow covert channel through the mode field.) However, the label of the directory in which a new file's name is recorded must dominate that of the creator; the name could bear secrets. .SH Covert channels .PP Having classified many communication paths as ``covert channels,'' we have an obligation to recognize generic classes of covert channels and to characterize their effectiveness. This we have done. Aside from very narrow ``timing channels,'' most of the covert channels in our system involve unusual behavior: forking enormous numbers of processes or opening enormous numbers of files[5]. .FS [5] One example: create a collection of files named .CW A , .CW B , .CW C , \&... each containing one letter, .CW a , .CW b , .CW c , \&... A high process opens files to spell out a message and does an .I exec with no arguments. The resulting low process reads from the open file descriptors to receive the message at several hundred bits per second. The channel can be throttled by refusing to reduce the label across an .I exec with too many open files. .FE Thus any extensive use of covert channels should be detectable from audit records. .PP A mole could certainly use such covert channels to smuggle out precious small secrets to unauthorized users; however an unauthorized user could not exploit them unaided, except by planting a Trojan horse. We supply a special featureless shell to holders of the most powerful licenses to help keep them away from horses.[6] .FS [6] This shell has no variables, no filename expansion, no compound commands, and no search path. The only builtin commands are .CW cd , .CW exit , and a command to drop privileges. Other command names must begin with slash or dot. .FE We have also designed audit tools along familiar lines to monitor the stability and safety of security settings. .PP We undertook this project because we believe it is desirable to try other models than those implied by thoroughgoing adherence to the Orange Book. In particular we suspect that a faithful Orange-Book .UX system would sacrifice much of the system's productive flavor, with security barriers surprising users at every turn. Dynamic labels should help alleviate the surprises. Moreover, faithful Orange-Book security may be inappropriate in applications where security breaches do not entail risks as final as military defeat. (Commercial users, for example, may recoup damages in court.) In such a setting security priorities are more likely to concern keeping outsiders out, preventing inadvertent leaks by insiders, limiting the chance for mistakes by superusers, frustrating attempts to plant Trojan horses, and reducing the vulnerability of the overall system to a single disaffected superuser\*(emall while maintaining high productivity. Procrustean solutions to curtail covert channels are not so critical.