How are intermodule dependencies resolved when...? - linux

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?

Related

Linux ELF shared library issue

Currently I am working with ELF files and trying to deal with loading SO files. I am trying to "forcibly" link a new (a fake one, without actual calls to the code) SO dependency into executable file. To do that, I modified the .dynstr section contents (created a new section, filled it with the new contents, and resolved all sh_link fileds of Elf64_Shdr entries). Also I modified the .dynamic section (it has more than one null entry, so I modified one) to have DT_NEEDED type with linkage to the needed third-party SO name.
My small test app, being analyzed, appears to be fine (as readelf with -d option, or objdump -p, show). Nevertheless, when trying to run the application, it tells:
error while loading shared libraries: ��oU: cannot open shared object file: No such file or directory
Every time running, the name is different. This makes me think some addresses in the ELF loaded are invalid.
I understand that this way of patching is highly error-prone, but I am interested anyway. So, my question is: are there any ELF tools (like gdb or strace), which can debug image loading process (i.e. which can tell one what is wrong before entry point is hit)? Or are there any switches or options, which can help with this situation?
I have tried things like strace -d, but it would not tell anything interesting.
You do not mention patching DT_STRTAB and DT_STRSZ. These tags control how the dynamic loader locates the dynamic string table. The section headers are only used by the link editor, not at run time.
First of all, I did not manage to find any possibility to deal with sane debugging. My solution came in just because of hard-way raw ELF file hex bytes manual analysis.
My conception in general was right (forgot to mention the DT_STRTAB and DT_STRSZ modification though, thanks to Florian Weimer for reminding of it). The patchelf util (see in the postscriptum below) made me sure I am generally right.
The thing is: when you add a new section to the end, make sure you put data to the PLT right way. To add a new ".dynstr" section, I had to overwrite an auxiliary note segment (Elf**_Phdr::p_type == PT_NOTE) with a new segment, right for the new ".dynstr" section data. Not yet sure if such overwriting might cause some error.
It turned out that I put a raw ELF file ('offline') offset, but had to put this data RVA in the running image (after loading ELF into memory by the system loader, 'online'). Once I fixed it, the ELF started to work properly.
P.S. found a somewhat similar question: How can I change the filename of a shared library after building a program that depends on it? (a useful util for the same purpose I need, patchelf, is mentioned there; patchelf is available under Debian via APT, it is a nice tool for the stated purpose)

How to load a modified kernel module which is already exist in precompiled kernel

one way is to do so is to build the kernel sources again with making original module loadable which need to be modified. so original module can be removed and modified module can be inserted. but this is time consuming process.
I am wondering if there is some other way to load modified module.
I made some modification in MD driver and tried to load it on precompiled kernel.
insmod failed with following error messege:
md_mod: exports duplicate symbol bitmap_close_sync (owned by kernel)
insmod: error inserting 'md-mod.ko': -1 Invalid module format
Please provide the feedback if it can be done. Any help would be appreciated. Thanks !
This error shows up because already the bitmap_close_sync symbol is exported by the kernel, again you are trying to re-export the same symbol in md_mod module. Try not to export the symbol, compile and try inserting the module (module should be compiled against the kernel version on which it is inserted). Go through stackoverflow link What will happen if two kernel module export same symbol. Hope it answers your question :-).

Make virtualbox kernel modules builtin, rather than modules, half done

I was trying to make virtualbox kernel modules builtin, I'm almost completed here, but at the final step, it stopped compiling, because kernel seems to treat all vbox* modules as a single one:
drivers/vboxnetadp/built-in.o: In function `cleanup_module':
(.exit.text+0x0): multiple definition of `cleanup_module'
drivers/vboxdrv/built-in.o:(.exit.text+0x0): first defined here
drivers/vboxnetadp/built-in.o: In function `init_module':
(.init.text+0x0): multiple definition of `init_module'
.. suppressed output ...
make[1]: *** [drivers/built-in.o] Error 1
make: *** [drivers] Error 2
Any thoughts ? Here's how I got that:
I copied all module sources into drivers folder, edit the makefile, put a obj-y += vbox/, and edit all Makefile of vbox modules, change obj-m to obj-y to make them builtin, pretty dirty hack, but worked.
EDIT
Why need to do that ? I need to disable module loading on my machine, so no modules should be present, I've made all modules wrote by myself builtin, only thing left is vbox's ones now
I would say your question rather belongs to Stack Overflow, since it is basically a c-programming-language-question.
The problem you are facing is that you try to compile two (previously separate) programs into one. Both seem to use the same functions - meant within their own context.
My guess is that you will have to rename all these multiple occurrences of init_module or other functions into separate name-spaces (like net_init_module and drv_init_module). Or perhaps there is a way to declare these functions to be "local" - it`s been a while that I programmed in C...

how to define if a kernel program is intended to be a module or built-in

I have written a Linux kernel module, which I included in a kernel downloaded from kernel.org. I modified the Kconfig file of the directory where my module will be to include it in the configuration menu.
But when I run make menuconfig, I can only select it as built-in, I can't make it run as a module. What determines if a program is intended to be only built-in or only module or both?
I already figured out how to do it.
For a kernel program to be compiled "module only" it must be depending on "m". By example:
config FOO
depends on m
This will limit FOO to be module (=m) or disabled (=n).
For more information:
http://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt

Export kernel module headers to userspace

I am writing a Linux kernel module which need to export some header files to userspace.
I am wondering if there is any standard method which use Kernel package to do required sanitation of headers (For example something like "$(MAKE) -C $(KERNELDIR) M=$(PWD) headers_install" if exist).
Should i take care of headers manually?
Any suggestion?
There is no such functionality out of the box because most kernel modules which need something like that come with an extra "devel" package which contains the (cleaned) header files and probably a shared library to talk to the module.
As for cleaning your headers, I suggest to split the header files into a generic part (which you export) and an internal part (which only the kernel module can see). typedef is your friend.
You can do it by adding 'header-y=' to one of the Kbuild under /include/uapi

Resources