[Python-Dev] Capabilities (we already got one)

Zooko zooko@zooko.com
Tue, 01 Apr 2003 11:47:56 -0500


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

 Guido wrote:
>
> Yes.  That may be why the demand for capabilities has been met with
> resistance: to quote the French in "Monty Python and the Holy Grail",
> "we already got one!" :-)

;-)

Such skepticism is of course perfectly appropriate for proposed changes to your 
beautiful language.

More on the one you already got below.  (I agree: you already got one.)


> > Here's a two sentence definition of capabilities:
> 
> I've heard too many of these.  They are all too abstract.

There may have been a terminological problem.  The word "capabilities" has been 
used for three different systems -- "capabilities-as-rows-of-the-Lampson-access-
control-matrix", "capabilities-as-keys", and "capabilities-as-references".  
Unfortunately, the distinction is rarely made explicit, so people often assert 
things about "capabilities" which are untrue of capabilities-as-references.  
(Ping has just written a paper about this.)

The former two kinds of capabilities have major problems and are disliked by 
almost everybody.  The last one is the one that Ping, Ben Laurie and I are 
advocating, and the one that you already got.

Anyway, if someone gave a definition of capabilities-as-references and it 
didn't match with the two-sentence definition I gave (and with the diagram), 
then it was wrong.

Here's the two-sentence definition again:

> > Authority originates in C code (in the interpreter or C extension
> > modules), and is passed from thing to thing.
> 
> This part I like.
> 
> > A given thing "X" -- an instance of ZipFile, for example -- has the
> > authority to use a given authority -- to invoke the real open(), for
> > example -- if and only if some thing "Y" previously held both the
> > "open()" authority and the "authority to extend authorities to X"
> > authority, and chose to extend the "open()" authority to X.
> 
> But the instance of ZipFile is not really a protection domain.
> Methods on the instance may have different authority.

Okay, ZipFile was the wrong example.  Here it is without examples:

Abstract version: A given thing "X" can use a given authority "S" if and only if 
some thing "Y" has previously held both the authority and the "authority to 
extend authorities to X" and chose to extend "S" to X.

To make it concrete, I will use the word "object" to mean "anything referenced 
by a Python reference".  This includes class instances, closures, bound methods, 
stack frames, etc.  When I mean Python's instance-of-a-class "object", I'll say 
"instance" instead of "object".  So the concrete version is:

Concrete version: An object "X" can use an object "S" if and only if some object 
"Y" has previously held references to both S and X, and chose to give a 
reference to S to X.


(Quoting out of order:)

> > Hm.  Reviewing the rexec docs, I being to suspect that the "access
> > control system with unified designation and authority" *is* how
> > Python does access control in restricted mode, and that rexec itself
> > is just to manage module import and certain dangerous builtins.
> 
> Yes.
[...]
> Sure.  The question is, what exactly are Alice, Bob and Carol?  I
> claim that they are not specific class instances but they are each a
> "workspace" as I tried to explain before.  A workspace is more or less
> the contents of a particular "sys.modules" dictionary.

I believe I understand the motivation for rexec now.

I think that in restricted-execution-mode (hereafter: "REM", as per Greg Ewing's 
suggestion [1]), Python objects have encapsulation -- one can't access their 
private data without their permission.

Once this is done, Python references are capabilities.

So if you have a Python object such as a wxWindow instance, and you want to 
control access to it, the natural way to do that is to control how references to 
it are passed around.

This is why you've already got one.  The natural and Pythonic way to control 
access to Python objects is with capabilities, and that's what you've been doing 
all along.

However, you don't use the same technique to control access to Python *modules* 
such as the zipfile module, because the "import zipfile" statement will give the 
current scope access to the zipfile module even if nobody has granted such 
access to the current scope.

This is a violation of the two-sentence definition and of the graph: the current 
scope just gained authority ex nihilo.

So your solution to this, to prevent code from grabbing privileges willy nilly 
via "import" and builtins, is rexec, which creates a scope in which code 
executes (now called a "workspace"), and allows you to control which builtins 
and modules are available for code executing in that "workspace".

Now access to modules conforms to the definition of capabilities: an object X 
can access a module S if and only if some object Y previously had access to X's 
workspace and to S, and Y chose to give X access to S.

So unless I've missed something, rexec conforms to the definition of 
capabilities as well.

(Of course, one can always build other access-control mechanisms on top of 
capabilities.  In particular, the rexec "hooks" mechanism seems intended for 
that.)

Regards,

Zooko

http://zooko.com/
         ^-- under re-construction: some new stuff, some broken links

[1] http://mail.python.org/pipermail/python-dev/2003-March/034311.html