How are intermodule dependencies resolved when both modules are built outside of the kernel tree and modversioning is enabled?
Modversioning is used to ensure that binary loadable modules are compatible with the kernels they are loaded upon. It is enabled with .config option CONFIG_MODVERSIONS.
We have two dynamically loaded kernel modules, one of which uses an exported symbol from the other. Although the module with the dependence on the other is loaded after the other, insmod complains that it can not resolve a dependency.
[FWIW, these particular modules would serve no useful purpose in the open source world. The people who designed these modules like to keep them out of the kernel tree for their own SCM purposes. The solution of deploying these as a kernel patch will not work.]
This is what the kernel log shows.
<4>foomod: no symbol version for bar_api
<4>foomod: Unknown symbol bar_api
However, if I cat /proc/kallsyms, the bar_api is there and shown as exported.
Another developer here suggested that we use a .conf file to get invoked from the loadmodules script that ignores this error and forces a load, something like this.
install foomod { /sbin/modprobe --ignore-install --force-modversion foomod
$CMDLINE_OPTS; }
I think there has got to be a cleaner way to fix this.
I've tried modifying the Makefile to reference symvers of the module exporting the symbol. The module source for each are in peer directories. It does not seem to matter, but I could be doing this wrong.
KBUILD_EXTRA_SYMBOLS := ../barmod/Module.symvers
This is the content of Module.symvers:
0x00000000 bar_api bar_api barmod
The 0x00000000 is supposed to be valid with modversioning disabled. I think if I could use modprobe like this and see the exported function, then the modprobe would be successful. However, this would only work when modversions is disabled.
# modprobe --dump-modversions foomod.ko
0x00000000 bar_api
However, copying both drivers into the kernel tree and building from within it works. This is a partial listing of the symbols referenced with checksums.
# modprobe --dump-modversions foomod.ko
0x46085e4f add_timer
0x7d11c268 jiffies
0x6a9f26c9 init_timer_key
0x7ec9bfbc strncpy
0xe43dc92b misc_register
0x3302b500 copy_from_user
0x85f8a266 copy_to_user
0xc6538cfc bar_api
0xea147363 printk
: :
Way back around ~2002 having CONFIG_MODVERSIONS would have caused the build to append a checksum generated from genksyms to each exported kernel function. Symbols would look something like this: printk_R1b7d40. This is the last time I've had to deal with modversioning since all of my work since has been with open-source code, within the stock kernel code, or with modversioning disabled. However, today's builds use genksyms to create a checksum for each symbol that goes into a special section. This special section is checked for a checksum match.
There used to be a kernel macro called EXPORT_SYMBOL_NOVERS() that would have worked, but that has been deprecated.
The Linux kernel used is 2.6.32.
I've found these articles relevant and helpful, but inconclusive:
http://lxr.free-electrons.com/source/Documentation/kbuild/modules.txt
http://lwn.net/Articles/21393/
http://www.linuxchix.org/content/courses/kernel_hacking/lesson8
http://lwn.net/Kernel/LDD2/ch11.lwn
How do I cleanly export a function from a loadable module and allow it to be used by another, dependent loadable module when both are built outside of the Linux kernel?