At Thu, 13 Oct 2005 14:13:21 +0200, Marcus Völp voelp@os.inf.tu-dresden.de wrote:
Jonathan, yes so far L4.Sec does not support such an operation. We thought about (I think Bernard Kauer and Marcus Brinkmann already had a discussion on this topic on l4-hackers) adding a compare operation on endpoints which allows you to match identity of two endpoint capability (compare permissions provided). So far we are not sure whether such an operation is really needed or whether you want to construct systems the way you do. The fundamental issue is that a potentially trusted capability is handed to a server by a not completely trusted source (the client C).
It is true that this is a property of Jonathans example. But in my discussion with Bernhard we established, I think, that the lack of a cmp operation also prevents other scenarios, including:
Invoking RPCs that have capabilities as arguments (for example a server-side copy operation).
Reference monitoring. In this case, trust is not necessarily involved, although it can be.
We thought briefly about two general solutions to this problem:
- obtain a version of this capability from a trusted source, or,
- prepare and defend against potential misbehavior of the invoked server.
ad 1: This solution assumes a network of trusted "name"-servers and protocols that require the client C in order to share a capability with some other process S that it establishes this sharing with the target of the capability (D). C can do so by giving its name to S to D and asking D to share the rights S can then request a capability to D from its trusted nameservers and ask for the shared capability provided it trusts D.
Please keep in mind that we did not build such a system yet and that it is only a preliminary and potentially not working solution.
If your "name" is a simple string of binary octets, then you are talking about unprotected capability systems, which don't offer adequate security.
If your "name" is a capability to an endpoint, then you are talking about a capability server, and that requires a cmp operation because you have to provide the capability you "name" as an argument to the request to retrieve a "trusted copy".
So, with reasonable assumptions, such a design requires a cmp operation at least. But please note: I have tried, quite hard, to make this work. Although I believe you can formally satisfy all logical requirements (ie, race-free protocols to do all the operations you want to do), the effort required is not reasonable, nor is the result usable. This applies to all variants of L4 I have heard so far, including Espen's work and the L4.sec work. Maybe someone smarter than me can fix that, but in my view this requires more changes to L4 than the addition of a cmp operation.
BTW, the protocol you describe doesn't even work, as in L4.sec there is no way for "C" to name "S" in its request to "D". Introducing such names, which would have to be authenticated, is impossible if C and S have a certain asymmetric trust relationship. However, there _are_ protocols which work, and I have worked them out (you can ask me for more details). They all require RPCs in which capabilities are passed as arguments and can be identified by the receiver, for example using a cmp operation.
Also, this proposal does not address the general case where an operation must be performed on more than one capability, like server side copy operations.
ad 2: Alternatively the server can prepare to defend against misbehavior of D. In L4.Sec the receiver of an IPC controls the location where an incoming message is placed. Thus it can select an area of its address space so that even if D replies with bogus content, S is not harmed. It remains, however, the problem of blocking S. An easy way to defend against blocking attacks is to fork of a thread for this particular client's request and let it invoke the pot. untrusted capability on behalf of the client. Other thread invoking the same server are not affected by this blocking.
This proposal achieves nothing. First of all, there is no benchmark that tells you when you have waited long enough and the capability should be rejected, for example because the destination blocked too long. But even more seriously, there is no benchmark to decide when the capability is good and its implementation be trusted. Thus, this proposal does not achieve the original goal at all.
It's nice that I can create a new thread to restrict the damage caused by a blocking RPC partner. But it has nothing to do with what you want to achieve in Jonathans example.
Again please keep in mind that both are preliminary solutions. We have still to construct a system on top of L4.Sec. Also please note that L4.Sec is not a fixed API but has experimental status and that we welcome both suggestions for improvement and requirements. However, you will find that features will be added only if they cannot be implemented on top of L4.Sec with a reasonable effort. This is one of the fundamental rules which in my opinion contributed to the success of L4. So please apologize my stubbornness in this point. Compare might be such a feature which will get added if we find no way to achieve what Jonathan listed in his mail.
You addressed this note to Jonathan, but I hope you will not mind if I share my opinion on it. From my perspective, it is totally fine that you are conservative in what you adopt for your design and implementation. It's also fine to have a focus on certain aspects of the system and leave other aspects completely aside.
But I am rather puzzled by your suggested preliminary solutions. The first doesn't work, and the second doesn't address the problem at all. At least to me they don't offer any insight into the following questions:
1. Is the design pattern actually desirable?
2. If yes, can it be _efficiently_ supported by the L4 architecture with a reasonable effort?
Thanks, Marcus