Why can't some functions be used in kernel modules? - c

For examples, in pgtable_types.h, the function prototype:
extern pte_t *lookup_address(unsigned long address, unsigned int *level);
Is clearly present in the header file.
However when I compile a kernel module with this function and then insmod the .ko output file I get a lookup_address symbol not found error.
Why is this?

Does your module have a MODULE_LICENSE("GPL v2") line in it? If not, it is assumed to be proprietary and will not allow access to GPL symbols which lookup_address is marked as.

Related

Unknown symbol when loading a kernel module

I tried to redo the code of the kernel module found in this topic How can I obtain battery level inside a Linux kernel module?. But when I try to use the functions contained in the power_supply.h header file, the loading of the module fails because it does not recognize the power_supply_get_by_name function.
Here is the code that I am using on Ubuntu 18.04 with kernel version 4.15.0-101-generic:
#include <linux/module.h>
#include <linux/power_supply.h>
static int __init test_init (void)
{
struct power_supply *psy;
char name[] = "BAT1";
psy = power_supply_get_by_name(name);
printk(KERN_DEBUG "Test module inserted");
return 0;
}
static void __exit test_exit (void)
{
printk(KERN_DEBUG "Test module removed");
}
module_init (test_init);
module_exit (test_exit);
I get no error at compiling except a warning concerning the module license which is I think not related to my problem but I get the following errors:
when running insmod in the terminal: "insmod: ERROR: could not insert module test.ko: Unknown symbol in module"
in the /var/log/kern.log file: "test: Unknown symbol power_supply_get_by_name (err 0)"
I checked the kallsyms proc file and the function is indicated as usable in other kernel modules if I understood well this topic What is the difference between T and t in /proc/kallsyms. Here is the output from reading the kallsyms file:
ffffffff8e9bd270 T power_supply_get_by_name
Does anyone knows why this is not working while I can use other linux headers functions without any problem and, if so, how I can fix my problem?
Thanks in advance
This may actually be related to the module license! If you look at the kernel source code, the function power_supply_get_by_name is exported here. You can see it's using EXPORT_SYMBOL_GPL. As this answer explains:
EXPORT_SYMBOL_GPL will show the symbol only in GPL-licensed modules
The use of this macro is controversial, but that's the way the project operates... To gain access to the symbols you need, you'll need to license your module as GPL:
MODULE_LICENSE("GPL");

Undefined symbol when using insmod

I write a linux-kernel module, but when I run this command insmod ./...ko, the kernel posts an error: Undefined symbol ...
After that, I searched for a long time, all the solutions are to use EXPORT_SYMBOL(), so I write it in kernel codes and rebuild the kernel. Interesting things happen, the kernel says exports duplicate symbol ... (owned by kernel). It seems that the symbol is exported more than once, but if so, why can I not use it before?
This is related code in my module:
extern struct task_struct *find_task_by_vpid(pid_t nr);
target_tsk = pid == -1 ? current : find_task_by_vpid(pid);
and I changed the kernel file linux/sched.h to this format:
extern struct task_struct *find_task_by_vpid(pid_t nr);
EXPORT_SYMBOL_GPL(find_task_by_vpid);
Symbol exporting (EXPORT_SYMBOL) should be performed in a source file (.c), not in a header file (.h).
This is because exporting symbol is a definition of (some other) symbol, and header files a not suitable for such things.

Exported kvm kernel functions get undefined warning when compiling a kernel driver that calls them

I'm trying to call two exported (maybe) kernel functions from the KVM - kvm_write_guest and kvm_get_segment but when I compile a kernel driver that will call these two functions I get a warning saying they are undefined.
WARNING: "kvm_write_guest" [/home/driver.ko] undefined!
WARNING: "kvm_get_segment" [/home/driver.ko] undefined!
When I executed the commands:
cat /proc/kallsyms | grep kvm_get_segment
cat /proc/kallsyms | grep kvm_write_guest
to check to see if they are exported I get the following:
0000000000000000 t kvm_write_guest [kvm]
0000000000000000 t kvm_get_segment [kvm]
Below are the protocols and includes that I have in the header file that is included in the .c file that calls these functions. I pulled the prototypes from the kvm_main.c code.
#include <linux/kvm.h>
#include <linux/kvm_types.h>
#include <linux/kvm_host.h>
int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, unsigned long len);
void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
When I dig into the kvm_main.c source code for kvm_write_guest they don't seem to be exported using the following code:
EXPORT_SYMBOL_GPL(kvm_write_guest);
When I dig into the x86.c code for kvm_get_segment it isn't exported using that method either. It doesn't seem that they are in fact exported but I want to make sure I'm not doing something wrong. I'd like to avoid patching the code and recompiling if I can. Thank in advance for any help it is greatly appreciated!
You're not doing anything wrong. If they're not exported with EXPORT_SYMBOL or EXPORT_SYMBOL_GPL, you won't be able to call them from a module.
Looks like you have two different problems. kvm_get_segment is only defined in arch/x86/kvm/x86.c and is not exported. So another module can't link to it (without patching the source or playing complicated tricks at runtime).
On the other hand, as you point out, kvm_write-guest is exported, with:
EXPORT_SYMBOL_GPL(kvm_write_guest);
That means only GPL-licensed modules can link to it; you'll need to put
MODULE_LICENSE("GPL");
in your driver to use that symbol. (And make sure you understand the legal implications of doing that)

how I call a function in my source file including only header file in c?

I would like to know , if I have source file like this
#include <stdio.h>
int main()
{
printf("Hello world");
}
as I know header files contains only prototypes of functions. If it so how can my source file get the function printf ? If I don't include the source file where it has been declared?
thank you
The question is not clear, but there are 2 things which happen before a program gets created,
Compiling (requires prototypes / declarations)
Linking (requires definitions).
Header information is needed for knowing prototypes. Even this would compile fine:
int printf ( const char * format, ... );
int main()
{
printf("Hello world");
}
On linking there will be no issues because the printf function is found in the C standard library, so on linking it will look into the standard directories (of the compiler where the library is kept - bin/lib folder) and link the function.
The source only needs to know the prototype. The problem a programmer will have in this case:
int my_printf ( const char * format, ... );
int main()
{
my_printf("Hello world");
}
The above will compile, but when linking my_printf your code will not have a definition so it will give an error on linking.
Header file has the definitions declarations of the functions ( stdio.h has definition declaration for printf ). The actual function exists in the libraries and gets linked when you compile the code.
When it comes to using libraries, you include the header of the library in your code and you instruct the linker to link using the code files of that library(usually object files). For the standard libraries, the IDE usually instructs the linker to link to them by default.
Assuming you're using gcc as a compiler the standard libraries are linked by default and that is where the function definitions lie. If you'd like to see exactly which libraries are being linked you can pass gcc the -v option which will cause it to dump information about the default options it will use including the library paths and default libraries and object files that will be linked in.
If you give the -Wl,--verbose option, gcc will pass the --verbose to the linker which will dump exactly where it's looking for libraries, including both failed and successful searches
gcc -v foo.c -Wl,--verbose
The header file stdio.h would declare printf as an extern function, i.e., it is defined elsewhere. The compiler is happy as long as functions you use have a declaration. The linker is the one that resolves these dependencies.
A very useful thing to do when you start asking good questions like this is to play with some linker commands.
Assuming you're on *nix, once you have your executable file (lets call it foo), do:
ldd foo
You should see a list of libraries that were linked with while creating foo.
libc.so should be one among those. It contains the definition for printf among other things!
You can refer to this link to learn more

Can anybody explain about following structure

What is the use of the below structure in linux kernel? I need to know it because I need to add a variable inside this structure.
static const struct modversion_info ____versions[]
It includes symbols referenced by the module and their checksums, when the module is inserted those symbols are checked to make sure the module is compiled for the running kernel.
On Ubnutu the kernel-headers package contains this file which has all the symbols exported by the kernel and their checksums, you should be able to find this file if you compiled your own kernel too
usr/src/linux-headers-2.6.38-generic/Module.symvers
Note, I'm not sure what you're trying to do but you shouldn't be adding symbols to your module, when you compile a module this structure is generated for you.

Resources