[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

The EROS Constructor

From: Jonathan S. Shapiro
Subject: The EROS Constructor
Date: Tue, 11 Oct 2005 16:24:11 -0400

My XMMS example will need to wait for tonight, because I need to go meet
my wife, but I think I can finish the constructor explanation without
getting divorced.

In EROS, the basic mechanism for process construction is called a
"constructor". I think that if I explain how the mechanism works and the
relationships that it enforces, some of the other things I have said
will become easier to understand. At the very least, I will be able to
walk people through how these apparently strange relationships are

Suppose you are a developer. You compile a program, and you wish to be
able to create new instances of it. Here is how you proceed.

First, your linker builds a program image in memory, pretty much in the
normal way.

Next, it goes to the "metaconstructor" (this used to be called the
"constructor constructor", for reasons that will shortly become clear,
but that is just impossible to say out loud). The metaconstructor is a
server that is part of the system TCB. It is available to everyone. The
job of the metaconstructor is to create new, empty constructors. Like
the metaconstructor, a constructor is trusted system code that is part
of your TCB.

The linker performs a "make constructor" call on the metaconstructor.
The linker provides a space bank and a schedule. In return, the
metaconstructor builds a new, empty constructor instance. For the
moment, I will call this a "??? constructor".

The linker now starts installing capabilities. It turns to the the "???
constructor" and makes a series of calls of the form:

  When you are asked to create a new process, it should be created with
  the following capability (an argument) at the following location in
  its initial image.

Some non-obvious "locations" include "the schedule capability slot",
"the address space slot", and a few other slots of the new process

Eventually, all needed capabilities have been inserted, and the linker
says to the "??? constructor"

  seal yourself

After the seal() operation, the "??? constructor" changes state, and no
more capabilities can be added. The "??? constructor" will now agree to
create new instances of whatever program it knows how to create.

[Note: this same mechanism is used by the application installer.]

At this point, I will imagine that we have been building a constructor
for a program called foo, and we will now call this new constructor the
"foo constructor".

The sealed constructor is now placed in a directory, which is how you
get it.

Now let's look at what happens when you want to create an instance of

If you entirely trust the developer, you go to the "foo constructor",
you hand it a space bank and a schedule capability, and you say "make me
a foo". It responds: "Congratulations! You are now a foo!" Okay. Maybe
not, but this needed some humor somewhere to see if you are still awake.

You hand the foo constructor a space bank and a schedule capability, and
you say "make a new foo". It creates a new process using storage from
this space bank, inserts the schedule capability, inserts all of the
capabilities previously specified by the developer [or the installation
package]. The constructor sets this new foo instance running to
initialize itself. Eventually, the new foo instance returns to you. As
part of this initial return, it passes you a capability to itself.

The first problem with this protocol is that you might not trust the foo
developer. Suppose the developer is your girlfriend and "foo" is really
a phone book application. You may want to know, before you create an
instance of "foo", that your list of *other* girlfriends should not be
disclosed, because you are a foolish male and you are worried that they
will be more interested in her than they are in you. After all, you are
a hacker, and we do not bathe frequently.

[Have I mentioned that my students think I should hire a staff
cartoonist to capture these bad metaphors?]

But since *you* control your portion of the initial capabilities, the
only way this could occur is if the initial capabilities held by the
"foo constructor" include some way to talk to your girlfriend.

This is where it becomes important that the constructor is trusted
system code. *Before* you create the "foo", you can ask the "foo
constructor" the following question:

  *If* I were to create a new instance of "foo", would it have
  any capability to the outside world other than the ones that
  I provide?

It turns out that the constructor knows enough to answer this question
"yes" or "no" in O(0) time (yes: in unit time). As long as it answers
"no", you know that you are safe. If it answers "yes", then you should
perhaps consider not storing your phone book using this tool.

But there is one more problem: you may not be talking to an "official"
constructor. How do you know that you can believe that this is a
constructor at all?

Well, it turns out that every constructor can identify the processes
that it has created [this is the identify operation that we have
previously discussed]. This includes the metaconstructor. So you can go
to *your* metaconstructor capability and ask it: "is this foo
constructor really an official constructor?"  If it says "yes", then you
know that the foo constructor will not lie to you.

Good. But how do you know about the metaconstructor capability?

You know about the metaconstructor capability because it was provided to
your account by the system's account creation software. You trust it
because somebody on the EROS team wrote that, and because the system
simply doesn't let the administrator screw around with that list at all.
This is the end of the chain of trust, because if you don't trust that
you shouldn't be running EROS anyway.

Now: this CAN be spoofed. If an attacker can convince something in your
process hierarchy to use a metaconstructor provided by the attacker, AND
get you to invoke a fake constructor at the same time, then the whole
chain will fall apart pretty quickly.

But then, you can cut your hands off with a blunt tooth pick if you work
at it hard enough. The point here is not that it is impossible to hurt
yourself, but that it is really pretty hard to do if your shell is not
aggressively stupid. In an environment where the users are naive, a
reasonable administrative decision might be to restrict creation of new
constructors to the installer. You and I might not like that system for
*our* use, but in some environments it would be appropriate.

This all sounds impossibly complicated the first time you read it, but
it actually isn't. In fact, this mechanism for creating processes is
significantly faster than fork+exec!

In my next (and final) note on this subject I will describe how to
exploit this tool to build a version of XMMS that can safely use plugins
that are **actively** hostile (i.e. not just buggy).

Then I will back off for a while so that these ideas can have some time
to settle, and I will try not to introduce any new ideas for a little


reply via email to

[Prev in Thread] Current Thread [Next in Thread]