>"Most of today's operating-system kernels, for example the Linux kernel, are highly-complex pieces of software that contain everything needed to manage resources (e.g., memory), access the hardware, store information on a file system, handle network packets, and control user processes. Therefore, such a kernel requires the privilege to control the whole machine. The left side of the figure illustrates such a monolithic operating-system kernel.

The high functional requirements and the broad range of existing hardware causes such a kernel to grow huge. Users expect different network cards to be supported, different file systems, a wide variety of network protocols, and a lot more.

Consequently, a typical Linux kernel contains far more than 500,000 lines of code.

It is impossible to fully avoid bugs and security leaks at a system of such scale. Bug-prone code in the kernel can corrupt the proper operation of the whole system and thus, can impose fatal consequences. As illustrated in the right side of the figure, a broken network driver can corrupt the whole operating system.

With virtual address spaces, modern operating systems and hardware platforms provide mechanisms to isolate concurrently running user applications. Each user application runs within a dedicated address space and interacts in a safe, well-controlled manner with other user applications only via mechanisms provided by the kernel. This way, the kernel effectively protects user applications from each other.

Microkernel-based systems use these techniques not only for user applications but also for device drivers, file systems, and other typical kernel-level services. Therefore, the effect of a bug-prone component is locally restricted. The microkernel withdraws all non-needed privileges from each component and thereby shrinks the overall complexity of code running in privileged mode by an order of magnitude compared to a monolithic kernel.

For example, a typical microkernel of the L4 family is implemented in less than 20,000 lines of code.

As illustrated in the figure on the right, all components are protected from each other by address spaces. Thus, one component cannot inspect or corrupt other components without proper authorization. Communication between components can only happen by using communication mechanisms provided by the microkernel. If one component of the system gets corrupted by a bug or an attack, the fault is locally restricted to the broken component. Furthermore, the microkernel enforces CPU time scheduling and can grant guaranteed processing time to user processes. No de-privileged system component is able to violate such guarantees. Therefore, a microkernel can safely execute sensitive applications, de-privileged system services, and large untrusted applications side by side on one machine.

Whereas microkernels deliver fault isolation and separation of concerns well in theory, in practice, this is only half of a solution because all those de-privileged components must be appropriately organized to make the approach effective. Because, by definition, a microkernel does not implement policy but only mechanisms, the policy must be provided by someone else. One approach is the introduction of a central policy management component with a global view on the whole system, controlled by a specially-privileged administrator. The complexity and manageability of a centralized policy, however, depends on the scale of the system.

In contrast,

Genode extends the microkernel idea of de-composing the operating system code to the idea of de-composing also the system policy by imposing a strict organizational structure onto each part of the system."

Related:

https://github.com/genodelabs/genode