Nell'ambito dei requisiti del kernel del modulo introdotti in Android 8.0, tutti i kernel System-on-Chip (SoC) devono supportare i moduli del kernel caricabili.
Opzioni di configurazione del kernel
Per supportare i moduli del kernel caricabili, android-base.config in tutti i kernel comuni include le seguenti opzioni kernel-config (o il relativo equivalente kernel-version):
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
Tutti i kernel del dispositivo devono attivare queste opzioni. I moduli del kernel devono inoltre supportare lo scaricamento e il ricaricamento, se possibile.
Firma del modulo
La firma del modulo non è supportata per i moduli del fornitore GKI. Sui dispositivi che devono supportare l'avvio verificato, Android richiede che i moduli del kernel si trovino nelle partizioni in cui è abilitato dm-verity. In questo modo non è più necessario firmare i singoli moduli per verificarne l'autenticità.
Android 13 ha introdotto il concetto di moduli GKI. I moduli GKI utilizzano l'infrastruttura di firma al momento della compilazione del kernel per distinguere il GKI da altri moduli in fase di esecuzione.
I moduli non firmati sono consentiti se utilizzano solo i simboli presenti nella lista consentita o forniti da altri moduli non firmati.
Per facilitare la firma dei moduli GKI durante la compilazione del GKI utilizzando la coppia di chiavi del momento di compilazione del kernel,
la configurazione del kernel GKI ha attivato CONFIG_MODULE_SIG_ALL=y
.
Per evitare di firmare i moduli non GKI durante le build del kernel del dispositivo, devi aggiungere
# CONFIG_MODULE_SIG_ALL is not set
come parte dei frammenti di configurazione del kernel.
Posizioni dei file
Sebbene Android 7.x e versioni precedenti non vietino i moduli del kernel (e includano il supporto per insmod
e rmmod
), Android 8.x e versioni successive consigliano l'utilizzo di moduli del kernel nell'ecosistema. La tabella seguente mostra il potenziale supporto delle periferiche specifico della scheda richiesto nelle tre modalità di avvio di Android.
Modalità di avvio | Spazio di archiviazione | Display | Tastierino | Batteria | PMIC | Touchscreen | NFC, Wi-Fi, Bluetooth |
Sensori | Fotocamera |
---|---|---|---|---|---|---|---|---|---|
Ripristino | |||||||||
Caricabatterie | |||||||||
Android |
Oltre alla disponibilità nelle modalità di avvio di Android, i moduli del kernel possono anche essere classificati in base a chi li possiede (il fornitore del SoC o l'ODM). Se vengono utilizzati moduli del kernel, i requisiti per il loro posizionamento nel file system sono i seguenti:
- Tutti i kernel devono avere il supporto integrato per l'avvio e il montaggio delle partizioni.
- I moduli del kernel devono essere caricati da una partizione di sola lettura.
- Per i dispositivi che devono avere l'avvio verificato, i moduli del kernel devono essere caricati dalle partizioni verificate.
- I moduli del kernel non devono trovarsi in
/system
. - I moduli GKI richiesti per il dispositivo devono essere caricati da
/system/lib/modules
, che è un link simbolico a/system_dlkm/lib/modules
. - I moduli del kernel del fornitore del SoC necessari per le modalità Android o caricabatterie complete devono trovarsi in
/vendor/lib/modules
. - Se esiste una partizione ODM, i moduli del kernel dell'ODM richiesti per le modalità Android o Caricabatterie complete devono trovarsi in
/odm/lib/modules
. In caso contrario, questi moduli devono trovarsi in/vendor/lib/modules
. - I moduli del kernel del fornitore del SoC e dell'ODM necessari per la modalità di recupero devono trovarsi nella cartella
ramfs
di recupero all'indirizzo/lib/modules
. - I moduli del kernel richiesti sia per la modalità di ripristino sia per le modalità Android o caricabatterie complete devono esistere sia nella partizione
rootfs
di ripristino sia nelle partizioni/vendor
o/odm
(come descritto sopra). - I moduli del kernel utilizzati in modalità di recupero non devono dipendere da moduli situati solo in
/vendor
o/odm
, poiché queste partizioni non sono montate in modalità di recupero. - I moduli del kernel del fornitore SoC non devono dipendere dai moduli del kernel ODM.
In Android 7.x e versioni precedenti, le partizioni /vendor
e /odm
non vengono montate in anticipo. In Android 8.x e versioni successive, per consentire il caricamento dei moduli da queste partizioni, sono state prese disposizioni per il montaggio anticipato delle partizioni sia per i dispositivi non A/B che per quelli A/B. In questo modo,
viene garantito che le partizioni vengano montate sia in modalità Android sia in modalità caricabatterie.
Supporto del sistema di build Android
In BoardConfig.mk
, la build Android definisce una variabile BOARD_VENDOR_KERNEL_MODULES
che fornisce un elenco completo dei moduli del kernel destinati all'immagine del fornitore. I moduli elencati in questa variabile vengono copiati nell'immagine del fornitore in /lib/modules/
e, dopo essere stati montati in Android, vengono visualizzati in /vendor/lib/modules
(in conformità ai requisiti sopra indicati).
Configurazione di esempio dei moduli del kernel del fornitore:
vendor_lkm_dir := device/$(vendor)/lkm-4.x BOARD_VENDOR_KERNEL_MODULES := \ $(vendor_lkm_dir)/vendor_module_a.ko \ $(vendor_lkm_dir)/vendor_module_b.ko \ $(vendor_lkm_dir)/vendor_module_c.ko
In questo esempio, un repository precompilato del modulo del kernel del fornitore viene mappato nella compilazione Android nella posizione sopra indicata.
L'immagine di ripristino potrebbe contenere un sottoinsieme dei moduli del fornitore. La compilazione Android
definisce la variabile BOARD_RECOVERY_KERNEL_MODULES
per
questi moduli. Esempio:
vendor_lkm_dir := device/$(vendor)/lkm-4.x BOARD_RECOVERY_KERNEL_MODULES := \ $(vendor_lkm_dir)/vendor_module_a.ko \ $(vendor_lkm_dir)/vendor_module_b.ko
La compilazione Android si occupa di eseguire depmod
per generare i file modules.dep
richiesti in /vendor/lib/modules
e /lib/modules
(recovery ramfs
).
Caricamento e controllo delle versioni dei moduli
Carica tutti i moduli del kernel in un passaggio da init.rc*
richiamando
modprobe -a
. In questo modo si evita il sovraccarico dell'inizializzazione ripetuta
dell'ambiente di runtime C per il file binario modprobe
. L'evento early-init
può essere modificato per richiamare modprobe
:
on early-init exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules module_a module_b module_c ...
In genere, un modulo del kernel deve essere compilato con il kernel con cui deve essere utilizzato (in caso contrario, il kernel rifiuta di caricare il modulo).
CONFIG_MODVERSIONS
fornisce una soluzione alternativa rilevando le interruzioni
nell'interfaccia a bit dell'applicazione (ABI). Questa funzionalità calcola un valore di controllo di ridondanza ciclica (CRC) per il prototipo di ogni simbolo esportato nel kernel e memorizza i valori all'interno del kernel. Per i simboli utilizzati da un modulo del kernel, i valori vengono memorizzati anche nel modulo del kernel. Quando il
modulo viene caricato, i valori dei simboli utilizzati dal modulo vengono confrontati
con quelli del kernel. Se i valori corrispondono, il modulo viene caricato;
in caso contrario, il caricamento non va a buon fine.
Per abilitare l'aggiornamento dell'immagine del kernel separatamente dall'immagine del fornitore, attiva CONFIG_MODVERSIONS
. In questo modo è possibile apportare piccoli aggiornamenti al kernel (ad esempio correzioni di bug dall'LTS) mantenendo la compatibilità con i moduli del kernel esistenti nell'immagine del fornitore. Tuttavia,
CONFIG_MODVERSIONS
non corregge da solo un'interruzione dell'ABI. Se il
prototipo di un simbolo esportato nel kernel cambia, a causa della
modifica del codice sorgente o della configurazione del kernel, la compatibilità con i moduli del kernel che utilizzano quel simbolo viene interrotta. In questi casi,
il modulo del kernel deve essere ricompilato.
Ad esempio, la struttura task_struct
nel kernel (definita in
include/linux/sched.h
) contiene molti campi inclusi in modo condizionale
a seconda della configurazione del kernel. Il campo sched_info
è presente solo se è attivato CONFIG_SCHED_INFO
(cosa che accade quando sono attivati CONFIG_SCHEDSTATS
o
CONFIG_TASK_DELAY_ACCT
). Se queste opzioni di configurazione cambiano stato, il layout della struttura task_struct
cambia e le eventuali interfacce esportate dal kernel che utilizzano task_struct
vengono alterate (ad esempio set_cpus_allowed_ptr
in kernel/sched/core.c
). La compatibilità con i moduli del kernel compilati in precedenza che utilizzano queste interfacce viene interrotta, pertanto è necessario ricostruire questi moduli con la nuova configurazione del kernel.
Per ulteriori dettagli su CONFIG_MODVERSIONS
, consulta la documentazione nell'albero del kernel all'indirizzo Documentation/kbuild/modules.rst
.