As part of the module kernel requirements introduced in Android 8.0, all system-on-chip (SoC) kernels must support loadable kernel modules.
Kernel configuration options
To support loadable kernel modules, android-base.config in all common kernels includes the following kernel-config options (or their kernel-version equivalent):
CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y
All device kernels must enable these options. Kernel modules should also support unloading and reloading whenever possible.
Module signing
Module-signing is not supported for GKI vendor modules. On devices required to
support verified boot, Android requires kernel modules to be in the partitions
that have dm-verity enabled. This removes the need for signing individual
modules for their authenticity.
Android 13 introduced the concept of GKI modules. GKI modules use the kernel's build time
signing infrastructure to differentiate between GKI and other modules at run time.
Unsigned modules are allowed to load as long as they only use symbols appearing on the allowlist
or provided by other unsigned modules.
To facilitate GKI modules signing during GKI build using kernel's build time key pair,
GKI kernel config has enabled CONFIG_MODULE_SIG_ALL=y
.
To avoid signing non-GKI modules during device kernel builds, you must add
# CONFIG_MODULE_SIG_ALL is not set
as part of your kernel config
fragments.
File locations
While Android 7.x and lower don't mandate against kernel modules (and include
support for insmod
and rmmod
), Android 8.x and
higher recommend the use of kernel modules in the ecosystem. The following
table shows potential board-specific peripheral support required across three
Android boot modes.
Boot mode | Storage | Display | Keypad | Battery | PMIC | Touchscreen | NFC, Wi-Fi, Bluetooth |
Sensors | Camera |
---|---|---|---|---|---|---|---|---|---|
Recovery | |||||||||
Charger | |||||||||
Android |
In addition to availability in Android boot modes, kernel modules may also be categorized by who owns them (the SoC vendor or the ODM). If kernel modules are being used, requirements for their placement in file system are as follows:
- All kernels should have built-in support for booting and mounting partitions.
- Kernel modules must be loaded from a read-only partition.
- For devices required to have verified boot, kernel modules should be loaded from verified partitions.
- Kernel modules shouldn't be located in
/system
. - GKI modules required for the device should be loaded from
/system/lib/modules
which is a symbolic link to/system_dlkm/lib/modules
. - Kernel modules from the SoC vendor that are required for full Android or
Charger modes should be located in
/vendor/lib/modules
. - If an ODM partition exists, kernel modules from the ODM that are required
for full Android or Charger modes should be located in
/odm/lib/modules
. Otherwise, these modules should be located in/vendor/lib/modules
. - Kernel modules from the SoC vendor and ODM that are required for Recovery
mode should be located in the recovery
ramfs
at/lib/modules
. - Kernel modules required for both Recovery mode and full Android or
Charger modes should exist both in the recovery
rootfs
and either the/vendor
or/odm
partitions (as described above). - Kernel modules used in Recovery mode shouldn't depend on modules located
only in
/vendor
or/odm
, as those partitions aren't mounted in Recovery mode. - SoC vendor kernel modules shouldn't depend on ODM kernel modules.
In Android 7.x and lower, /vendor
and /odm
partitions are not mounted early. In Android 8.x and higher,
to make module loading from these partitions possible, provisions have been
made to mount partitions early for both
non-A/B and A/B devices. This also
ensures that the partitions are mounted in both Android and Charger modes.
Android build system support
In BoardConfig.mk
, the Android build defines a
BOARD_VENDOR_KERNEL_MODULES
variable that provides a full list
of the kernel modules intended for the vendor image. The modules listed in
this variable are copied into the vendor image at /lib/modules/
,
and, after being mounted in Android, appear in
/vendor/lib/modules
(in accordance with the above requirements).
Example configuration of the vendor kernel modules:
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 this example, a vendor kernel module pre-built repository is mapped into the Android build at the location listed above.
The recovery image may contain a subset of the vendor modules. The Android
build defines the variable BOARD_RECOVERY_KERNEL_MODULES
for
these modules. Example:
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
The Android build takes care of running depmod
to generate the
required modules.dep
files in /vendor/lib/modules
and /lib/modules
(recovery ramfs
).
Module loading and versioning
Load all kernel modules in one pass from init.rc*
by invoking
modprobe -a
. This avoids the overhead of repeatedly initializing
the C runtime environment for the modprobe
binary. The
early-init
event can be modified to invoke modprobe
:
on early-init exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules module_a module_b module_c ...
Typically, a kernel module must be compiled with the kernel that the module is
to be used with (otherwise the kernel refuses to load the module).
CONFIG_MODVERSIONS
provides a workaround by detecting breakages
in the application binary interface (ABI). This feature calculates a cyclic
redundancy check (CRC) value for the prototype of each exported symbol in the
kernel and stores the values as part of the kernel; for symbols used by a
kernel module, the values are also stored in the kernel module. When the
module is loaded, the values for the symbols used by the module are compared
with the ones in the kernel. If the values match, the module is loaded;
otherwise the load fails.
To enable the updating of the kernel image separately from the vendor image,
enable CONFIG_MODVERSIONS
. Doing so allows small updates to the
kernel (such as bug fixes from LTS) to be made while maintaining compatibility
with existing kernel modules in the vendor image. However,
CONFIG_MODVERSIONS
doesn't fix an ABI breakage by itself. If the
prototype of an exported symbol in the kernel changes, either due to
modification of the source or because the kernel configuration changed, this
breaks compatibility with kernel modules that use that symbol. In such cases,
the kernel module must be recompiled.
For example, the task_struct
structure in the kernel (defined in
include/linux/sched.h
) contains many fields conditionally
included depending on the kernel configuration. The sched_info
field is present only if CONFIG_SCHED_INFO
is enabled (which
occurs when CONFIG_SCHEDSTATS
or
CONFIG_TASK_DELAY_ACCT
are enabled). If these configuration
options change state, the layout of the task_struct
structure
changes and any exported interfaces from the kernel that use
task_struct
are altered (for example,
set_cpus_allowed_ptr
in kernel/sched/core.c
).
Compatibility with previously compiled kernel modules that use these
interfaces breaks, requiring those modules to be rebuilt with the new kernel
configuration.
For more details on CONFIG_MODVERSIONS
, refer to the
documentation in the kernel tree at
Documentation/kbuild/modules.rst
.