Perché sto costruendo un micro-nucleo basato su capacità da zero
I sistemi operativi sono tra i software più complessi mai costruiti. Gestiscono la memoria, pianificano il calcolo, controllano l’hardware e fanno rispettare i confini di sicurezza che proteggono ogni applicazione in esecuzione su una macchina.
Eppure molti dei sistemi operativi su cui facciamo affidamento oggi sono costruiti su idee architetturali che risalgono a diversi decenni fa. Sebbene questi sistemi siano straordinariamente potenti e collaudati, portano con sé anche decenni di complessità accumulata.
Questo progetto esplora una direzione diversa: costruire un sistema operativo moderno a micro-nucleo, basato su capacità, da zero, con una forte attenzione all’autorità esplicita, a una base di calcolo fidata (TCB) minima e a una separazione rigorosa tra nucleo e spazio utente.
Questo sistema operativo si chiama EriX.
Perché costruire un altro sistema operativo?⌗
A prima vista, costruire un nuovo sistema operativo può sembrare inutile. Sistemi maturi come Linux, Windows e BSD esistono già e alimentano miliardi di dispositivi.
Tuttavia, questi sistemi si sono evoluti sotto vincoli storici. Nel tempo hanno accumulato strati di astrazioni, meccanismi di compatibilità e interfacce legacy. Sebbene queste caratteristiche siano spesso necessarie nel software reale, rendono anche difficile sperimentare idee architetturali fondamentalmente diverse.
I sistemi operativi di ricerca hanno esplorato a lungo approcci alternativi alla progettazione dei sistemi operativi. I micro-nuclei, i sistemi a capacità e i nuclei formalmente verificati hanno dimostrato che è possibile costruire sistemi più piccoli, più sicuri e più facili da analizzare.
L’obiettivo di EriX non è sostituire i sistemi operativi esistenti. Piuttosto, è un’esplorazione di come potrebbe essere progettato un sistema operativo moderno se partissimo dai primi principi.
Micro-nucleo e base di calcolo fidata⌗
Una delle idee centrali dietro EriX è l’architettura a micro-nucleo.
I nuclei monolitici tradizionali includono molti servizi direttamente all’interno del nucleo stesso. Questi spesso includono:
- controllori di dispositivo
- filesystem
- stack di rete
- sottosistemi di gestione dei processi
Sebbene questo approccio possa essere efficiente, aumenta anche la dimensione della base di calcolo fidata (TCB). La TCB include ogni parte di codice che deve comportarsi correttamente affinché il sistema resti sicuro e affidabile.
I micro-nuclei adottano un approccio diverso.
Un micro-nucleo mantiene nel nucleo solo i meccanismi più fondamentali, tipicamente:
- schedulazione dei thread
- gestione dello spazio di indirizzamento
- comunicazione inter-processo (IPC)
- gestione delle capacità
- gestione di interrupt ed eccezioni
Tutto il resto gira in spazio utente, inclusi controllori, filesystem e servizi di livello superiore.
Questa progettazione riduce drasticamente la quantità di codice di cui ci si deve fidare. I guasti nei componenti in spazio utente hanno meno probabilità di compromettere l’intero sistema, e i singoli componenti possono essere riavviati o sostituiti senza mandare in crash il nucleo.
Sicurezza basata su capacità⌗
Un altro principio centrale di progettazione di EriX è la sicurezza basata su capacità.
La maggior parte dei sistemi operativi si basa fortemente su autorità ambientale. In questi sistemi, i processi hanno spesso accesso implicito alle risorse in base a spazi dei nomi globali, identità utente o privilegi ereditati.
Per esempio, un processo può aprire un file semplicemente perché conosce il percorso del file e il sistema operativo decide che quel processo ha il permesso di accedervi.
I sistemi a capacità adottano un approccio diverso.
Una capacità è un token non falsificabile che concede accesso a uno specifico oggetto con specifici diritti. Un processo può accedere a un oggetto solo se possiede una capacità che autorizza quell’accesso.
Le capacità hanno diverse proprietà importanti:
- Rappresentano l’autorità in modo esplicito.
- Possono essere trasferite tra processi.
- Possono limitare le operazioni a un insieme preciso di diritti.
In un sistema basato su capacità, l’autorità fluisce attraverso trasferimenti espliciti invece che tramite spazi dei nomi globali. Questo rende il sistema più facile da analizzare e aiuta a eliminare intere classi di vulnerabilità di sicurezza.
Perché Rust?⌗
I sistemi operativi sono tradizionalmente scritti in C o assembly. Questi linguaggi offrono un controllo preciso su hardware e memoria, ma rendono anche facile introdurre bug sottili.
I bug di sicurezza della memoria, come uso dopo liberazione, overflow del buffer e corse di dati, sono stati storicamente una delle maggiori fonti di vulnerabilità nel software di sistema.
EriX è scritto principalmente in Rust.
Rust fornisce forti garanzie sulla sicurezza della memoria pur consentendo un
controllo a basso livello dell’hardware. Il modello di proprietà del linguaggio
aiuta a prevenire molte classi di bug in fase di compilazione, mentre i blocchi
unsafe espliciti rendono visibili e verificabili le operazioni
potenzialmente pericolose.
Usare Rust non elimina tutti i possibili errori, ma alza in modo significativo la soglia di sicurezza di base nella programmazione di sistema.
Un sistema operativo in camera bianca⌗
Un aspetto insolito del progetto EriX è il suo approccio di sviluppo in camera bianca.
Tutti i componenti del sistema vengono implementati all’interno del progetto stesso. Nessun codice sorgente esterno viene copiato o incorporato, e non vengono usate librerie di terze parti.
Questo vincolo ha diversi scopi:
- Garantisce che l’intero sistema possa essere compreso e verificato.
- Evita dipendenze nascoste e comportamenti inattesi.
- Costringe le decisioni architetturali a essere esplicite anziché ereditate.
Lo sviluppo in camera bianca trasforma inoltre il progetto in un esercizio educativo. Ogni sottosistema, dal caricatore di avvio al gestore di memoria, deve essere progettato e implementato deliberatamente.
Un obiettivo a lungo termine: auto-ospitazione⌗
Uno degli obiettivi a lungo termine di EriX è l’auto-ospitazione.
Un sistema è considerato auto-ospitato quando può compilare il proprio codice sorgente usando strumenti che girano sul sistema stesso.
Per EriX, questo significa che alla fine:
- il compilatore Rust gira su EriX
- gli strumenti di compilazione girano su EriX
- l’intero sistema operativo può essere compilato nativamente dentro EriX
Raggiungere questo traguardo richiede l’implementazione di molti strati infrastrutturali, inclusi filesystem, gestione dei processi e un ambiente utente compatibile con POSIX.
Perché documentare il percorso?⌗
Costruire un sistema operativo è un processo lungo e complesso. Molte delle intuizioni più interessanti non appaiono nel sistema finale, ma nelle decisioni, nei compromessi e negli errori incontrati lungo il cammino.
Questo blog documenta lo sviluppo di EriX mentre evolve. I post futuri tratteranno temi come:
- progettare un formato di immagine di avvio
- implementare spazi di capacità
- costruire un sistema IPC
- gestire l’autorità della memoria
- costruire server in spazio utente
L’obiettivo è rendere il processo di sviluppo trasparente e formativo.
Guardando avanti⌗
EriX è ancora nelle fasi iniziali. Gran parte del sistema deve ancora essere costruita e molte decisioni di progettazione evolveranno sicuramente nel tempo.
Ma i principi guida sono già chiari:
- nucleo minimo
- autorità esplicita
- sicurezza basata su capacità
- modularità rigorosa
- implementazione in camera bianca
Nel prossimo articolo esploreremo una delle idee centrali del sistema:
cosa sono i sistemi operativi basati su capacità e perché sono importanti.