A cosa servono le estensioni del kernel? Spiegato!

Nell’ultimo articolo ci siamo lasciati con la spiegazione del metodo Fuzzing, per scovare bug in iOS. In questo articolo parleremo delle estensioni del kernel, perchè si usano e perchè sono così importanti.

kernel

Introduzione

Abbiamo più volte ribadito che XNU, il kernel di macOS e iOS, “possiede un ecosistema vasto“: significa banalmente che ha tutti i servizi necessari al corretto funzionamento del sistema operativo, che vanno dalla pianificazione alla gestione della memoria, al controllo dell’I/O e così via.

Tuttavia, nessun kernel, nemmeno un monolitico, può essere effettivamente “completo”. Qual è la soluzione? Come possiamo rendere il kernel estensibile, per farlo “adattare”? Attraverso le estensioni del kernel!

Si tratta semplicemente di moduli del kernel, che possono essere inseriti o rimossi dinamicamente e su richiesta; XNU, sia in macOS che in iOS, utilizza questi moduli per caricare i vari driver dei dispositivi e per potenziare le funzionalità del kernel con sottosistemi interamente autonomi.

Estendere il kernel

In ogni sistema operativo, sebbene un kernel sia di solito autonomo e debba essere in grado di fornire un set completo di API previste in user mode, eseguire un kernel collegato staticamente è praticamente impossibile: un kernel di questo tipo implicherebbe una struttura molto rigida, non estensibile in alcun modo: non sarebbe possibile aggiungere funzionalità aggiuntive su richiesta. Abbiamo quindi capito una prima cosa, avere un kernel che contiene tutti e solo i driver necessari per il dispositivo non è fattibile.

Abbiamo bisogno di estensibilità, quindi di un design modulare. Proprio come la user mode in Windows possiede le DLL o Unix con i suoi shared object, la kernel mode possiede dei moduli o – in linguaggio XNU – estensioni del kernel.

Sono chiamati kexts e sono un elemento fondamentale in XNU, quasi al pari del kernel stesso: in effetti, non è raro trovare più codice in kernel mode risultante dall’inserimento di moduli aggiuntivi, rispetto al nucleo del kernel stesso.

Anche se la nomenclatura è diversa, l’idea alla base dei kexts è esattamente la stessa di quella dei file .sys di Windows e dei file .ko di Linux. Tutti e tre i tipi di file sono codici rilocabili, collegati dinamicamente con simboli specifici che il kernel ritiene adatti all’esportazione (volendo semplificare, ad ogni indirizzo logico/simbolico viene fatto corrispondere un indirizzo fisico: l’associazione tra indirizzi simbolici ed indirizzi assoluti viene detta binding e può essere fatto staticamente a tempo di caricamento: il compilatore genera degli indirizzi relativi che vengono convertiti in indirizzi assoluti dal loader [codice rilocabile]).

Questi kexts richiedono solo un punto di ingresso, che di solito gestisce tutte le attività di inizializzazione richieste dall’estensione e da quel momento può eseguire qualsiasi codice richiesto dallo sviluppatore.
Un kext viene eseguito sempre in kernel mode e quindi ha pieno accesso allo spazio del kernel: implicitamente, uno sviluppatore può utilizzare qualsiasi funzione definita dal kernel come esportabile. Anche le variabili e le strutture globali del kernel possono essere interrogate e persino impostate, rendendo i kexts molto popolari per ogni tipo di sviluppo a livello di kernel.

Giustamente, come potreste pensare, offrire a questi moduli kernel così tanta potenza rappresenta un rischio maggiore per la sicurezza dell’utente. Se ad esempio il kernel è impostato per accettare del codice di origine sconosciuta, è impossibile determinare la natura malevola di tale codice, prima di caricarlo effettivamente; inoltre, una volta che il codice è stato caricato nel kernel, esso è effettivamente visto come codice dal kernel, quindi corretto a priori. Questo significa che la stabilità e ancor più la sicurezza dell’intero sistema operativo possono essere compromesse. In effetti, la maggior parte dei malware moderni sono camuffati sotto forma di moduli dannosi, noti anche come rootkit.

Spostiamoci adesso su iOS. Apple, nel suo sistema operativo per iPhone non ha mai avuto alcun intento di aprire lo spazio di sviluppo del kernel a chiunque, se non ai suoi stessi sviluppatori. Come sistema operativo iOS è molto robusto, sia in user mode che ancora di più in kernel mode, proprio per scoraggiare qualsiasi tipo di modifica. Quindi, anche se i kexts sono ampiamente usati per fornire supporto per i vari iDevice, sono “fusi” nella kernel-cache di iOS nel momento in il sistema viene “costruito”, risultando una parte integrante del kernel stesso, XNU.

Anche per questo articolo è tutto. Per eventuali domande, curiosità o feedback potete lasciare un commento qui in basso, a presto!

NovitàAcquista il nuovo iPhone 16 su Amazon
Approfondimenti