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