EROS FAQ: Basic Questions About EROS
This document is part of the EROS Frequently Asked Questions list. To return to the main index, click here.
What is EROS?
EROS is a new operating system being implemented at the University of Pennsylvania. The system merges some very old ideas in operating systems with some newer ideas about performance and resource management. The result is a small, secure, real-time operating system that provides orthogonal persistence.
Some unsual qualities/features of EROS include:
EROS will eventually supply a secure, UNIX-compatible environement to go along with it's native environment.
What is a Capability?
A capability names an object and conveys authorities to that object. In a capability system, a program must hold a capability to an object to do anything to it. There are no file systems, no notions of ``user identitity,'' and no other way to access objects. A detailed introduction to capabilities, including a comparison to access-list architectures (UNIX is an access list architecture) can be found in the essay What is a Capability, Anyway?
Harrison, Ruzzo and Ullman proved in 1976 that access list systems cannot prevent a program from disclosing information to anyone in the system. This means that users cannot trust programs with sensitive information unless they can inspect the source code.
Capability systems can prevent such disclosure. They are therefore the only foundation we know of today on which systems that handle sensitive information can safely be constructed.
A few access list system vendors claim that their systems are secure. This usually means ``resistant to attack from outside.'' This makes no guarantees about what will happen when a user runs a bad program that has been installed on the system. Bad programs are very common. How many of the millions of lines of code that went into the operating system and utilities on the system you are running now do you think were inspected for security flaws? Never mind the operating system. How about just your copy of Netscape or Internet Explorer (or whatever browser you are using)?
Both of these browsers have had a number of serious security flaws in every revision to date. Active content is making matters worse.
Active content is making matters worse. Did you know that there is a demonstration web page that will shut down your windows system if you load it into your web browser? There is another that will write an electronic check withdrawing money from your account if you happen to use Quicken.
Such problems can be prevented in capability-based systems.
What is a Capability System?
A capability system is an operating system or hardware system in which protection is enforced by capabilities. See the What is a Capability? entry, above.
What is Persistence?
Different systems use the word ``persistence'' to mean very different things.
In EROS, persistence means that the system periodically saves a copy of everything you are doing. If your dog trips and knocks the plug out of the wall (don't laugh - my dog actually did this to me), EROS will restart wherever it last saved your work, complete with windows, applications, and everything you typed.
Typical configurations of EROS save what you are doing every 5 minutes. In practice, this seems to be often enough to prevent major losses.
How are Capabilities Different From Access Control Lists (ACLs)?
This question has two variations:
If you are asking the second question, you want to look at the answer to Aren't Capabilities and ACL's Equivalent?, below. You might also want to look at What is a Capability, Anyway? if you have not already done so.
At the most basic level, the difference between the two approaches lies in where they stick access control information.
In an access control list (ACL) system, every process is assumed to act on behalf of a particular user, and the user identity of this user is associated with the process. Every object has attached to it a list of access rights for each user. Access rights are things like read, write, execute, and own. The ``own'' right allows the user to grant additional authority to any other user.
To access an object, a typical ACL system requires that the program perform some operation (e.g. open) to obtain a descriptor to the object. In most real ACL systems, the access list is examined only once at the time of the open rather than with each operation. A very few systems check the access list with each operation. The reason that most systems check only at open time is that the check is expensive and the implementation tricks to make it efficient are complicated.
A capability system, in contrast, attaches all the authority to the object descriptor. Capabilities (which contain the descriptors) can be passed directly from one program to another; the open step is unnecessary. Since the only way to name an object (i.e. to say ``I want to manipulate that thing'') is to hold a capability, the permissions check becomes very simple. The system already knows that the user has access to the object because they hold a capability; all that is needed is to find out if they have the authority to do the operation they asked for.
If you are a UNIX developer, you may be thinking at this point that capabilities smell a lot like UNIX file descriptors. That is pretty much correct, though capabilities do not have any state equivalent to the current file offset. Once you get past the open call, the UNIX file interface is essentially a capability interface for reasons of performance.
Why aren't capabilities and ACL's equivalent?
I recently received email that asked:
In "What is" you say that one can't build a capability system on top of an ACL system. In practical terms I certainly agree with you but I wonder if this is true logically; i.e. if I manufacture enough identities and enough ACL entries can I not let in the same principals and keep out the same principals in both cases?
The short answer is ``no.'' There are several reasons why:
Most users do not have the authority to create new user identities in the system.
Access is dynamic, not static. Ignoring the own right (see below), you could conceivably set up an initial system configuration that granted read, write and execute permissions in exactly the same way when the system first starts running.
The minute that a new file is created or a new process begins running, the parallel construction of access rights will break down.
In an access list system, there is no way to grant object access to exactly one program.
Consider a relatively simple problem of authority transfer: Process A has created a new object C, and wishes to transfer to B and only to B the right to access C.
In an access list system, C is owned by userA, and B is running on behalf of userB (user A and user B might not be the same). The only way for A to grant access to B is to add userB to the access list for C.
The catch is that user A has no way to know what other programs are running on behalf of user B. All of these programs will gain access to C when userB is added to the access list for C.
There is no way to grant object access to a single program B without potentially granting access to other programs as well.
In a capability system, the transfer is restricted to program B, because the capability is transfered only to program B. The default situation is that other programs do not gain access to the object.
In fact, the problem in capability systems is the other way around: sometimes you do want lots of programs to have access to a new object. The solution, in short, is to grant all of those programs access to a common directory object when they are created, and insert the new object into the directory. A key point, however, is that very few programs actually need this authority.
Thanks to Mark Miller for permission to reuse the picture illustrating the behavior of the capability system. The variant for access list systems is my own, and I'ld welcome suggestions on how to improve it.
In an access list system, there is no way to prevent the owner of an object from granting rights to an arbitrary user.
In the preceding example, we quietly assumed that B was a service operating on behalf of A.
Suppose instead that A is a service operating on behalf of some program D (not shown). D is the creator of C, and has given A access to C. In the new scenario, we are trying to prevent A from passing this access to B.
In an access list system, this cannot be prevented. A is free to create some new object or interprocess communication channel and grant B access to it. B can then use this channel to tell A what it wishes to know. A performs the required operations on C and transmits the answers to B.
There are some people who think that restricting the system calls A can perform will somehow help. This is not so:
We could prevent A from creating new objects, but it works equally well for B to create the object.
We could prevent A from opening or reading or writing objects (or some combination of these), but then A could not gain access to C, which we intend for it to have.
We might add the program code for A to the access list and treat program A as though it were a user. This strategy is used by Microsoft's Authenticode technology.
This approach is easily defeated by a debugger. We create a new copy of A, cause it (by means of the debugger) to open C, and then replace the program image with anything we desire.
Fundamentally, what is needed to solve this problem is object-oriented protection, which is exactly what capabilities provide.
In a capability system, anyone holding a capability can transfer the rights it conveys, but only if they have the authority to communicate with the recipient. Note that if they have this authority they are already in a position to provide proxy service, so prohibiting the transfer is pointless.
In our scenario, A can only transmit capabilities to B only if A holds a capability to B. The solution, then, is to properly restrict the initial capabilities held by A. This is the service performed by the EROS constructor.
A might still create new objects and give them the C capability, but this cannot be used to cause access to C to leak. Just as A cannot transfer the C capability, it cannot transfer any of the capabilities to these new objects to B.
As an aside, note that this restriction is not possible in a ``password capability'' system, because there is no way to determine what capabilities A initially holds.
Why does the difference between capabilities and ACLs matter? Give an example.
Here are some examples that may illustrate the differences:
Capability systems have no notion of user. The permissions system is therefore less complicated and more flexible.
A new service application can define its own notion of authentication and identity without needing to have access to a system password database and without compromising the rest of the machine.
A program running on behalf of a service-specific ``user'' will have only that authority that the service grants it. It does not run with the authority of the server process simply because the server happened to have a particular user identity.
Capability systems have no equivalent to the UNIX root user or the Windows sysadmin user identity. There is no user who has total authority.
When a trusted service (say, the email processing server) is compromised in an access list system, the end result is that an unauthorized outsider gets the authority to do anything that the service can do. Even if care has been taken not to run those programs with special authority, it is common for users to leave certain files and directories publicly writable, and those files and directories can be compromised.
With things like email becoming active (i.e. reading the email message causes a program to run), the mail agent need only compromise the user's mail file to compromise the user on an ACL system. When the user later goes to read their mail, the mail reader will start up the program described in the email, and that program will run with the full authority of the user reading the mail.
In a capability system, both effects are contained. The user (or the administrator) can define a restricted environment that mail programs run within, and can thereby prevent such damage from occurring. The mail transfer agent, for its part, runs with no special authority. It has access to the user's mail files, and these can be compromised, but it does not have access to anything else.
Capability systems have no notion of user.
In a capability design, it is not possible for a capability-protected program to open up your electronic check processing file and post a new check made out to the program author unless you permit it by granting access to the object holding the check records.
There is an ActiveX component running around out there that will do this to you if you happen to be a Quicken user. There are holes in all current Java implementations that would permit a suitably crafted Java applet to do the same thing.
Please scrutinize the check ledger carefully before letting any electronic payment orders get off your machine.
Capability systems have no equivalent to the own right.
A restricted program therefore cannot overcome its restriction by granting access to an unrestricted program.
Copyright 1999 by Jonathan Shapiro. All rights reserved. For terms of redistribution, see the GNU General Public License