in-image security with multiple image segments

Lex Spoon lex at cc.gatech.edu
Sat Jan 25 21:41:03 UTC 2003


The topic is in-image security.  You have multiple bunches of objects
in an image, and one bunch might try to harm another bunch.  You could
use separate OS processes and hardware memory protection to protect
these bunches from each other, but that makes it hard for *nice* bunches
of objects to cooperate with each other.  Thus, it would be nice to load
them all together into the same image, so that they can cooperate
conveniently.

The common sense of many people is that to have practical security, you
divide these objects into some sort of memory segments.  Those segments
might be called islands, vats, environments, or even something else. 
I'll go with that for now, though it's hardly obvious that this is "the"
way to do in-image security.  (eg, you may want to just use individual
objects!!)


A further intuition many people have is that these segments should
completely segregated so that there are *no* pointers between the
images.  That approach boils down to having separate Squeak processes
(at the OS level), and so it doesn't sound much like in-image security. 
Thus it isn't right to have super-strong protection between images
(unless you want to give up on in-image security).

On the other hand, you can't have completely normal pointers between the
images, can you?  If you did, then you'd essentially just have one
virtual segment that is arranged as a normal one.  You have to either
have a new kind of pointer, or to have checks in the VM for every normal
pointer that crosses a segment boundary.  More on this later.

Now we have special pointers between image segments.  How much can they
be used?  We are probably assuming, for example, that the entire content
of one image segment has become hostile.  In that case, your special
pointers better be limited enough that any valid access to them cannot
cause harm.

What kinds of restrictions would you place?  In the "Islands" work I did
a few years ago, the restrictions were frustratingly strict.  They go
something like:

	1. You do not pass across arguments verbatim: you first sanitize them. 
If you pass an argument across, then the other segment is suddenly
polluted with an arbitrary pointer back into your space, and remember
that we are trying to carefully control the pointers between spaces. 
For simple data like numbers and strings, you can copy the data before
passing it across.  For more complex data, you can either copy it, or
you can provide a new special pointer to it that you pass across. 
That's a pain, so you try to avoid it.

	2. Similarly, you do not pass the response back verbatim.  The
solutions are identical.

	3. You do not create new inter-segment pointers arbirtarily.  Each
inter-segment pointer is giving the segment a new capability (in the
security sense) and thus it needs to done carefully.  The nice thing is
that you can only get a new inter-segment pointer (assuming the VM is
tweaked in various little ways) by accessing an existing inter-segment
pointer.  Assuming you don't have too many pointers between image
segments, your task as a security auditor isn't that hard.


Something to think about is what kind of help you get from VM support
for segments.  If you automate everything, eg automatically creating an
inter-segment pointer from a normal pointer if it is passed to the other
image, then you gain nothing that I can see.

In fact, you don't *have* to have VM support.  There is no "special
pointer" in my "Islands" work.  Instead, the programmer must keep track
of everything.  It's not particularly hard, BUT you get no protection if
some obscure pointer is incorrect.  While it is unclear how much it
helps to have VM help, it is certain that you can get some.  The
question is, how should things be arranged?

I'm not sure.  But consider the case of an arbitrary morph in one
segment, and a World in the other segment that is trying to draw the
morph.  Now devise a secure way for this guy to draw, with bonus points
if your solution is efficient.  The underlying morph is going to send
commands back out to the outside world, and the underlying morph is
going to get input events somehow.  (In Islands, I did this by having a
world within a world, and thus keeping the communication fairly thin.  I
hacked the performance a little by letting the morph's island and the
world's island have shared access to the bitmaps of a form, and then
those bits could be copied out into the world's display...  An
alternative solution is to use something like Nebraska to talk across
the connection....)


Lex



More information about the Squeak-dev mailing list