L4, High Assurance, and Protection
Jonathan S. Shapiro
shap at eros-os.org
Mon Jan 5 21:31:24 CET 2004
On Mon, 2004-01-05 at 12:56, Volkmar Uhlig wrote:
> I think there is some misconception around about L4's thread ids. In L4
> V4 (X.2 is going to become V4 after maturing) threads and address spaces
> are completely independent of each other....
Volkmar:
I believe that I have now asked twice for a URL to this specification.
Can you send me a URL? Otherwise we will continue to waste each other's
time. Please accept my apologies that, in the absence of this document,
I may have done so.
If it was on one of the L4 web sites, I failed to see it.
> Threads execute in an address
> spaces, but they can migrate. A thread ID is a communication-endpoint
> place holder. If you have, say, 100 threads in an address space and you
> want to hide that fact you can use a single thread serving as a
> distributer. Since we have local IPC the distribution can completely
> take place in user land without a kernel invocation. The worker can
> impersonate the distributer for the reply.
This sound like a very good thing, and it almost certainly addresses the
issue of "revealed thread ids".
> > While I do not advocate any particular implementation strategy, let me
> > give an *example* of one that might suffice: a simple hash table.
> > Instead of using the PCB address as the process ID, the
> > kernel could use
> > H(sender kernel ID, requested-recipient-ID) as an index into a hash
> > table and perform a single indirection (and possible hash bucket
> > chasing) to find the process address. This is fundamentally the design
> > proposed by Trent several years ago.
>
> You immediately run into replacement policy issues.
If there is a faster way, great! But protection is not merely a desire.
It is a hard requirement. *Every* mechanism I know about for achieving a
protected interface carries a fundamental cost somewhere. You can do it
with address space traversal, or you can accept the need for a
replacement policy, or you can do something else, but you are going to
pay *somewhere*.
My problem is that performance cannot be used to justify fundamental
insecurity. Speed at the cost of correctness is simply unacceptable.
> > In general, I like the map/grant model very much, but in some
> > systems it is necessary for the manager to know who has what mappings.
>
> > In these systems, having applications perform mappings directly to
> each
> > other creates a consistency problem.
>
> Here the argument is around IPC redirection (which is arguably
> expensive). By sticking an interceptor in between you know which
> mappings go in and out. That way you can control it. But I suspect
> that fine-grain control over mapping privileges makes sense. The
> question is what this granularity should be--page or mapping in general.
>From a security perspective, the problem is with the presence of mapping
operations at all. Mapping establishes a high-speed, mutable channel, so
it tends to undermine reference monitors.
My preferred model is that performing a send with a mapping on a
disabled descriptor would be treated as an access violation, and a
suitable exception would be delivered to fault handler. I don't want to
pay any indirection cost for the legal (non-mapping) IPCs.
> > The problem with the first method is that it requires protected
> > recipient descriptors.
>
> You can transparently drop the mapping if it is not allowed. Since the
> guarantees whether a page is mapped or not come from the pager hierarchy
> it is only as strong as all combined pagers. By adding a
> non-guaranteeing pager in the hierarchiy you are set.
>From a security perspective, failing silently is *always* a mistake. It
also makes virtualization difficult if somebody wishes to be backward
compatible with the interface later. You are describing a situation in
which a sender has done a known-illegal operation, but no fault is
generated? This doesn't seem like a good design.
> > The problem with implementing only the second method is: what
> > thread id should a page fault handler receive from a faulting thread?
> > Restricted or non-restricted? I can argue for either depending on what
>
> > kind of system I am trying to build.
>
> That raises the question whether the pager is privileged or not. Since
> the pager can be set by the thread the pager can be changed and the
> thread could elevate its privileges. Or did I misunderstand you?
It is a big problem for the pager to be settable by the thread. There
are some systems in which this can be permitted, and other systems in
which it **must not** be permitted. Because there exists systems in
which this must not be permitted, the operation must (at a minimum)
involve invocation of a trusted party.
Perhaps there is some third design possibility that I have not
considered carefully enough, but it appears to me that a high-assurance
system constructed on top of L4 must be built exclusively using trusted
pagers. While it is possible, in abstract, to use untrusted pagers in a
descriptor-based system (as EROS does), the L4 map/grant operations
don't appear to provide enough book-keeping controls to be trusted.
shap
More information about the l4-hackers
mailing list