export per cpu symbol for kernel module - linux

I'm trying to export a per-cpu symbol "x86_cpu_to_logical_apicid" from kernel so that my kernel module can access it. In "arch/x86/kernel/apic/x2apic_cluster.c", I did
//static DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); //I remove static
EXPORT_PER_CPU_SYMBOL(x86_cpu_to_logical_apicid); // I add this
And after I recompile the kernel, the /proc/kallsyms shows
0000000000011fc0 V x86_cpu_to_logical_apicid
0000000000012288 V x86_cpu_to_node_map
ffffffff8187df50 r __ksymtab_x86_cpu_to_apicid
Then I try to access the "x86_cpu_to_logical_apicid" in my kernel module, by using
int apicid = per_cpu(x86_cpu_to_logical_apicid, 2)
However, when I loaded it, it fails to load it due to "Unknown symbol in module". The flag "V" means weak object, however I'm not sure whether this is the reason I fails to export the symbol. Can anyone give me some suggestions? Thank you!

I realize that the OP perhaps is not interested in the answer anymore, but today I had a similar issue, and I thought it might help others as well.
Before using an exported per_cpu variable in a module, you have to declare it first. For your case:
DECLARE_PER_CPU(u32, x86_cpu_to_logical_apicid);
Then you can use get_cpu_var and put_cpu_var to safely access the current processor's copy of the variable. You can read more here.

Related

"WARNING, putname undefined" when complie my kernel module

I was writing a kernel module that will check some thing in VFS . In this module, I need to use the kernel API "putname" which is defined as:
#ifdef CONFIG_AUDITSYSCALL
void putname(const char *name)
{
if (unlikely(!audit_dummy_context()))
audit_putname(name);
else
__putname(name);
}
EXPORT_SYMBOL(putname);
When I complied it in Fedora 18 with kernel 3.6.10, Everything is OK, the module works fine, but when I switch it to kernel 3.11.4. The complier gave me a warnning "putname is undefined", When I replace "putname" with "__putname", the kernel module can be complied but when it was running, something will go wrong. the backtrace shows that it was in __putname. Is there anybody can help me on this issue?
Thanks
See the commit #91a27b2a756784714e924e5e854b919273082d26 from Jeff:
This patchset converts the getname()/putname() interfaces to return a struct instead of a string. For now, the struct just tracks the string in kernel space and the original userland pointer for it.
The interface was changed right after the v3.6. So you have to rework your code taking this change into account.

what is __ksymtab? in linux kernel

when we cat 'proc/kallsyms' or 'system.map' we get symbols like this
....
c033718c T nf_hook_slow
c04ca284 r __ksymtab_nf_hook_slow
c04ca28c r __ksymtab_nf_hooks
c04d24a0 r __kcrctab_nf_hook_slow
c04d24a4 r __kcrctab_nf_hooks
c04e9122 r __kstrtab_nf_hook_slow
c04e9179 r __kstrtab_nf_hooks
c054d854 D nf_hooks
c0571ca0 d nf_hook_mutex
....
what is the meaning of T, r, D, d stuffs?
I can find symbols in kernel source as EXPORT_SYMBOL(...)
but there are others prefixing with __ksymtab... or __kstrtab...
what are these?
Is is possible that there are symbols in System.map but excluded in /proc/kallsyms?
(assuming kernel is compiled properly)
I have netfilter enabled linux kernel but I cant find the symbol 'nf_hooks'
but there is '__ksymtab_nf_hook'. is there some way to get address of nf_hooks
using __ksymtab_nf_hook?
I see in my linux source code EXPORT_SYMBOL(nf_hook) but I cant find it if I
'cat /proc/kallsyms'. is there some typical reason for this?
thank you in advance.
The format is similar to that of the output of nm utility, see also this page.
To put it simple, 'T' usually denotes a global (non-static but not necessarily exported) function, 't' - a function local to the compilation unit (i.e. static), 'D' - global data, 'd' - data local to the compilation unit. 'R' and 'r' - same as 'D'/'d' but for read-only data.
These are the items from the special sections needed to export symbols so that the symbols could be used by kernel modules.
For each exported symbol, al least the following is defined by EXPORT_SYMBOL():
__kstrtab_<symbol_name> - name of the symbol as a string
__ksymtab_<symbol_name> - a structure with the information about the symbol: its address, address of __kstrtab_<symbol_name>, etc.
__kcrctab_<symbol_name> - address of the control sum (CRC) of the symbol - it is used, for example, to check if the kernel or a module provides an exactly the same symbol as needed by a given kernel module. If a module requires a symbol with a given name and CRC and the kernel provides a symbol with that name but a different CRC (e.g. if the module was compiled for a different kernel version), the module loader will refuse to load that kernel module (unless this check is disabled).
Take a look at the implementation of EXPORT_SYMBOL() macro in linux/export.h for details.
Not sure but I have not encountered a situation so far when a function ("text symbol") or a variable ("data symbol") was present in System.map but not shown in /proc/kallsyms if the kernel is compiled properly and with kallsyms fully enabled (CONFIG_KALLSYMS=y, CONFIG_KALLSYMS_ALL=y). If CONFIG_KALLSYMS_ALL=n, only the functions (to be exact, symbols from *.text sections) will be shown in /proc/kallsyms.
Depends on your kernel version. You can take a look at the definition of EXPORT_SYMBOL() for your kernel and find which type __ksymtab_<symbol_name> variables are. In the kernel 3.11, it is struct kernel_symbol defined in linux/export.h. Having the definition of that struct and its address, I suppose, you can get the address of the symbol: struct kernel_symbol::value. Haven't tried this myself though.
Note, however, that __ksymtab_nf_hook is for nf_hook but not for nf_hooks. The name must match. nf_hooks and nf_hook are different entities.
Hard to tell without seeing the code and the relevant part of /proc/kallsyms. Maybe it is #ifdef'ed out and not compiled at all, may be there is something else.
Besides, nf_hooks is a data item so it might not show up in /proc/kallsyms if CONFIG_KALLSYMS_ALL is 'n'.

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 :-).

EXPORT_SYMBOL does not export symbols globally

I'm running a 3.4.7 kernel on my box and writing my own kernel modules, one of which should call functions in other modules.
I used EXPORT_SYMBOL to make the functions accessible to the other kernel modules. In my case, my module 'klm_sse' does this.
Now I load another module that uses the symbols exported by 'klm_sse', but when I load it, it complains:
[22892.216551] klm_<...>: Unknown symbol sys_srv_register_multiple (err 0)
Here is the output of 'cat /proc/kallsyms | grep klm_sse', where klm_sse is my module name.
ffffffffa013d170 r __ksymtab_sys_srv_register_multiple [klm_sse]
ffffffffa013d28b r __kstrtab_sys_srv_register_multiple [klm_sse]
ffffffffa012e9b0 t sys_srv_register_multiple [klm_sse]
From the 'man' pages I read that if an entry from /proc/kallsyms shows a lower case letter, here 'r' and 't', it means that the symbols are not globally exported.
How do I make my exports globally visible, so others can access it?
Is it a kernel compile option that is needed to fix this? Appreciate any inputs regarding this, I am literally banging my head on this for two days!
Thanks a million in advance

do we need both EXPORT_SYMBOL and head file declaration

I am new to the linux kernel. I have searched a little bit of EXPORT_SYMBOL but I still get a little confused. I know it's used to export a variable or function defined in one module to another module. Does that mean by using that, we do not need to include any header file that declares that variable or function? Or are they both needed? If both needed , why do we need to have EXPORT_SYMBOL? Thanks,
Header files are for the compiler. EXPORT_SYMBOL is for the module loader. This allows for proper separation of module code from kernel code.

Resources