Re: CAOS - A CApable OS? [was: Process Authentication Groups (PAGs)] Jonathan S. Shapiro (jsshapiro@earthlink.net)
Mon, 23 Mar 1998 15:05:31 -0500

> In the CAOS model I
> presumed a starting process is put into a 'black box', a can-do-nothing
> position. Since this means that process can't do anything at all, I
> introduced this initial 'request', where the process can state the
> resources that it will need in order to become usefull. It is asumed
> that since the process has been considered by the system as valid to
> start, the process is allowed to state its needs.

There are several problems with this model.

  1. I can think of lots of reasons to start a process with no intention of running it. Postmortem debugging is one. The assumption that the process will be run is therefore a mistake. It may be a template for future processes.
  2. In order to request resources, the process must have sufficient authority to execute instructions and also sufficient authority to speak to the requestee. This implies, at a minimum:
	authority to some CPU schedule
	authority to an address space, and any necessary mappings
	    therein
        authority to the requestee

Pragmatically, it also will in common cases require:

	authority to take page faults, and therefore
	authority to acquire rights to storage

This is quite a lot of authority. Actually, it's most of the authority that most programs will *ever* need.

My belief is that resource requirements are part of the documentation of a program. A sufficient set of requirements is known in advance to get the program started, and should be provided by the party who causes the process to be created.

> I thought of this 'request' when I was thinking about non-cpu-specific
> process startup methods and non-platform-specific system calls and it
> came as an obvious solution which obeys the
> can-do-nothing-without-authorization rule...

As you can see from above, it hardly obeys the "nothing without authorization rule"

> > The best way to keep hold of the capabilities that a process needs is
> > to grant them from the beginning and ensure that they are never lost.
>
> This was the original idea. The 'request' above is the means a process
> can obtain the needed capabilities. But since in the low level we always
> come to the terms of functions, I translated 'capabilities' to
> 'functions that perform specific actions on objects'.
>
> Do you think that this translation is a good thing? I see difficulties
> in managing unnamed objects but at the time I felt that it's worth a
> thought.

I disagree that in the low level we always come to the terms of functions. I think that at the low level, we always come to a function performed on an object. A read call is performed on a file descriptor. An open call is performed on a directory passing a string. etc. etc.

In fact, I cannot think of even one example function that is unconditionally safe on all objects, unless it is one that returns immutable state. The result of such a function never changes, and the function is therefore not useful.

Even being able to ask an arbitrary object something very simple like it's size provides a communication channel between parties.

Indeed, the fundamental security issue is not what functions can be performed, but what objects can be reached. Functions are very broadly classifiable into activities that provide read, write, or read-write access to an object. That plus the identity of the initial objects is sufficient to make arguments about information flow in the system, and therefore about the security of the system overall.

Conceptually, then, it isn't the functions that make or break the security of the system; it's the object identities. From experience in the theoretical security work that Sam Weber and I did, I can tell you that the hard part of the security proofs is establishing the accessability and mutability graphs. The difficulty lies not in the access/mutate part, but in determining which objects lead to access to other objects and how.

> > In a capability system it cannot. The child either holds a capability
> > or it doesn't. There is nothing in the capability that records where
> > the capability came from. Once transferred, the sender has no control
> > over how the receiver uses the capability.
>
> Mhm. So every capability can in every point in time have only one
> holder?

I'm not sure where you got that idea. Perhaps I should have said 'transferred or copied.'

Think of pointers. If you and I each hold pointers to the same object, the pointers live at different locations but contain the same bits. The question is whether you wish to think of these as one pointer or two. Depending on the purposes of our discussion, either answer could be correct. To a garbage collector these are different pointers. For programmer purposes it's often sound to think of them as the same pointer.

In the same way, if you and I hold separate copies of a capability to the same object conveying the same authority, we can speak in either sense correctly. Each capability has a unique holder, but pragmatically it is useful to think of two parties as holding the same capability.

What I was really trying to say is that a capability does not record information about how it has been copied. The holder knows what capabilities they hold, in the sense that they can learn by experiment what those capabilities seem to do. The capability does not know its holder, and in most capability systems a capability invocation does not convey to the recipient any information about the calling process (such a design would be a hybrid protection model).

This is part of what it means to say that holding a capability is a necessary *and sufficient* condition for performing the capability-authorized actions on the object designated by that capability.

> > Observation: while you could build a modified capability system that
> > used hierarchically constrained access rights, you would create to
> > problems in doing so:
> >
> > 1. Undesired communication channels inherent in the access control
> > hierarchy itself.
> > 2. Variable-length capabilities.
> >
> > >From an implementation perspective, capabilities *really* want to be
> > fixed size. Imagine programming a system with variable length
> > pointers...
>
> Hm. Can you give an example of the two mentioned problems?

Sure. Suppose you record hierarchy. You either must bound the depth of the process hierarchy so that you can bound the space required to record that hierarchy of transfers, or you must dynamically resize the capability. If you dynamically resize the capability then preallocating storage for it becomes a mess -- thus the analogy to variable size pointers.

Worse, the space for the dynamically sized capability must come from somewhere, and the amount of available storage in the storage agent is a source of information transfer. By combining downward transfer (allocate storage) with deleting capabilities (free storage) and some error correction coding, a fairly high bandwidth channel can be constructed by querying the amount of space available from the storage manager (several hundred kilobits/second). The guy on the inside transmits data by moving the available storage up and down. The guy on the outside watches the changes in the water level.

Actually, there's a worse problem. In general, hierarchical transfer isn't real desirable. You want any two communicating processes to be able to transfer capabilities, which violates the hierarchy model.

> > The graph shows lines for several choices of X, several crossing
> > speeds, and several numbers of crossings.
>
> Do you have an URL on this?

Sorry, I'm afraid I don't. I believe it appears in one of the L3/L4 papers, which you can find off the L4 web site. I'ld send a URL for that, but Penn's web server isn't cooperating at the moment.

> I picked the term 'capability' because I felt it described quite
> well the basic idea of the model that I'm trying to develope. I was
> not aware of existance of any such systems at the time...

No problem. New ideas deserve new, catchy names.

> The idea that I was (probably in a very clumsy way) proposing is
> quite similar to a hyerarchycal capability model that you were talking
> about.

Hmm. If you will not take it amiss, let's talk about whether the hierarchical restriction buys you. I'ld propose two questions to start with:

  1. Why is it useful to restrict capabilities to hierarchical transfer?
  2. What (if any) marginal security is provided by such an restriction?
  3. What (if any) simplification of engineering arises from this restriction?

In fairness, I should say that I think the answers are (1) it isn't, (2) none, (3) none, actually more complex. I think I can support those answers.

shap