[Python-Dev] In defense of Capabilities [was: doc for new restricted execution design for Python]

Brett Cannon brett at python.org
Sun Jul 9 04:44:40 CEST 2006


On 7/7/06, Talin <talin at acm.org> wrote:
>
> Brett Cannon wrote:
> > On 7/7/06, Guido van Rossum <guido at python.org> wrote:
> >
> >>
> >> On 7/7/06, Brett Cannon <brett at python.org> wrote:
> >> > I guess I am just not seeing where your approach is better than
> >> preventing
> >> > the constructor in 'file' and having open() return the 'file' object
> or
> >> > proxy object.  With your approach 'file' would be flagged, but with
> the
> >> > other you just put the same check in 'file's constructor.  With both
> >> you
> >> > would probably also want open() to be a factory function anyway.  So
> I
> >> don't
> >> > see where you gain simplicity or more security.  It seems like you
> are
> >> > pushing the check into the eval loop, but you still require the
> >> flagging
> >> of
> >> > objects as unsafe.  Going with the other two proposals you don't
> burden
> >> the
> >> > eval loop with the check but the objects that you would have flagged
> in
> >> the
> >> > first place.
> >> >
> >> > It just seems like we are pushing around the flagging of unsafe stuff
> >> and
> >> > that doesn't feel like it buys us much.
> >>
> >> At the risk of repeating someone's point or making no sense (I'm only
> >> following this with half an ear) I would like to point out that as
> >> long as there's C code involved, we can have the equivalent of private
> >> constructors in C++/Java. This means classes that cannot be
> >> constructed by calling the class from Python. C code has to use some
> >> other API to create an instance, bypassing this check. It seems
> >> reasonable to me, even if most popular types *can* be constructed.
> >> There are other types that have this property, e.g. list iterators.
> >> Try type(iter(list()))().
> >
> >
> >
> > Good point.  C code could circumvent the bit check by doing all of the
> work
> > behind the scenes without pushing the object on the stack.  But if the
> > check
> > is in the C code for the object itself it is much harder to get around.
> >
> > -Brett
>
> I may be confused (I usually am), but I think you are misinterpreting
> Guido's point. I think what he is saying is not "you should beware of C
> code getting around the checks" but rather he is pointing out that C
> code that gets around the checks can be a useful part of the system -
> thus the notion of "private constructors", in other words methods for
> creating an object that are normally inaccessible to Python code.
>
> As to your point: I think I am beginning to understand, so let me
> reiterate to see if I have it right.
>
> In the scenario you describe, the open() function is replaced by a
> function that returns a proxy that has limits on what it is allowed to
> do. (Ideally, it would return one of several different types of proxies
> based on the input file path - so a file handle to /tmp would have a
> different set of restrictions than a file handle to /home/me.)


Yep.

Somewhere inside this proxy is the 'real' file handle. We need to insure
> that the proxy is air-tight, so that it can't 'leak' to the outside
> world. (The original motivation for my scheme was the belief that
> air-tightness couldn't be achieved, however the point that Guido makes
> above is beginning to make me believe otherwise.)


The proxy is air-tight by being written in C and holding on to the
reference to the file object in the struct of the proxy.

The proxy also has to be able to support all of the methods that the
> regular file handle can - because we're going to want to pass that proxy
> over to other subsystems that don't know that they are dealing with a
> proxy - such as XML parsers or config file readers. Because the
> permission checks are implemented in the proxy, this means that library
> code using the proxy has exactly the same access restrictions as the
> sandboxed code.


Yep.  Or at least the methods that will be needed (e.g., a read-only proxy
only needs the read()-like methods).

If you want any library code to be able to have additional privileges
> beyond what the sandboxed code can do, you'll need to pass them the
> 'real' file handle, something which can only be done by either the
> proxy, or by a C 'gateway' function. This is not a problem as long as
> the library code doesn't attempt to hold on to the file handle
> (otherwise then the sandboxed code could potentially grab it from the
> library's objects.) So for any case where a library needs additional
> privileges, you'll need to add additional methods to the proxy or create
> the gateway functions to deal with that.


Basically.  A library shouldn't need additional abilities.  If they do they
are not following the security restrictions so it shouldn't work.  It should
be a rarity that a library really needs to sneak around the security of a
proxy to the point of we don't even consider it.  Duck typing should be
enough for this not to be a problem.

So if it truly is the case that the file handle cannot leak into the
> outside world, then you are correct - there's no need to put a check
> into the interpreter. My motivation was based on the belief that there
> would always be a way to get around that, so instead the notion was to
> 'poison' these protected objects so that even if they did leak out,
> attempting to use them in a restricted environment would fail.


At some point we have to trust something.  If you control the constructor,
you shouldn't have to worry about anything getting out since you won't be
able to make anything out of it.

Moreover, there would be no need to even bother preventing such leakage
> - you wouldn't have to change the behavior of __subclasses__ and so on -
> which means that the 'restricted' environment would look nearly
> identical to the normal Python programming environment, i.e. you are
> free to inspect and use __subclasses__ or any other inspection feature
> as long as the result doesn't contain any poisoned objects.


Yep.  I would like to minimize the impact on Python code and what abilities
they have.

(BTW, I'm going to dub my idea the 'poisoned object' scheme, just so we
> have a label.)
>
> While I was typing this, I did realize a drawback to poisoned objects,
> which I will illustrate by the following example:
>
> Suppose we want to grant to the sandboxed program permission to read and
> write cofiguration properties. We don't want to give them arbitrary
> write access to the file, instead we want to force the sandbox code to
> only access that file by setting and getting properties.
>
> This is an example where a subsystem would require elevated privileges
> compared to the main program - the config file reader / writer needs to
> be able to read & write the file as a text stream, but we don't want to
> allow the sandboxed program to just write arbitrary data to it.
>
> The only way to enforce this restriction is to re-wrap the 'real' file
> handle - in other words, replace the 'file-like object' wrapper with a
> 'config-like object' wrapper.


Yep.  But that is just a general issue that you are going to have with any
security system.  It all comes down to where you put your foot down in terms
or restricting access to a resource.

Merely passing the poisoned file handle to 'config' doesn't work,
> because 'config' doesn't know how to safely handle it (only the C
> gateway code can shift the interpreter into a state where poisoned
> objects can be handled safely.)
>
> Passing the file-like proxy to 'config' doesn't work either, because the
> proxy doesn't allow arbitrary writes.
>
> The only thing that you really can do is write another wrapper - which
> is exactly what you would have to do in the non-poison case.


Yep.

-Brett

-- Talin
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> http://mail.python.org/mailman/options/python-dev/brett%40python.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-dev/attachments/20060708/7564ef57/attachment-0001.htm 


More information about the Python-Dev mailing list