[Python-Dev] Capabilities
Paul Prescod
paul@prescod.net
Sun, 30 Mar 2003 13:59:26 -0800
Ka-Ping Yee wrote:
> On Sun, 30 Mar 2003, Paul Prescod wrote:
>
>>It wouldn't have hurt for you to describe how the code achieves security
>>by using lexical closure namespaces instead of dictionary-backed
>>namespaces. ;)
>
> Sorry. :) I assumed it would be clear.
It probably is for those following the thread more closely.
> That immutability isn't required in order to prevent filesystem access.
Okay, now I see that that's what you meant about "__dict__". You were
talking about the object's. namespace in general, not the magical
attribute named __dict__.
>...
>>del x.__class__.__setattr__
>
> Sneaky. :)
I would have complimented you on the elegance of this proposal but I
thought it might just be a translation of E's object construct. To
whatever extent you innovated in creating it, congratulations, it's very
cool.
> ....In restricted mode you wouldn't be able to do that.
I'm not clear (because I've been following the thread with half my
brain, over quite a few days) whether you are making or have made some
specific proposal. I guess you are proposing a restricted mode that
would make this example actually secure as opposed to almost secure. Are
you also proposing any changes to the syntax?
Also, is restricted mode an interpreter mode or is it scoped by module?
I can't see how it would work as an interpreter mode because too much
library code depends on introspectability and hackability of Python objects.
>>I can't see in
>>this model how to implement what C++ calls a "friend" class.
>
> I haven't tried an example that requires that yet, but two classes
> could communicate through access to a shared object if they wanted to.
This doesn't actually simulate "friend" but that's probably because
friend makes no sense in a capability system.
It occurs to me after further thought that there are two orthogonal
problems. First is privacy for the sake of software engineering. Python
has always rejected that and I'm glad it has (although it makes advocacy
harder). This sort of privacy just gets in your way when you're trying
to coerce code into doing what you want when it wasn't designed to.
Languages like C++ make it really hard to hack when you need to, but
they don't really prevent you from doing it if you are determined
enough, so you have the worst of both worlds.
Second, is safety for the sake of security. IF you have chosen the
capabilities model of security, THEN "friend" perhaps doesn't make
sense. You either have a capability reference or you don't. The code's
compile-time class or package is irrelevant. Allowing classes (as
opposed to objects) to declare each other friends probably only opens up
security holes.
But if you want to have an example of something like this for the record
books, perhaps you could implement an iterator over a data structure
with the caveat that we'd like to implement the iterator and data
structure in separate files (because sometimes the implementation of
each could be large and complicated). I think it works like this:
The Data structure is one capability class. The iterator is another. The
application asks the data structure to create an iterator. The data
structure creates one and passes some subset of its internal state to
the new object. It probably could not (and anyway should not) pass a
pointer to the opaque closure that is its external representation. So
instead it passes in whatever state variables the iterator is likely to
be interested in.
If you did want to emulate class-based "friendship" (can't think of why,
off the top of my head) you could do so like this:
def tellMeYourSecrets(myfriend):
if instanceof(myfriend, MyFriendClass):
return my_namespace()
else:
raise SecurityViolation, "Bug off"
The example in Stroustrop is where you want a vector class to be able to
directly read the internals of a matrix class rather than go through
inefficient method calls. But in a capabilities universe, even matrices
can't, in general, see the internals of other matrices. I guess they'd
have to use the trick above if that was really necessary.
>>If this technique became widespread, Python's restrictions on assigning
>>to lexically inherited variables would probably become annoying.
>
>
> The Namespace offers a possible workaround.
Yes, but why workaround rather than fix? Is there a deep reason Python
objects can't write to intermediate namespaces? Is it just a little bit
of extra safety against accidentally overwriting something? This is
probably overkill in the case of intermediate scopes. And if not, there
could be a keyword which is like global but for intermediate scopes.
> ...
> It would be cool if you could suggest little "security challenges"
> to work through. Given specific scenarios requiring things like
> mutability or friend classes, i think trying to implement them in
> this style could be very instructive.
Unfortunately, most of the examples I can come up with seem to be hacks,
workarounds and optimizations. It isn't surprising that sometimes you
lose some efficiency or simplicity when working in a secure system.
It makes me wonder about whether E might be less fun, efficient and
productive than Python because security is embedded so deeply within it?
(just a speculation...I don't know E) A Python that could go back in
forth from secure mode to insecure mode might be a nice compromise.
Paul Prescod