Just to avoid any confusion. Can you tell me if I got this right:
There are three possible ways to restict/allow communication between threads, using
* Thread IDs (current L4 v4 implementation) Any thread can communicate to any thread and send any message. Access checks need to be done by the server, that might need to verify some things using another 'security' server, requiring another IPC. The IPCs itself are very fast because no table lookups are necessary to verify if the communication is allows. However suity holes are much easier to created by buggy code that forgets to verify some accesses. Additionally the security checks are executed even slower than if they where done inside the kernel as in the other two methodes. These security checks can be done automatically using IPC redirection. This still requires an additional IPC, had some strange (unclean) quircks associated with it and I still doubt wether this methode is secure especially when used by buggy programs.
* Virtual Thread Objects (possible L4 v5 implementation) Each thread has a kernel table attached to it (1) which lists the threads it can communicate to. These virtual thread objects can be grranted, mapped and unmapped just like flexpages. So when a message is received the server can be sure it is send by a thread that is mapped it's thread ID to.
(1) Threads in the same address space might share the same table.
* Capabilities (current EROS implementation) Capabilities are similar to Virtual Thread Objects except that they have a server defined word attached to them.
I first want to make clear why the second and third methode are much better than the first:
* Methode 1 is insecured when used with buggy programs. The fact simply is that most, if not all, programs are buggy. I agree with shap that the cost of a program should be measured in total resources used (dollars or additional programming time for example) and not just computational resources. * In a system that requires security the 2nd and 3rd methodes are actually faster because only a single, cimple kernel check needs to be made agisnt several complex user checks for methode 1 (is this realy true? comments please). L4 is designed to be secure anyway and is therefore already to slow for systems that don't require security, so the penalty the insecure systems woudl suffer does not apply. * Additional security benefits are that the internal thread structure is not revealed to every program running on the system and some protection against DoS attacks is offered.
Now I want to make clear why capablities are much better than virtual thread objects:
* The extra word does not seem to decrease performance in any way (is this true?) so it a free feature, that can be used but doesn't have to. * The server defined word will probably be used to store a pointer to some client specific data structure containing important information that needs to be access often. You might say, yeah well mbut you can calculate this address from the sender ID, but this no longer works when clients start to grant and map server objects/capabilites to eachother, because the server doesn't know about these actions, unless some complex, slow protocol is used to update the serves information.
My conclusion is that Virtual Thread Objects/Capabilities are far supiror than just using Thread IDs and that the server defined word of Capabilities are very important to manage information of a server. The size of the capability should be equal to the pointer/word size of the machine.
Constructive criticism is very much appreciated,
Rudy Koot
_________________________________________________________________ Hotmail en Messenger on the move http://www.msn.nl/communicatie/smsdiensten/hotmailsmsv2/
Rudy:
Sorry for the delay in reply.
First, some corrections on specific statements that you made, because they are potentially distracting from the real issues. Then I will try to answer your questions.
Corrections:
1. L4 IPC speed has relatively little to do with the "direct lookup" aspect of thread ids. Any indirect encoding will carry a cost, but in terms of the overall performance of IPC this cost is quite small.
2. Security checks done in the server vs. the kernel are not necessarily slower or faster. It depends greatly on what security checks you wish to do. I argue that:
a) *many* (not all) of the security checks currently done in L4 servers could be eliminated if kernel-protected bits existed in each descriptor
b) For some types of systems (capability systems), disclosure of the sender id is an absolute violation of design requirements, so any microkernel that relies exclusively on server-side security checks based on sender-id is not a universal microkernel.
c) More specifically, any microkernel that requires checks based on sender-id is entirely unsuitable as a platform for EROS-NG.
Now to answer your questions:
There are really two things being controlled:
1. Who can *send* to a given server 2. How the server determines what actions a sender is permitted to invoke.
Ignoring clans and chiefs (which we all agree is too expensive and inflexible), here is how the three schemes break down:
Thread IDs: No restriction who can send. Server makes decisions based on sender-id
Mapped Threads (Virtual Thread Objects) Sender can only invoke a thread that is mapped in their thread space. Server still makes most decisions based on sender-id
Capabilities: Sender can only invoke a thread descriptor that is mapped in their thread descriptor space (thread space) Server makes decisions based on a field that is encoded within the descriptor. No sender-id is transmitted.
And then, here is the hybrid mechanism that I have proposed:
Hybrid: Sender can only invoke a thread descriptor that is mapped in their thread descriptor space (thread space) Server makes decisions based on either (a) a field that is encoded within the descriptor, or (b) the sender-id.
** Sender-id is software controlled by the thread manager, and can be set to zero for all threads to simulate capability behavior.
- In a system that requires security the [virtual thread] and [capability]
methods are actually faster because only a single, simple kernel check needs to be made against several complex user checks for [thread-IDs] (is this really true? comments please).
I think this is true, but it is not so straightforward.
In the thread-IDs design, there are two distinguished phases in the server-side security checks:
1. Object resolution. Based on sender-id and arguments, determines the identity and permissions of the server-implemented object that has been invoked. This phase may conclude that no such object exists.
2. Permissions check. Given the object identity and permissions, make a decision about whether the particular operation is to be permitted.
All of the bits needed for phase 2 can be encoded in the descriptor. All of the expensive parts of the current L4 protocol lie in phase 1 (object resolution).
Now I want to make clear why capablities are much better than virtual thread objects:
- The extra word does not seem to decrease performance in any way (is this
true?) so it a free feature, that can be used but doesn't have to.
I believe that this is true, and the evidence of the EROS implementation seems to support this view.
- The server defined word will probably be used to store a pointer to some
client specific data structure containing important information that needs to be access often. You might say, yeah well mbut you can calculate this address from the sender ID, but this no longer works when clients start to grant and map server objects/capabilites to eachother, because the server doesn't know about these actions, unless some complex, slow protocol is used to update the serves information.
This is a possible usage. In our experience, the more common behavior is to have a pointer to some data structure that describes a server implemented object (i.e. has nothing to do with any particular client), and reuse the low bits for permissions. For example, the pointer might point to a file metadata structure, and the low bits might indicate read and write permissions.
The size of the capability should be equal to the pointer/word size of the machine.
This can't be true, since the capability must encode both the destination thread id and also the extra word. Minimum practical size is two machine words.
shap
l4-hackers@os.inf.tu-dresden.de