"BL" == Ben Laurie email@example.com writes:
BL> I'll admit to being that person. A capability is, in essence, an BL> opaque bound method. Of course, for them to be much use, you BL> want the system to provide some other stuff, like not being able BL> to recreate capabilities (i.e. you get hold of them from on BL> high, and that's the _only_ way to get them).
That seems like a funny defintion of a capability. That is, you seem to have chosen a particular way to represent capabilities and are using the representation to describe the abstract idea. A more general definition might be: A capability is an object that carries with it the authorization to perform some action. Informally, a capability can be thought of as a ticket. The ticket is good for some event and possession of the ticket is sufficient to attend the event.
A capability system must have some rules for creating and copying capabilities, but there is more than one way to realize those rules in a programming language. I assume you're suggesting that methods be thought of as capabilities, so that possession of a bound method object implies permission to invoke it. That seems like a reasonable design, but what about classes or functions or instances?
The problem, which rexec solves after a fashion, is to prevent unauthorized copying of the capabilities, or more specifically of the access rights contained in the capability. That is, there's some object that checks tickets (the reference monitor). It needs to be able to inspect the ticket, but it shouldn't be possible for someone else to use that mechanism to forge a ticket.
The problem for Python is that its introspection features make it impossible (?) for pure Python code to hide something. In Java, you could declare an instance variable private and know that the type system will prevent client code from accessing the variable directly. In Python, there is no private.
Rexec provides a way to turn off some of the introspection in order to allow some confinement. If you can't extract the im_class, im_func, and im_self attributes of a bound method, then you can use a bound method as a capability without risk that the holder will break into the object. On the other hand, if you want to use some other kind of object as a capability, you must be sure that there isn't some introspection mechanism that allows the holder to get into the representation. If there is, rexec needs to turn it off.
The problem with rexec is that the security code is smeared across the entire interpreter. Each object or instrospection facility would need to has to have a little bit of code that participates in rexec. And every change to the language needs to taken rexec into account. What's worse is that rexec turns off a set of introspection features, so you can't use any of those features in code that might get loaded in rexec.
The Zope proxy approach seems a little more promising, because it centralizes all the security machinery in one object, a security proxy. A proxy for an object can appear virtually indistinguishable for the object itself, except that type(proxy) != type(object_being_proxied). The proxy guarantees that any object returned through the proxy is wrapped in its own proxy, except for simple immutable objects like ints or strings.
This approach seems promising because it is fairly self-contained. The proxy code can be largely independent of the rest of the interpreter, so that you can analyze it without scouring the entire source tree. It's also quite flexible. If you want to use instances is capabilities, you could, for example, use a proxy that only allows access to methods, not to instance variables. It's a simple mechanism that allows many policies, as opposed to rexec which couples policy and mechanism.