[Python-Dev] Capabilities / Restricted Execution

James Y Knight foom at fuhm.net
Sun Jul 16 19:20:43 CEST 2006


On Jul 16, 2006, at 5:42 AM, Scott Dial wrote:

> Talin wrote:
>> Scott Dial wrote:
>>> Phillip J. Eby wrote:
>>>
>>>> A function's func_closure contains cell objects that hold the
>>>> variables.  These are readable if you can set the func_closure  
>>>> of some
>>>> function of your own.  If the overall plan includes the ability  
>>>> to restrict
>>>> func_closure setting (or reading) in a restricted interpreter,  
>>>> then you
>>>> might be okay.
>>>
>>> Except this function (__getattribute__) has been trapped inside of a
>>> class which does not expose it as an attribute. So, you shouldn't be
>>> able to get to the func_closure attribute of the __getattribute__
>>> function for an instance of the Guard class. I can't come up with  
>>> a way
>>> to defeat this protection, at least. If you have a way, then I'd be
>>> interested to hear it.
>>
>> I've thought of several ways to break it already. Some are  
>> repairable,
>> I'm not sure that they all are.
>>
>> For example, neither of the following statements blows up:
>>
>>     print t2.get_name.func_closure[0]
>>     print object.__getattribute__( t2, '__dict__' )
>>
>> Still, its perhaps a useful basis for experimentation.
>>
>> -- Talin
>
> I quickly poked around it in python and realized that in 2.5 (as  
> opposed
> to the 2.4 python I was playing in) the cell object exposes
> cell_contents.. blargh. So, yes, you can defeat the protection because
> the wrapped instance is exposed.
>
>      print t2.get_name()
>      t2.get_name.func_closure[0].cell_contents.im_self.name = 'poop'
>      print t2.get_name()
>
> Although, your second example with using the object.__getattribute__
> doesn't seem to really be an issue. You retrieved the __dict__ for the
> Guard class which is empty and is something we should not feel  
> concerned
> about being leaked.
>
> Only way I see this as viable is if in "restricted" mode cell_contents
> was removed from cell objects.

Similarly to how function attributes aren't accessible in restricted  
mode. In older versions of python, it's always been possible to get  
the closure variables in non-restricted mode, via mutating func_code...

def get_closure_contents(fun):
   num = len(fun.func_closure)
   vars = ["x%d" % n for n in range(num)]
   defines = ' = '.join(vars) + " = None"
   returns = ', '.join(vars)+','
   exec """
def b():
   %s
   def bb():
     return %s
   return bb
""" % (defines, returns)
   old_code = fun.func_code
   fun.func_code = b().func_code
   result = fun()
   fun.func_code = old_code
   return dict(zip(old_code.co_freevars, result))

def make_secret(x,y):
   def g():
     return x*y
   return g


 >>> secret = f(5,7)
 >>> secret()
35
 >>> get_closure_contents(secret)
{'y': 7, 'x': 5}








More information about the Python-Dev mailing list