On the Genode Book
I like the way they begin as they describe where OS’s are found.
I would add that the OS is somewhat like a police function that makes each of the several functions of the device survive on the merits of the code directly and indirectly supporting that function, without relying on the merits of other code in the device.
(Actually no, We get there only for capability systems.)
Quote:
The low complexity of separation kernels comes at the cost of being inflexible.
Because the hardware resources are partitioned at system-integration time, dynamic workloads are hard to accommodate.
The rigidity of the approach stands in the way whenever the number of partitions, the assignment of resources to partitions, and the software running in the partitions have to be changed at runtime.
SeL4 does not dynamically assign objects to DRAM.
Particular DRAM is allocated to an object for its lifetime.
In short seL4 does not swap.
This would have been wildly impractical for Keykos in its time and as the paragraph above suggests, too expensive for many purposes today.
VM/370 was an early virtual machine host which delivered virtual machines with few object attributes.
VM/370 swapped.
Quote:
The trusted computing base (TCB) of all commodity general-purpose operating systems is measured in millions of lines of code.
It comprises all the software components that must be trusted to not violate the interests of the user.
This includes the kernel, the software executed at the system start, all background services with system privileges, and the actual application software.
That is in interesting description of the TCB.
There is the issue of programs that are not programmed to “violate the interests of the user” but:
- have the authority to do so,
- and receive external messages,
- and are vulnerable to obeying them as code.
In their figure 1 I presume that the small squares denote pieces of code.
At least most readers will take it that way.
Apple seems to have thought that way as they incorporated pieces of Mach.
That interpretation explains the inclusion in the red area of a box that is not in the direct call chain of the box at the top of the red area.
The point is that some piece of code may be vulnerable to malformed calls from some of its clients to cause it to abuse its authority.
Yet that does not impact the security of other users of that code.
The reason is that there is one code body but two objects that obey that code and the corrupted object lacks the authority to damage the other object.
Some code bodies, or behaviors, by their charter, need not be shared among mutually suspicious users.
They need not survive malicious calls.
Other behavior, by its charter, must distinguish its callers since what one caller says effects how it responds to another caller — shared abstracted state between mutually suspicious users.
Quote:
A Genode system is structured as a tree of components where each component (except for the root of the tree) is owned by its parent.
This is a common Keykos pattern but it is not enforced.
The kernel is aware of no hierarchy but only who has what caps.
It takes space and time to do something and unless someone gave you a bank cap for space and meter cap for time you won’t do much of anything.
Calls to create something invariably(?) include capabilities to a bank and a meter.
These last two points may be related.
When two objects obey the same code for customers of diverse interests, they should be incommunicado and consume space and time from their customer’s resources.
You need flexible concepts of space and time via caps to achieve this, I think.
Page 12 lists four desirable characteristics of a system and suggests that Genode is the first to embrace them all.
I think that Keykos and Coyotos embraced all of those earlier.
The following is based on an incomplete view of Genode.
I write it here and now lest I forget.
Apple, as best I can tell, devotes just one object to a behavior and this object is shared between all who need that behavior.
Contagion!!
If the b-tree directory object has a flaw that corrupts when some particular call is made on it, other customers are effected.
Indeed the shared object has shared state that can be scrambled upon corruption.
When implemented as in Keykos, a user can rely on the object as long as he does not perform this particular bad call.
The is no state scrambling for there is no object where state from two clients exists.
One client may corrupt its object but that cannot effect a sibling object for lack of authority.
This is a weakness of Mac OS, as far as I can tell.
I may be wrong about Genode in which case I will excise this text to another file.
Quote:
Components are able to trade resource budgets along the branches of the tree.
This way, components can offer services to other components without consuming their own resources.
It is not as bad perhaps as I thought.
I think the following must be the common practice.
The space where the state of an unshared object lives must come from whoever the object serves, and the served has neither read nor write access to that space.
Quote:
make run/demo KERNEL=linux
Genode has division lines in place that I had not dreamt of.
Genode can in some sense run on a variety of kernels.
Running on top of Linux is a convenient debugging scenario.
They enumerate some extant kernels that I did not know of.
Known platforms:
- Linux
- ambient
- nova
- NOVA microhypervisor
- hw
- (Ordinary NOVA has Linux between Genode and real hardware.)
- seL4:
- (still experimental)
- foc:
- Fiasco.OC
- okl4:
- Originally from Open-Kernel-Labs
- pistachio:
- L4ka from Karlsruhe
- fiasco:
- Technische Universität Dresden
This is sort of the converse of the VR for legacy apps that I describe.
Quote:
For example, a network driver accesses a physical network card and provides a bidirectional stream of network packets to another component, which, in turn, may process the packets using a TCP/IP stack and a network application.
Even though the network driver and the TCP/IP stack cooperate when processing network packets, they are living in separate protection domains.
So a bug in one component cannot observe or corrupt the internal state of another.
I would add that each component has its own invariants clearly separated from the other.
There may be invariants that relate the states of these two components, but those should be written respecting the abstractions in place.
Quote:
Like a pointer to an object, that can be used to call a function of the pointed-to object, a capability can be used to call functions of its corresponding RPC object.
I fear the impression that any function may be called.
In Keykos the domain is the entity known to the scheduler and there cannot be ‘two threads’ in a domain for the Keykos domain is the closest thing to a thread in Keykos.
The code that the domain obeys has exclusive access to the state of the object defined by the domain.
I also fear that the caller is supposed to know the spelling of the name of the function.
This description might lead the reader to imagine that for any user mode mode code that there are messages that it cannot process.
On the other hand it does nail down some important notions from the language theory perspective.
Quote:
The transfer of a capability from one protection domain to another delegates the authority to use the capability to the receiving protection domain.
This operation is called delegation and can be performed only by the kernel.
The word “delegation” leaves the connotation that the protection that sends the cap has a superior status to the domain that receives the cap, and the kernel is supposed to recall this after the transfer is done.
In Keykos the relation between the two domains with a cap to the object, is symmetrical.
Quote:
Only the owner of an RPC object is able to destroy it along with the corresponding object identity
A clear difference between Genode and Keykos.
Keykos logic is:
- Destroying an object is an act.
- All acts are via some capability.
- All capabilities may be sent in messages.
- The authority to delete an object is delegable.
Another difference is that the kernel allocates space in the c-list, as Unix decides on new fd values.
A creation call site in Keykos expects a new capability to be returned and says in the key invocation setup, where to put the new cap.
This was in analogy to performing a multiply operation where the instruction names the register which is to receive the product.
Quote:
Once the object identity for an RPC object is gone, the owner can destruct the actual RPC object.
There seems to be just one thing here in Keykos, both conceptually and really.
Quote:
Once the object identity for an RPC object is gone, the owner can destruct the actual RPC object.
This sounds as if the capabilities are facets on an underlying object implemented by the Genode ‘protection domain’.
This is welcome in this context.
The map is:Genode | facet terminology
|
protection domain | object
|
RPC object | facet
|
Figure 6 suggests to me that when a protection domain receives a new cap as it is called, the kernel looks to see if the domain already holds that cap.
I think this may reveal things that some would object to.
I shall think about it.
If it is done efficiently it provides a form of synergy.
Page 46
More Genode notes