Alternative to the GPL *find_symbol* method in Linux kernel module - c

I have a proprietary Linux module which might be loaded before or after a second proprietary module that contain the function foo.
I would like my first module, when being configured dynamically, to lookup for the second's module symbol foo, and if found to call it.
The general idea (in loose syntax) is this:
/* check if the module/symbol can be found */
module, foo_cb = lookup_for_a_symbol("foo");
if (foo_cb && module) {
/* increment the refcnt to make sure the module will not be unloaded */
module_try_get(module);
foo_cb(my_params);
/* release the module */
module_put(module);
}
I found a function in module.c that does something like this called find_symbol, however it is GPL.
Any non-GPL alternative for dynamic symbol lookup ?
Thanks.

But your module does not export GPL symbols, so this should not be a problem. The only problem is if you want to be able to load proprietary module bar without loading foo.
Module foo should use EXPORT_SYMBOL() to export anything that will be used by bar.
If you need conditional dynamic linking, then add a third module to do this, which calls bar with the symbol from foo and use EXPORT_SYMBOL() in both foo and bar to make the necessary symbols available to module foobar.

Sorry I know it is a relatively old question, but I recently had the same need and I used a pretty obvious solution without creating a GPL helper module that nobody mentioned here, so I think it is worth mentioning.
scnprintf is non GPL, and it supports %pf or %pF format that does the symbol resolution you need. See printk formats

Related

In the latest linux kernel is it possible to write a loadable Linux Security Module (LSM), which can be loaded and unloaded using insmod and rmmod?

I am a beginner in the field of Linux kernel programming. I was studying Linux Security Modules (LSM). The references which I have seen (recent ones) especially this video here, bakes the module written into the kernel itself, and then the entire compiled kernel is installed on say an Ubuntu machine.
I was thinking of writing a program, such that instead of making it into the kernel itself, I could load and unload it as per my need. (Especially to test the correctness of its functionality, easily).
The video which I have mentioned above makes use of security_add_hooks to bind our function to the security subsystem. But, using the mention of security_add_hooks and LSM_HOOK_INIT which in turn uses security_hook_heads struct, causes an issue when I try to make a .ko file for this module.
ERROR: modpost: "security_add_hooks" [security/my_test.ko] undefined!
ERROR: modpost: "security_hook_heads" [security/my_test.ko] undefined!
I can understand that security_add_hooks is a function and has not been exported for use by the modules. So, I tried to EXPORT_SYMBOL(security_add_hooks) so that my .ko file can use it.
But another issue arises. Regarding two struct definitions, security_hook_heads and security_hook_list. I simply don't know how to export them. I tried to write a statement EXPORT_SYMBOL(security_hook_heads); just after the corresponding struct definition as follows, in lsm_hooks.h:
struct security_hook_heads {
#define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME;
#include "lsm_hook_defs.h"
#undef LSM_HOOK
} __randomize_layout;
EXPORT_SYMBOL(security_hook_heads);
Corresponding to this I get the following error:
./include/linux/lsm_hooks.h:1601:15: error: ‘security_hook_heads’ undeclared here (not in a function)
1601 | EXPORT_SYMBOL(security_hook_heads);
I don't fully understand the meaning of the error, but I feel it is trying to point out that exporting a symbol from a header file is not possible.
So, I could not figure out how to work out this approach. Is there any other easy method available?
I was going through a few old YouTube videos and a few articles, where they make use of functions like register_security and unregister_security, but I guess these functions are no longer there in the latest Linux kernel (6.0.0). [As was mentioned in the thread of the following few questions: (1), see the comment to the answer for the previous question, (2)]
You can't do this in a module.
security_add_hooks is marked with __init.
It is linked into a special linker section (e.g. .init.text).
At a certain point in the kernel startup (see: kernel_init) it calls free_initmem.
After that, the memory occupied by these functions is reclaimed and can be used as ordinary memory.
So, by the time your module is loaded, security_add_hooks et. al. are long gone.
If you have to modify security/security.c to add EXPORT_SYMBOL(security_add_hooks), then you are building a custom kernel. So, you might as well just bake your code into the kernel.

Partially Linked Vxworks Image Project (VIP)

The product I work on is structured as several DKM projects referenced by my VIP project.
though, there is one "Unknown" function implementation, one that will be loaded later on in the init phase.
In order to load it:
1. I declare a function pointer (funcPtr).
2. after I call LoadModule() aka. ld()
3. call symFind() to get the address of the newly loaded symbol
4. assign the funcPtr the address.
I have problems with this solution as I must not have the symbol-table in my release build.
Its treated as sensitive organizational data, but without it I couldn't use symFind()
Any of the following question can mitigate or resolve my problem, so i'd appreciate any answer :)
When calling loadModule(myModule.o), is there a function in myModule that is called right after it is loaded?
Can I compile a VIP project with a missing extern symbol, like in linux.
that will be relocated later on when i use ld() for my module?
Can I limit the Symbol-Table to dispense the sym-tbl except for the few symbols I need, How?
I faced the same problem a while back. I have implemented the dynamic linking facility as the following (on VxWorks 6.8), assuming there exists a function with the signiture void* callMeDynamic():
use loadModule() to load needed object files.
Get the address(es) of the function.
I could not find an easy way to achieve this step. I found a work around as the following.
2.1. Create a pipe and divert the stdout as described in Using a VxWorks Pipe
2.2. Call lkup(callMeDynamic) and save the output using said pipe.
2.3. Parse the output of the lkup dump and get the address of your entry function.
Cast and assign the obtained address to a suitable function pointer
Call the function as needed
Hope this helps.
Answering my Questions:
When calling loadModule(myModule.o), is there a function in myModule that is called right after it is loaded?
Answer: Didn't use it.
Can I compile a VIP project with a missing extern symbol, like in linux. that will be relocated later on when i use ld() for my module?
Answer: No, a VIP is fully-linked and cannot have undefined symbols.
You can have Pointer to Functions, and assign their addresses when they become available.
Can I limit the Symbol-Table to dispense the sym-tbl except for the few symbols I need, How?
Answer: Yes, I used stripppc -K <symbol_to_keep> ... command in the make-file to achieve that.

building kernel module and resolve missing symbol definitions

If I build a module which depends on other modules, and i get this warning:
'function or symbol ?' [source dir/my_module.ko] undefined!
What does the warning mean?
The warning doesn't tell me if it is a function defined in a header or in some module source. I suppose this means some module symbol definition is missing . So do I have to rebuild all modules on which my module is depending?
Or may I somehow insert explicit symbols in my module source or in the makefile - for instance if I include the *.c source file where the missing symbols are defined in my module source? So to say - build my module without the need to build extra object files not in my source directory, on which my module depends.
Thanks in advance!
(If the symbols are not in /proc/kallsyms, it is likely that that the kernel source did not explicitly EXPORT_SYMBOL() those symbols. Hence, in order to use those symbols, you have several options:
1) Add EXPORT_SYMBOL() to each symbol in the source that your kmod needs
to link with, and then re-compile the kernel.
This option has several drawbacks. In my mind, the greatest drawback is that many distro's don't offer support for a recompiled kernel (re: SUSE SLES, etc.). Perhaps this solution would work for a one-off kmod. However, if you plan to distribute it to others, you will have to get a feel for how they take to the idea of recompiling their kernel.
2) Copy the entire function(s) from the kernel source into your code.
Of course, if the copied functions contain references to other kernel functions, which also lack EXPORT_SYMBOL() (and are not listed in /proc/kallsysm), this option isn't always helpful.
3) Find another Linux release, or distro, which exports the needed symbols.
I work a lot with SLES. I find that from one release to the next, kernel symbols come and go. There are also differences between SUSE, Redhat, etc., distros; where one may export the needed symbols.
Let's find where the function is defined. You should add EXPORT_SYMBOL() for missing function and compile the kernel (for built-in function) or a dependent module where the function is defined.
http://onebitbug.me/2011/03/04/introducing-linux-kernel-symbols/

Which headers and functions can I use in loadable kernel modules (except external libraries)?

Section 2 of the Linux man pages contains system calls.
http://linux.die.net/man/2/
After finding this link, I say "OK! I use this reference for developing every modules, It is complete".
But it seems I can not use some functions of this section (like bind(2)). After including required headers (like <sys/socket.h>) the module compilation failed.
Some functions/macros like printk does not listed in the section 2. Many people used Linux Apis that I could not find any official reference for it (just like printk). I don't know how they found these functions? (May be by reading whole source code of kernel instead of reading any reference)
Some functions like memset describes in section 3 (user space libraries) but kernel module developer can use it without any error!
Where I can found a COMPLETE reference of available headers and functions when developing a loadable kernel modules? (Something like MSDN and WINDDK references)
#include <linux/init.h>
#include <linux/module.h>
/* A complete list of availabe headers and functions is missing! */
static int my_init(void)
{
return 0;
}
static void my_exit(void)
{
return;
}
module_init(my_init);
module_exit(my_exit);
As you know, the Kernel is quite a big, big and independent beast. This means that you cannot include anything which is not found under your kernel source tree.
When you're implementing your module, that means the only things you can link to is what you got in :
The kernel source tree itself
Another module you've made (I would recommend to avoid this scenario though whenever possible ... )
Note that you will be able to use the functions only if they are exported. You can check this using the nm utility on the compiled .ko file of a module. If you want to export some symbols of your module, you have to use the macro EXPORT_SYMBOL.
Be careful not to confuse user-space includes, usually found under /usr/include with the kernel module headers (which you are likely wanting to link against).
In the example you gave, the sys/socket.h is the location of the header after a make headers_install. At this location, it is meant to be used by userspace applications. This is NOT what you want when you are programming a module.
I think you have to look deeper in the use of sockets in the kernel. By googling up a little, I found -> this <- on LWN and checked the include/linux/net.h header of my 3.8 kernel source tree. The patch described in the link is integrated in the kernel and is likely to be what you are looking for.
The memset example is also an illustration of what I explained this far : if you want to use it in a common application, you'll have to include the string.h header, which is simply located at /usr/include/string.h. Its kernel equivalent is found under ...
/your-kernel-source-tree-dir/include/linux/string.h
Et voila ! You can use memset and friends inside any piece of kernel code, as long as you include the right header !
Thus, when you feel some frustration, thinking Man, I was able to use this by simply including this header in my apps ... Take a deep look at the kernel source tree (or have grep do it for you ;) ). You are very likely to find what you are looking for !
As per my knowledge there is no such complete reference for kernel module programming. I suggest you study the LDD3 basic sections and http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN978 for a beginner.

How to catch unintentional function interpositioning?

Reading through my book Expert C Programming, I came across the chapter on function interpositioning and how it can lead to some serious hard to find bugs if done unintentionally.
The example given in the book is the following:
my_source.c
mktemp() { ... }
main() {
mktemp();
getwd();
}
libc
mktemp(){ ... }
getwd(){ ...; mktemp(); ... }
According to the book, what happens in main() is that mktemp() (a standard C library function) is interposed by the implementation in my_source.c. Although having main() call my implementation of mktemp() is intended behavior, having getwd() (another C library function) also call my implementation of mktemp() is not.
Apparently, this example was a real life bug that existed in SunOS 4.0.3's version of lpr. The book goes on to explain the fix was to add the keyword static to the definition of mktemp() in my_source.c; although changing the name altogether should have fixed this problem as well.
This chapter leaves me with some unresolved questions that I hope you guys could answer:
Does GCC have a way to warn about function interposition? We certainly don't ever intend on this happening and I'd like to know about it if it does.
Should our software group adopt the practice of putting the keyword static in front of all functions that we don't want to be exposed?
Can interposition happen with functions introduced by static libraries?
Thanks for the help.
EDIT
I should note that my question is not just aimed at interposing over standard C library functions, but also functions contained in other libraries, perhaps 3rd party, perhaps ones created in-house. Essentially, I want to catch any instance of interpositioning regardless of where the interposed function resides.
This is really a linker issue.
When you compile a bunch of C source files the compiler will create an object file for each one. Each .o file will contain a list of the public functions in this module, plus a list of functions that are called by code in the module, but are not actually defined there i.e. functions that this module is expecting some library to provide.
When you link a bunch of .o files together to make an executable the linker must resolve all of these missing references. This is the point where interposing can happen. If there are unresolved references to a function called "mktemp" and several libraries provide a public function with that name, which version should it use? There's no easy answer to this and yes odd things can happen if the wrong one is chosen
So yes, it's a good idea in C to "static" everything unless you really do need to use it from other source files. In fact in many other languages this is the default behavior and you have to mark things "public" if you want them accessible from outside.
It sounds like what you want is for the tools to detect that there are name conflicts in functions - ie., you don't want your externally accessible function names form accidentally having the same name and therefore 'override' or hide functions with the same name in a library.
There was a recent SO question related to this problem: Linking Libraries with Duplicate Class Names using GCC
Using the --whole-archive option on all the libraries you link against may help (but as I mentioned in the answer over there, I really don't know how well this works or how easy it is to convince builds to apply the option to all libraries)
Purely formally, the interpositioning you describe is a straightforward violation of C language definition rules (ODR rule, in C++ parlance). Any decent compiler must either detect these situations, or provide options for detecting them. It is simply illegal to define more than one function with the same name in C language, regardless of where these functions are defined (Standard library, other user library etc.)
I understand that many platforms provide means to customize the [standard] library behavior by defining some standard functions as weak symbols. While this is indeed a useful feature, I believe the compilers must still provide the user with means to enforce the standard diagnostics (on per-function or per-library basis preferably).
So, again, you should not worry about interpositioning if you have no weak symbols in your libraries. If you do (or if you suspect that you do), you have to consult your compiler documentation to find out if it offers you with means to inspect the weak symbol resolution.
In GCC, for example, you can disable the weak symbol functionality by using -fno-weak, but this basically kills everything related to weak symbols, which is not always desirable.
If the function does not need to be accessed outside of the C file it lives in then yes, I would recommend making the function static.
One thing you can do to help catch this is to use an editor that has configurable syntax highlighting. I personally use SciTE, and I have configured it to display all standard library function names in red. That way, it's easy to spot if I am re-using a name I shouldn't be using (nothing is enforced by the compiler, though).
It's relatively easy to write a script that runs nm -o on all your .o files and your libraries and checks to see if an external name is defined both in your program and in a library. Just one of the many sane sensible services that the Unix linker doesn't provide because it's stuck in 1974, looking at one file at a time. (Try putting libraries in the wrong order and see if you get a useful error message!)
The Interposistioning occurs when the linker is trying to link separate modules.
It cannot occur within a module. If there are duplicate symbols in a module the linker will report this as an error.
For *nix linkers, unintended Interposistioning is a problem and it is difficult for the linker to guard against it.
For the purposes of this answer consider the two linking stages:
The linker links translation units into modulles (basically
applications or libraries).
The linker links any remaining unfound symbols by searching in modules.
Consider the scenario described in 'Expert C programming' and in SiegeX's question.
The linker fist tries to build the application module.
It sess that the symbol mktemp() is an external and tries to find a funcion definiton for the symbol. The linker finds
the definition for the function in the object code of the application module and marks the symbol as found.
At this stage the symbol mktemp() is completely resolved. It is not considered in any way tentative so as to allow
for the possibility that the anothere module might define the symbol.
In many ways this makes sense, since the linker should first try and resolve external symbols within the module it is
currently linking. It is only unfound symbols that it searches for when linking in other modules.
Furthermore, since the symbol has been marked as resolved, the linker will use the applications mktemp() in any
other cases where is needs to resolve this symbol.
Thus the applications version of mktemp() will be used by the library.
A simple way to guard agains the problem is to try and make all external sysmbols in your application or library unique.
For modules that are only going to shared on a limited basis, this can fairly easily be done by making sure all
extenal symbols in your module are unique by appending a unique identifier.
For modules that are widely shared making up unique names is a problem.

Resources