Issue
I want to build a kernel module that will be compatible with all the kernel’s releases. For example, if I build a kernel module on kernel 3.2.0-29 and try to load it on 3.2.0-86, I get the following error:
modprobe my_driver
FATAL: Error inserting my_driver (/lib/modules/3.2.0-86-generic/kernel/fs/my_drv/my_drv.ko): Invalid module format
[ In the log messeges: my_drv: disagrees about version of symbol module_layout ]
How can I build a kernel module on 3.2.0-29 that will be good for all 3.2.0 releases.
Solution
In short: you hardly can write useful kernel module, which can be loaded to kernels of relatively wide range of versions.
When you build the module against kernel compiled with CONFIG_MODVERSIONS
(like in your case), for every symbol, exported from the kernel, CRC (Cyclic Redundancy Check) for this symbol is stored in module's file. CRC is some sort of control sum, which takes into account, among other things, layout of types, used for function's parameters. For example, if layout of a hypothetical struct A
differs in two kernels, CRC for function f(struct A *a)
in these kernels differs too.
When a module is loaded into running kernel, CRC for all functions in the module are compared with ones for the kernel. If they differ, the kernel refuses to load the module. To read more about this mechanism see the kernel's documentation (Documentation/kbuild/modules.txt).
So, for make a module loadable into two different kernels, you are restricted only with functions whose parameters have same layout in both kernels. In particular, if layout of type struct module
differs, no single module can be loaded for both kernels.
There are several approaches to deliver a driver suitable for several kernels. The simplest way is to deliver the driver's sources and add them to dkms
. Such a way, if running kernel doesn't have the driver built, the driver will be compiled automatically using its sources.
Answered By - Tsyvarev Answer Checked By - Clifford M. (WPSolving Volunteer)