[Python-Dev] Re: rexec.py unuseable

Luke Kenneth Casson Leighton lkcl at lkcl.net
Tue Dec 16 11:16:03 EST 2003

On Tue, Dec 16, 2003 at 07:13:21AM -0800, Michael Chermside wrote:

> I (Michael) wrote:
>     [Speaking of how to provide restricted execution in Python]
> > Actually, I rather prefer the approach that has been mentioned before
> > of trying to use capabilities. 
> > See, for instance, the threads on
> > Capabilities found here: 
> > http://mail.python.org/pipermail/python-dev/2003-March/thread.html#33854

> Luke replied:
> > capabilities, acls, schmapabilities, same thiiing :)
> No... they're not. Read the thread I mentioned above, or read this, 
> and some of the other documentation for the language E:
>   http://www.erights.org/elib/capability/ode/ode-capabilities.html

 no offense intended: i'll read that later, i'm running out of time.

 without going into too many definitions, consider what i am advocating
 to be _like_ an access control list but instead to be a capabilities
 control list, instead.

 a "capabilities list", where it's a list ordered on a
 per-caller-function-name basis [with a special wildcard function name
 called "absolutely everything"]

> Later Luke writes:
> > btw yes you're right, it's better off called "capabilities"
> > but the name CCLs - capability control lists - is a bit of
> > a mouthful :)
> Again, I mean something different, NOT CCLs, but capabilities.

 anyone have a one-para summary of the difference between
 capabilities and access control lists?

 even if it's "access control lists are lists of capabilities"
 which i don't know if that's true.

 access control lists are typically made on a per-user basis,
 but what i am recommending in _this_ case is that a "user"
 be considered to be a *function*.

 so maybe i _do_ mean access control list and should stick to my
 guns, here :)


 is the difference between capabilities and access control lists
 simply that capabilities lists restrict caller-function rights
 and access control lists restrict user rights?

> Hmm... how about a quick summary from me (but I'm not an expert).
> Suppose that had some code which had an object representing a
> directory, with a method "open(filename, mode='r')" that opened 
> files in the directory. Given this object, you could imagine 
> constructing new objects with more limited capabilities. For 
> instance, you might create a readOnlyDirectory object which had
> a method "open(filename)" that didn't allow specifying the mode
> as anything but 'r'. Or you might open a file and then pass a
> file object with "read()", "write()", "seek()", and other such
> methods, which would only access that file.

 [i'll have to read this in more depth later, i'm out of time, sorry]

> So _IF_ the only way to access files were through this object (and
> that's a BIG if), then you could imagine a world where HAVING and
> object was equivalent to being able to do something. If a bit of
> code had access to a read-only-file object then it could read that
> file, but couldn't write to it, or do anything else with the file 
> system unless it ALSO had access to some OTHER objects. That's
> capabilities... and it would work for most kinds of restricted
> resources, not just the file system. The key idea is that HAVING
> a pointer to the object is equivalent to having the permission to
> USE that object, and whatever it provides access to.

 [again, i'll have to read this in more depth later, i'm out of time,

> There are several ways to "escape" out of this system. One way is
> to access some global ability... for instance, you might use the
> "open()" function from __builtins__.  

 i would expect __builtins__.open() to have _its_ own mmm...
 capabilities list, and _if_ that list contained a permission
 for the restricted function to "execute" it, then _yes_ it
 would be allowed, but otherwise no, definitely not.

 therefore, the author of the [new] rexec.py module should simply
 be a matter of creating the right ACLs, and applying them.

 in the case of __builtins__ it could be a matter of just applying
 a capabilities list of one item:
 	[("all functions and modules", DENY, "write, apply-to-sub-objects")]

 and that would be _it_!
 all functions in __builtins__ would be dealt with, and restricted!

 of course, i don't believe it will be _quite_ that simple, but it


> For capabilities to work in
> Python access to "dangerous" globals would need to be restricted.

 simple: apply a capabilities list that denies dangerous actions, on
 all such "dangerous" globals.


 one important "permission" is "change acl" of course, which must be "DENIED"!

> Another way is to just create an object out of nowhere, or forge
> a pointer to an object. Fortunately, in Python these are already
> impossible... pure Python code cannot forge references or create
> objects without access to the type or class. (C extensions can
> do anything and are unsafe.)

 that is why i mentioned about "create object" permissions

 if there is a permission/capability whereby the capabilities list of
 a parent object is "inherited" when a create object action is carried
 out, the problem you describe is alleviated.

 _at_ object create time (and object create itself could be a separate
 permission / capability, granted on a per-function and per-module
 basis like everything else), the capabilities are examined.

 what happens is that _if_ the "inherit capabilities" flag is set,
 then the newly created object receives a COPY of the parent object's
 capabilities list.

 ta-da, problem solved.

 this is a _normal_ bog-standard approach that is used in the windows
 nt security model, and has been for over twenty years, now, and if
 you count the VAX/VMS history as well, a lot longer than twenty years.

> Another way is to access the more powerful object that "empowers"
> a less powerful one... perhaps using the (supposed to be private)
> _directory field in the readOnlyfile object. So capabilities in
> Python are impossible without some sort of private data for
> objects (this is not a particularly onerous requirement). Yet
> *another* approach would be to use introspection... for instance,
> in Python today, given any file object, the class itself ("file")
> can be obtained via introspection, and then used to create other
> file objects. Using capabilities in Python would require that
> "restricted" objects have some more limited form of introspection...
> perhaps one could only obtain a "fake" class object which had
> a __equals__ method that simulated being the real class, but
> which had no __init__ so it couldn't be used to create new
> instances.

 i don't quite follow, even after reading the capabilities thread,
 what introspection is.

 but let me try to clarify so you can correct me if necessary:
 introspection is the ability to go via the __XXXXX__ functions
 etc. including the __class__ stuff, yes?

 well, if i follow you correctly, you simply put a capabilities
 list on all those things, or you put one on the entire object.

 or better yet, you put an "inherited" one on the class, such that
 _any_ object created will receive restricted capabilities.


> At any rate, you get the idea. Capabilities are possible in Python
> only if some sort of "restricted mode" is created, which restricts
> access to some built-in abilities and which creates "restricted"
> objects with some private data and limited introspection. 

> But IF
> you had these things (and they're NOT trivial), then capabilities
> may be a conceptually more elegant approach than ACLs, lleading to
> more elegant programs.
  i believe that if you understand what i am suggesting, and i
  hope that filling in some examples above, i believe that what
  i am suggesting covers your concerns.

  the capabilities lists that i am recommending can be applied
  on a per-function and per-object basis and can be inherited.

  in this way, useful restrictions can be made to achieve the
  expected results.

  ... i didn't say, however, that it wouldn't require quite a lot
  of thought about _which_ functions to apply restricted capabilities
  lists to!

  starting, of course, with the "nothing goes" one, and repeatedly
  attempting to run code.


More information about the Python-Dev mailing list