Architecture
A minimal trusted computing base, user-space drivers and services, capability-based access control, and IPC as the spine of the system.
The microkernel philosophy
A microkernel is an operating-system kernel reduced to the smallest set of functions that must run in privileged mode. In ONCRIX, that set is exactly three things: scheduling, memory management, and inter-process communication. Everything else — device drivers, filesystems, network stacks, and system services — runs as an ordinary user-space process and talks to the rest of the system by passing messages.
The contrast with a monolithic kernel is structural. In a monolithic design, drivers, filesystems, and the network stack are all linked into a single privileged image; a fault in any one of them is a fault in the whole kernel, and the attack surface running in ring 0 grows with every feature. A microkernel inverts that: each subsystem is an isolated process with its own address space, so a crashing driver takes down a service, not the machine, and a compromised component is confined by the kernel rather than able to bypass it.
ONCRIX takes this seriously as a design constraint, not a slogan. It is an original
operating system written from scratch in Rust — ONCRIX is Not a Copy, Real
Independent uniX — not a fork or clone of Linux or UNIX. The kernel is
#![no_std] and #![no_main], kernel-space crates depend only on
core and alloc, and architecture-specific behaviour is kept
behind the hardware abstraction layer. The result is a small, auditable core that does
as little as possible and delegates everything it can.
Inside the trusted computing base
The trusted computing base (TCB) is the set of code that the security of the whole system depends on — the code that, if it were buggy or hostile, could violate every guarantee above it. The goal of a microkernel is to make that set small. The smaller the privileged core, the less code can hold a fatal bug, the smaller the attack surface, and the more of the system can be reasoned about, audited, and restarted independently.
In ONCRIX the split is explicit:
- Runs in the privileged core: the scheduler (which thread runs next, on which CPU), memory management (address spaces, page tables, the page allocator), and IPC (the message-passing primitives that let isolated processes cooperate).
- Runs in user space: device drivers, filesystems, and system services — each in its own process, each holding only the capabilities it was explicitly granted.
Because drivers and filesystems are user-space processes, they are subject to the same isolation, scheduling, and capability rules as any other program. A faulty storage driver cannot corrupt unrelated memory; a compromised network service cannot reach hardware it was never handed. The privileged core stays small precisely so that this confinement is meaningful.
unsafe is wrapped in safe abstractions
with documented // SAFETY: invariants, production paths avoid
unwrap()/expect() in favour of Result<T, E>
and the ? operator, and the workspace is held to a zero-warning policy.Ten crates
ONCRIX is organised as a Cargo workspace of ten focused crates. Each has a single clear
responsibility, and the kernel/user boundary is reflected directly in the crate
structure: kernel-space crates take only core and alloc, while
drivers and services are built to run unprivileged.
| Crate | Space | Role |
|---|---|---|
kernel | Kernel | Privileged core — scheduler, IPC, and memory core. |
mm | Kernel | Virtual memory and the page allocator. |
vfs | Kernel | Virtual filesystem layer that dispatches to filesystem services. |
process | Kernel | Process and thread management — creation, lifecycle, scheduling state. |
ipc | Kernel | IPC primitives — channels, shared memory, and message queues. |
syscall | Kernel | POSIX-compatible system-call interface — validates and dispatches. |
hal | Kernel | Hardware abstraction layer — isolates architecture-specific code. |
drivers | User | User-space device drivers that talk to hardware via the HAL and IPC. |
bootloader | Kernel | Boot protocol and early initialization. |
lib | Shared | Shared libraries and common utilities used across crates. |
The drivers crate is deliberately the only one marked for user space: it is
the concrete realisation of the microkernel promise that hardware drivers do not belong
in the privileged core. The hal crate is the seam that keeps the
x86_64-unknown-none primary target, the secondary aarch64
target, and the tertiary riscv64 target from leaking
architecture details into the rest of the system; arch-specific code uses inline
assembly gated behind it.
How data flows
Three paths describe almost everything that happens in ONCRIX: how a program asks the kernel for something, how two programs talk to each other, and how a hardware event reaches the driver that handles it.
The syscall path
A user program issues a POSIX-compatible system call. The syscall crate is
the single front door: it validates every argument — including any
user-space pointer — before anything is dereferenced, then dispatches
to the right subsystem crate (kernel, process, mm,
or vfs). From there, if real hardware is involved, the request reaches it
only through the hal. Validation happens once, at the boundary, so the
subsystems behind it can assume their inputs are sound.
The IPC path
Because drivers, filesystems, and services are separate processes, they cannot call each
other directly — they communicate by message passing. The ipc crate provides
the channels, message queues, and shared-memory regions that carry those messages. This
is the spine of the system: a filesystem request, a driver command, or a service reply
is an IPC message, mediated by the kernel, between two isolated address spaces.
The driver path
When hardware raises an interrupt, the hal receives it and the kernel runs a
deliberately minimal handler — just enough to acknowledge the event and
hand it off. The real work is deferred to the user-space driver, which is notified over
IPC. Keeping interrupt handlers tiny keeps the privileged core small and predictable, and
keeps driver logic — the part most likely to be complex or buggy — out of ring 0.
Capability-based access control
ONCRIX names and grants access to resources through capabilities: unforgeable tokens that both identify a resource and convey the right to use it. A process can act on a resource only if it holds a capability for it — there is no ambient authority to fall back on, and a capability cannot be guessed or fabricated.
This makes least privilege the default rather than an aspiration. A user-space driver is handed exactly the capabilities it needs to reach its device and nothing more; a filesystem service receives only the storage and channels it was granted. Privilege separation falls out of the same model: because authority travels as explicit, unforgeable tokens, the kernel can confine each component to precisely the set of resources it was given, which is what makes a small TCB and user-space drivers safe to rely on.
Memory model
Every process runs in its own virtual address space. The
mm crate owns virtual memory and the page allocator, and the actual page
tables are programmed through the hal, so the same memory model holds across
the x86_64, aarch64, and riscv64 targets without
the higher layers knowing the difference.
The boundary between user and kernel is enforced at the pointer level. Any pointer that
crosses from user space into the kernel is validated before it is
dereferenced — the syscall crate checks it at the front door, so no
subsystem behind the dispatcher ever trusts a raw user address. Combined with Rust's
memory safety, the absence of undefined behaviour, and graceful panic handling, this is
how ONCRIX keeps process isolation honest: a process can describe memory to the kernel,
but it can never trick the kernel into touching memory it has no right to.