implementing sandboxes with capabilities
withers at vnet.net
Tue Apr 11 22:57:13 UTC 2000
Lex Spoon wrote:
> I didn't follow everything, sorry, but I can reply to this:
:-) Using effective terminology is my bane. My apologies.
There are two major nexii of control, that we need to handle, and I am
continually getting them confused. One nexus is to disallow any
navigation across an edge in the stateful graph of objects (bindings),
yet we still need to have a binding. The other is lookup of a selector
during a msg send. This is where the granting of capabilities would be
It would serve us well to consider this without assumptions about
usage. We should construct this in such a way that it is easily
cross-dialect. We also want to use the different spaces for different
things (OOBD, Security, Remote Objects, Segments). In general, we want
to partition the image into multiple subspaces. These subspaces have
elements, most of which are local and disjoint from other spaces. As
you mentioned, there are two classes of other elements however.
nonlocal immutable elements.
nonlocal mutable elements. (some of which are Behavior objects)
Those elements which are immutable or local should be direct bindings,
however the nonlocal elements should be represented in the local space
as a surrogate (proxy), which can control nonlocal access to the real
thing. This is category theory stuff, isn't it?
Let us create a minimal solution with the most flexibility. The way to
do this may be a construction of a tree of spaces which hold Objects,
some of which are Classes, and some of which are Surrogates, the rest of
which are just Objects. There is a sub-super relationship of spaces.
There is also a sibling relationship between spaces and this is where
the surrogates come in. You *must* use a surrogate to bind to an object
in a sibling (disjoint) space. A subspace can transparently see into a
superspace (no surrogate needed), but a superspace must have a surrogate
to an object in a subspace. This is so a subspace which has a direct
reference to an object in a superspace can't directly access an object
in a different disjoint subspace.
When a surrogate is for a Class, it is a ShadowClassSurrogate which
contains a methodDictionary. The CompiledMethods in a ShadowClass can
do any kind of control they want with a msgSend which selects it for
evaluation. The capabilities are granted by installing a protocol
bundle into the ShadowClass, of a particular Class - FileStream, of a
SubSpace - like my Guest subspace.
The Shared Immutable space is merely the root universal space that all
subspaces can access directly, therefore all pointers are immediate.
The System Classes could be in a subspace, which a capabilities profile
can grant surrogates to when one of us creates a user space.
If this can be done by subclassing the Surrogate from ProtoObject or
creating another root from #nil then great. I am trying to consider a
cross-dialect solution. The point in having a binding is to send
messages to it, right? Therefore, the alternative approach is to
decouple a binding and stick a pumped msg queue in between. Not the
easiest solution as there are pointer management problems like GC and
I would like to think of this from a multiuser standpoint. There should
be no reason that all of us couldn't be processing, in a protected way,
in one image. My concerns are that we rush this without thinking that
generality through. I think having multiple Proxy Subclasses is smelly
and may well cause big problems. A big problem regardless, will be the
administration of capabilities. Another question is what does it mean
to pass a surrogate to another space? All arguments to a msgSend
should transform to the appropriate Surrogate (or direct pointer). The
return should also map.
Let us create a true secure multiuser Squeak. ;-)
> > A better, cleaner approach seems to be one of composition. If we can
> > guarantee a break in the pointer such that instVarAt: and friends can't
> > get to it, then we can guarantee isolation.
> Yes. The primary characteristic of a proxy, in the scheme I've
> sketched, is that it doesn't allow outsiders to traverse past it
> in the object graph. Thus, the two sides are isolated from each
> other, and must use the proxy's methods to communicate. Making
> Proxy a new root class which defines hardly anything, seems like
> a good approach for implementing them.
> The majority of non-proxy objects, which I've been calling "sandbox
> safe" for lack of a better term, are much freer, and can safely do
> instVarAt: and instVarAt:put: as much as they want. They can really
> mess each *other* up, but they can't do any real harm without going
> through one of the proxies. The goal here, is that the vast majority
> of the image can be left as is. To be honest, I'm not *completely*
> sure that it will fall out that way, but that is certainly the goal.
Smalltalking by choice. Isn't it nice to have one!
More information about the Squeak-dev