Im Rahmen der in Android 8.0 eingeführten Anforderungen an den Modul-Kernel müssen alle SoC-Kernel (System-on-Chip) ladbare Kernelmodule unterstützen.
Kernel-Konfigurationsoptionen
Zur Unterstützung ladbarer Kernelmodule enthält android-base.config in allen gängigen Kerneln die folgenden Kernel-Konfigurationsoptionen (oder deren Kernel-Versionsäquivalente):
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
Diese Optionen müssen für alle Gerätekerne aktiviert sein. Kernelmodule sollten nach Möglichkeit auch das Entladen und Neuladen unterstützen.
Modulsignatur
Die Modulsignatur wird für GKI-Anbietermodule nicht unterstützt. Auf Geräten, die den sicheren Start unterstützen müssen, müssen sich die Kernelmodule in den Partitionen befinden, für die dm-verity aktiviert ist. Dadurch müssen einzelne Module nicht mehr auf Authentizität signiert werden.
Mit Android 13 wurde das Konzept der GKI-Module eingeführt. GKI-Module verwenden die Signaturinfrastruktur der Buildzeit des Kernels, um bei der Laufzeit zwischen GKI- und anderen Modulen zu unterscheiden.
Unsignierte Module dürfen geladen werden, solange sie nur Symbole verwenden, die auf der Zulassungsliste stehen oder von anderen unsignierten Modulen bereitgestellt werden.
Um die Signatur von GKI-Modulen während des GKI-Builds mit dem Buildzeit-Schlüsselpaar des Kernels zu ermöglichen, wurde in der GKI-Kernelkonfiguration CONFIG_MODULE_SIG_ALL=y
aktiviert.
Damit bei der Erstellung des Gerätekernels keine nicht GKI-Module signiert werden, müssen Sie # CONFIG_MODULE_SIG_ALL is not set
als Teil Ihrer Kernel-Konfigurationsfragmente hinzufügen.
Dateispeicherorte
Unter Android 7.x und niedriger sind Kernelmodule zwar nicht vorgeschrieben (und es wird Unterstützung für insmod
und rmmod
angeboten), unter Android 8.x und höher wird jedoch die Verwendung von Kernelmodulen im Android-System empfohlen. In der folgenden Tabelle sind die möglichen gerätespezifischen Peripheriegeräte aufgeführt, die für die drei Android-Bootmodi erforderlich sind.
Bootmodus | Speicher | Anzeige | Wähltastatur | Akku | PMIC | Touchscreen | NFC, WLAN, Bluetooth |
Sensoren | Kamera |
---|---|---|---|---|---|---|---|---|---|
Recovery | |||||||||
Ladegerät | |||||||||
Android |
Neben der Verfügbarkeit in den Android-Bootmodi können Kernelmodule auch nach dem Eigentümer (SoC-Anbieter oder ODM) kategorisiert werden. Wenn Kernelmodule verwendet werden, gelten für deren Platzierung im Dateisystem folgende Anforderungen:
- Alle Kernel sollten eine integrierte Unterstützung für das Booten und das Bereitstellen von Partitionen haben.
- Kernelmodule müssen von einer schreibgeschützten Partition geladen werden.
- Bei Geräten, für die ein bestätigter Boot erforderlich ist, sollten Kernelmodule aus bestätigten Partitionen geladen werden.
- Kernelmodule sollten sich nicht in
/system
befinden. - Die für das Gerät erforderlichen GKI-Module sollten von
/system/lib/modules
geladen werden, einem symbolischen Link zu/system_dlkm/lib/modules
. - Kernelmodule des SoC-Anbieters, die für den vollständigen Android-Betrieb oder Lademodi erforderlich sind, sollten sich in
/vendor/lib/modules
befinden. - Wenn eine ODM-Partition vorhanden ist, sollten sich die Kernelmodule des ODM, die für den vollständigen Android- oder Lademodus erforderlich sind, in
/odm/lib/modules
befinden. Andernfalls sollten sich diese Module in/vendor/lib/modules
befinden. - Kernelmodule vom SoC-Anbieter und ODM, die für den Wiederherstellungsmodus erforderlich sind, sollten sich in der Wiederherstellungspartition
ramfs
unter/lib/modules
befinden. - Kernelmodule, die sowohl für den Wiederherstellungsmodus als auch für den vollständigen Android- oder Lademodus erforderlich sind, müssen sowohl in der Wiederherstellungspartition
rootfs
als auch in der Partition/vendor
oder/odm
vorhanden sein (wie oben beschrieben). - Kernelmodule, die im Wiederherstellungsmodus verwendet werden, dürfen nicht von Modulen abhängen, die sich nur in
/vendor
oder/odm
befinden, da diese Partitionen im Wiederherstellungsmodus nicht bereitgestellt werden. - Kernelmodule von SoC-Anbietern sollten nicht von ODM-Kernelmodulen abhängen.
Unter Android 7.x und niedriger werden die Partitionen /vendor
und /odm
nicht frühzeitig bereitgestellt. Unter Android 8.x und höher werden Partitionen sowohl für Nicht-A/B- als auch für A/B-Geräte frühzeitig bereitgestellt, damit das Laden von Modulen aus diesen Partitionen möglich ist. So wird auch sichergestellt, dass die Partitionen sowohl im Android- als auch im Lademodus bereitgestellt werden.
Unterstützung für Android-Build-System
In BoardConfig.mk
definiert der Android-Build eine BOARD_VENDOR_KERNEL_MODULES
-Variable, die eine vollständige Liste der Kernelmodule enthält, die für das Anbieterimage vorgesehen sind. Die in dieser Variablen aufgeführten Module werden in das Anbieterimage unter /lib/modules/
kopiert und nach dem Bereitstellen in Android unter /vendor/lib/modules
angezeigt (gemäß den oben genannten Anforderungen).
Beispielkonfiguration der Kernelmodule des Anbieters:
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 diesem Beispiel wird ein vorkonfiguriertes Repository für ein Kernelmodul eines Anbieters dem Android-Build an dem oben aufgeführten Speicherort zugeordnet.
Das Wiederherstellungsimage kann eine Teilmenge der Anbietermodule enthalten. Der Android-Build definiert die Variable BOARD_RECOVERY_KERNEL_MODULES
für diese Module. Beispiel:
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
Beim Android-Build wird depmod
ausgeführt, um die erforderlichen modules.dep
-Dateien in /vendor/lib/modules
und /lib/modules
(recovery ramfs
) zu generieren.
Modulladen und -versionierung
Laden Sie alle Kernelmodule in einem Durchlauf von init.rc*
, indem Sie modprobe -a
aufrufen. So wird der Overhead vermieden, der durch wiederholtes Initialisieren der C-Laufzeitumgebung für das modprobe
-Binärprogramm entsteht. Das Ereignis early-init
kann so geändert werden, dass modprobe
aufgerufen wird:
on early-init exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules module_a module_b module_c ...
Normalerweise muss ein Kernelmodul mit dem Kernel kompiliert werden, mit dem es verwendet werden soll. Andernfalls lädt der Kernel das Modul nicht.
CONFIG_MODVERSIONS
bietet eine Lösung, indem Unterbrechungen in der Application Binary Interface (ABI) erkannt werden. Diese Funktion berechnet einen CRC-Wert (Cyclic Redundancy Check) für den Prototyp jedes exportierten Symbols im Kernel und speichert die Werte als Teil des Kernels. Bei Symbolen, die von einem Kernelmodul verwendet werden, werden die Werte auch im Kernelmodul gespeichert. Beim Laden des Moduls werden die Werte für die vom Modul verwendeten Symbole mit denen im Kernel verglichen. Wenn die Werte übereinstimmen, wird das Modul geladen. Andernfalls schlägt das Laden fehl.
Wenn Sie das Kernel-Image unabhängig vom Anbieter-Image aktualisieren möchten, aktivieren Sie CONFIG_MODVERSIONS
. So können kleine Updates am Kernel (z. B. Fehlerkorrekturen aus LTS) vorgenommen werden, während die Kompatibilität mit vorhandenen Kernelmodulen im Anbieter-Image erhalten bleibt. CONFIG_MODVERSIONS
behebt jedoch nicht automatisch eine ABI-Unterbrechung. Wenn sich der Prototyp eines exportierten Symbols im Kernel ändert, entweder aufgrund einer Änderung der Quelle oder aufgrund einer Änderung der Kernelkonfiguration, wird die Kompatibilität mit Kernelmodulen, die dieses Symbol verwenden, aufgehoben. In solchen Fällen muss das Kernelmodul neu kompiliert werden.
Die task_struct
-Struktur im Kernel (definiert in include/linux/sched.h
) enthält beispielsweise viele Felder, die je nach Kernelkonfiguration bedingt eingeschlossen sind. Das Feld sched_info
ist nur vorhanden, wenn CONFIG_SCHED_INFO
aktiviert ist. Das ist der Fall, wenn CONFIG_SCHEDSTATS
oder CONFIG_TASK_DELAY_ACCT
aktiviert sind. Wenn sich der Status dieser Konfigurationsoptionen ändert, ändert sich auch das Layout der task_struct
-Struktur und alle vom Kernel exportierten Schnittstellen, die task_struct
verwenden, werden geändert (z. B. set_cpus_allowed_ptr
in kernel/sched/core.c
). Die Kompatibilität mit zuvor kompilierten Kernelmodulen, die diese Schnittstellen verwenden, wird unterbrochen. Diese Module müssen mit der neuen Kernelkonfiguration neu erstellt werden.
Weitere Informationen zu CONFIG_MODVERSIONS
finden Sie in der Dokumentation im Kernel-Baum unter Documentation/kbuild/modules.rst
.