[Python-Dev] Capabilities (we already got one)
Tue, 01 Apr 2003 11:47:56 -0500
(I, Zooko, wrote the lines prepended with "> > ".)
> 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
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.
> 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 ), 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
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
^-- under re-construction: some new stuff, some broken links