[Python-Dev] Re: Capabilities

Zooko zooko@zooko.com
Mon, 10 Mar 2003 15:11:04 -0500


(I, Zooko, wrote the lines prepended with "> > ".)

 Jeremy Hylton <jeremy@zope.com> wrote:
>
> > Until you have a substantial Least-Privilege-respecting library you can't gain 
> > the big benefit of capabilities -- code which is capable of doing something 
> > useful without also being capable of doing harm.  (You can gain the "sandbox" 
> > style of security -- code which is incapable of doing anything useful or 
> > harmful.)
> 
> If you need to rewrite all the libraries to be capability-aware, then
> you need to trust everyone who writes library code to understand
> capabilities and be thorough enough to get them right.

With capabilities, as with any other security regime, you can execute code while 
denying it access to any of the standard libraries.  However if you want to 
provide code access to some of the standard library's privileges without 
providing access to all of them, then you in any possible security regime need 
(a) some way to express which privileges it gets and which it doesn't, with 
sufficiently fine granularity that you can grant the privileges you want while 
excluding those you must, and (b) when actually executing the code you have to 
choose which specific privileges to extend.

In a capability secure language the first step, (a) is done by the language 
designer.  Then the library designer provides a library of bundles of 
privileges, and then (b) a programmer executes the code, passing to that code 
all and only those privileges which he wants that code to have.

The library designer's job is actually pretty easy -- just: 1.  try to make 
privileges which are likely to be wanted separately conveniently separable and 
2.  try to make privileges which are likely to be wanted together conveniently 
bundled.

If the library designers err on either side, the application programmer can 
patch it up.  For example, suppose the library designer made it so that a single 
object, the "os" object, contained both the "os.system()" method and the 
"os.times()" method, and the programmer wants to extend the ability to get a 
timestamp without extending the ability to invoke arbitrary commands.  (Note: 
I'm aware that os is a module and not an object, but for now I want to think of 
it as an object to be passed by reference instead of as a modules to be 
"import"'ed.  If we continue along the cap-Python path we'll have to come back 
to this.)

So the programmer just defines a proxy:

class osproxy:
    def __init__(self, os):
        self.os=os
    def times(self):
        return self.os.times()

and gives an instance of osproxy instead of the os object itself.  (In practice,
when it is only a single method, you would of course prefer to just pass the 
method itself.  The proxy pattern is more general.)

If the library designer has erred on the other side, making separate objects for 
each of a dozen different related and innocuous functions, the programmer will 
very likely define one object which contains all of those functions and pass a 
reference to that object where he would have had to pass a dozen references to a 
dozen functions.

I may have made too big a deal about this originally.  I just spent a few 
minutes browsing through modindex.html (parts of which I am already intimately 
familiar with), and nothing jumped out at me as needing to be wrapped or 
refactored before it could be used in a cap-Python.  Perhaps the Python Standard 
Library's natural modularity has already gotten us most of the way there.


> > http://www.erights.org/elib/capability/ode/ode-capabilities.html#patt-coop
> 
> I don't see the part of this paper that talks about library design :-). 
> I assume that it's the first section "Only Connectivity Begets
> Connectivity."  But I don't know if I understand how that applies to
> library design in concrete terms.

No, "Only Connectivity Begets Connectivity" is just the "pointer-safety" 
requirement -- that one can't get a reference to an object, except by either 
(a) creating the object, or (b) getting the reference from some other object 
which already had the reference.

Hm.  Yes, that page doesn't really talk about library design.  The authors of 
E performed a project [1] for DARPA in which they implemented a web browser 
which could host pluggable renderers, such that a malicious renderer was 
constrained in the damage it could do.  (I have no idea what DARPA wants with 
such a thing.  ;-))

The security review team at the conclusion of the project (which included great 
cryptographer David Wagner) wrote [2] that E appeared to have advanced the state 
of the art without breaking a sweat.  The security flaws that they uncovered 
were mostly due to insufficient wrapping of the Java standard libraries.  For 
example, the E folks had allowed an object to access a Java "File" object so 
that it could access a single file, without realizing that the Java File object 
has a "getParentFile()" method which returns the parent directory.

That was why I made such a big deal about the importance of a secure standard 
library in my previous message.  (As you know, Python's file objects don't have 
a "getParentFile()" method, so we're already one step ahead of Java there...)

Regards,

Zooko

[1] http://www.combex.com/tech/darpaBrowser.html
[2] http://www.combex.com/papers/darpa-review/index.html