Re: mapping pages into new address spaces

Joshua Haberman <[email protected]>
Newsgroups gmane.comp.micro-kernel.l4.l4ka.general
Message-ID <[email protected]>
On Tue, Sep 12, 2006 at 03:05:50PM +0200, Espen Skoglund wrote:
> [Joshua Haberman]
> > Let's start from scratch and forget what I suggested.  There is
> > still what I would consider a small but important gap in the current
> > API.  There is no way for a pager to proactively (ie. not in
> > response to a page fault) map pages into the address space of one of
> > its threads in a way that:
> 
> > 1. is not subject to the thread's acceptor
> 
> > 2. can complete even if the thread is not waiting for an IPC
> 
> > Compare this with unmapping.  A thread can unmap at any time using
> > the Unmap system call.  The target threads are not involved.  Why
> > shouldn't there be a similar system call for mapping?
> 
> There is one major difference between map and unmap.  A mapping is a
> transfer of rights to access an object (as well as the information in
> the object itself).  Unmapping is revokation of these rights.  For all
> non-trivial security policies it is important to be able to control
> this flow of rights and information.
> 
> Currently, mappings can only be performed during IPC, and by
> controlling IPC we can therefore control the flow of rights throughout
> the system.
> 
> Now, let's for a moment follow your line of thoughts:
> 
> [...]

I am convinced that your argument is better than mine.  I have some
responses to these points, but since they are not strong enough to
ultimately sway the argument in favor of my proposal, I won't waste
everyone's time with them.

I do, however, want to make one final suggestion, which is a much more
minor change than either of my previous two.  The suggestion is: make
maps/grants from a pager to any of its threads *always* ignore the
target thread's acceptor.

There should be no security implications: a thread has no illusion of
being able to protect its address space from its pager, since a pager
gets to ignore the acceptor every time a page fault happens.

This shouldn't muddy up the API spec or reference manual: instead of
writing in the page fault protocol that maps/grants will ignore the
target thread's acceptor, write this in the section about maps/grants
that they will *always* ignore the target thread's acceptor.  This
actually makes things more consistent, because it makes page fault IPC
more like other IPC.

It shouldn't complicate the implementation, because instead of
saving/restoring MR0 when a page fault happens, you can make the
map/grant IPC path simply skip the acceptor logic if the sender is the
pager for the receiver.  It's arguably a simpler implementation.

And finally, I can't think of a case where threads will want the feature
of having pages from their pager be subject to an acceptor -- the pager
needs to know everything about the thread's address space in order to
properly respond to page faults in it, so the pager should have enough
information to never erroneously map to an area that is already mapped.

What I keep coming back to is that I think maps from a thread's pager
are fundamentally different than maps from anyone else.  A normal thread
will have its acceptor always set to an area of its memory that it
doesn't mind having mapped by anonymous strangers.  But a thread's pager
is not an anonymous stranger -- it is the thread that is in control of
managing the thread's address space.  To do this job properly, it seems
that it should have the ability to map anywhere into its threads address
spaces without making their threads set/reset their acceptors all the
time.

In fact, there seems to be risk in asking clients to set/reset
acceptors.  Let's say that a pager wants to provide an API like mlock()
to its clients -- that is, ensure that a region of the address space is
in RAM and will not page fault.  Because of the acceptor scheme, clients
will have to set their acceptor to the entire address space before they
make this call (or at least to the portion they are trying to mlock()),
and reset it once the call returns.  But suppose that the pager is busy
when the thred makes this IPC, and is not waiting on a receive.  Another
thread is scheduled in, and it sends a map/grant to the thread that
overwrites a mapping it already had.  The thread had no way of making
sure that *only* its pager could take advantage of its weaker acceptor.

Josh
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.