Re: Split Capabilities: Making Capabilities Scale Jonathan S. Shapiro (shap@eros-os.org)
Sat, 1 Jul 2000 07:42:14 -0400

I've held off on responding to this thread, partly because I wanted to let the idea sink in and partly because I'm packing a house at the moment, which has me a bit distracted. These comments span several of the emails that have gone back and forth.

First off: Hi, Alan. I'm very glad that you can now talk about e-speak. It looks like a strong piece of work.

> The problem is the number of capabilities I need to deal with. After all,
> my PC has over 60,000 files on it. In the most general case, I need a
> conventional capability for each operation, e.g., read, write, execute,
for
> each file. Some applications, SAP comes to mind, have hundreds or
thousands
> of methods, each of which I might want to control separately.

There are really two issues hiding in this statement: total capability count and manageability.

I think that the total count is not per-se a problem. To expand on your example, your file system on your PC currently *has* 60,000 capabilities, only they are called inodes or vfat entries. Encrypting these entries does not inherently alter any of the issues arising from the number of them you have. Distribution may, and I haven't thought that issue through.

The manageability argument is more compelling, but if we examine your file system we soon note that the file system itself doesn't treat its objects as a flat space. It has internal organization (directories) and deals with subsets of the larger capability pool. To the extent that directories in the file system grow too large, they become unmanageable by human users. This, however, is not a result of using capabilities. It is a result of having too many things to designate. Whether the designations are capabilities or filename paths, there are two many distinct names for the human to manage. I claim that this issue is fundamental: in any system having a large number of objects that must be designated individually for operational purposes the namespace management problem will arise.

Finally, I think that the "general case of one capability per method" claim is mistaken, though it's a natural mistake given the way that the literature has presented capabilities. Contrary to what the historical presentation has claimed, capabilities do not authorize operations in real systems. I think that the following is a better way to think about what is going on:

Each object has an interface containing all

of the methods that exist on that object. For each object, there are some number

        of "thinnings" of that interface. For
        example, there may be a thinning for
        operations that can be performed under
        read-only authority.
    Each of these thinnings has a corresponding
        capability.

While shifting to this model doesn't change your claim in abstract, it does shift attention in a way that makes clearer why the abstract claim doesn't matter. Databases may have thousands of methods, but if they *were* individually controlled the database would have too many interfaces to be an engineerable software artifact, and the product would soon die for reasons having nothing to do with capabilities.

That is, either the number of capability variants per object is very small or the system design won't work for other reasons.

> Wildcards are often used to reduce the number of capabilities needed, but
> this approach is dangerous and not general enough. What happens if I put
a
> private file in a directory that has an outstanding wildcard capability
> granting read access to general users?

By wildcard, I assume that you mean wildcard on user identity. This implies a hybrid access control design. I'm not inherently opposed to hybrid systems, except insofar as bastardizing the protection model leads to the kinds of problems you identify (along with a host of others). Wildcards have been used in a few hybrid systems, but not in any capability system, because there is nothing to wildcard *on*.

The most thoroughly developed hybrid of this form is probably Karger's thesis (SCAP). Paul went to a hybrid model because neither he nor Boebert could see how to do multilevel security in an "unmodified" (Karger's term) capability system. It turns out that adding transparent indirection is all you really need, though a "weak" access right definitely helps. See the paper by Weber and Shapiro in the 2000 Symposium on Security and Privacy.

E is a "pure" capability model, and therefore has no wildcarding. So far, it does not appear to need any.

> We could also
> list all the relevant objects in the capability, but I don't think I want
to
> pass around a capability listing the 50,000 files on my system that you
can
> read.

You seem to be assuming that this is frequently necessary. In my experience it is not. These capabilities can almost invariably be stored in some "directory" object, and then a single capability to the directory object can be generated.

As an aside, I'ld argue that it is *rarely* the case that users may wish to share objects in bulk, and *never* the case that correctly designed programs should do so. Up to a point, the fact that capabilities means that they reinforce good design practices.

> The repository has an entry containing a number of fields for each
> registered resource. One of these fields is a list of pairs each
> consisting of a reference to an e-speak capability and the access
> rights granted when that capability is presented.

I think this is an interesting design. It's not appropriate in an operating system because of the number of dynamically allocated access records involved, but it has much to recommend it at the language level. A few questions:

If you pass an e-speak capability to me, and I pass it to Mary, how do you revoke mine without revoking hers? Injecting a wildcard filter can probably handle that, but now what about the case where you want to revoke capabilities that I hold except those held on my behalf by a particular trusted program?

How are access rights protected, given that they do not appear to be cryptographically secured? One of the important qualities of a vat is that if you compromise one vat you cannot compromise the next. I can imagine wire protocols that would achieve similar protections for e-speak, by shipping traditional capabilities over the wire, but all of the methods that I can see for doing so raise hairy consistency challenges in the context of object caching. In particular, one cannot guarantee that permission downgrade occurs promptly in the distributed case.

> In the case of multilevel security, I can cover
> all cases with only one e-speak capability per
> security level, and each user gets only one
> capability.

I think that this illustrates a flaw, and possibly a fatal flaw. If there is one fundamental advantage to true capabilities, it is that they make exactly this sort of aggregation hard. The aggregation you propose violates the principal of least privilege. Worse, it encourages the construction of programs that violate this principal routinely.

The reason this may be fatal is that one cannot assume that the programs are well behaved. Indeed, where security is taken seriously, we must assume that at some point somebody will slip us a trojan horse. In the design you propose, a single trojan horse can destroy everything I have access to *unless* I carefully restrict the capabilities that are handed to the trojan program, at which point we start to move to a design pattern in which I have to go to a lot of extra work to reconstruct traditional capabilities using the split capability mechanism.

> There's still a problem with the approach you describe. Namely, over time
> I'll accumulate a large number of capabilities. Either I'll have to
present
> them all on each request, in which case the permission checking will take
a
> long time, or I'll need a way to track which ones I need for each request.

First, let's be clear that "I" is a program, not a user. It is very easy for programs to track what capability goes to what. When was the last time a production version of a program you ran got its file descriptors confused?

Also, I'ld suggest that as a design pattern you want the program to present specifically the authorizing capability with each operation that it performs. This provides a form of scoping around the exercise of authority, and this scoping appears to be a very useful thing in reducing security-related errors.

> Besides, we can't really use that approach [the directory of capabilities
> approach] in e-speak because of the
> additional latency. The two step process you describe doubles the
latency.
> That's because in e-speak the holder of the strong capability is a
service,
> not an object.

In KeyKOS/EROS it's also a service, though it helps that the systems are not distributed.

Jonathan Shapiro