2

I have been using this process check-pointing project from Berkeley labs (namely, BLCR). And I noticed that they have been referencing some functions in the kernel that were not exported nor they were declared in any of the header files. Their code consists of kernel modules and some user-space utilities. So, they do not need to apply any kernel patches.

Their configure script generated some header files that declare these functions as externs and then assign some pointer value to each of the called functions. I am not sure how they generate these pointers to functions or how they are using them.

My question is: is there any way to call an in-kernel function without exporting that function and without declaring it in a header file?

feeling_lonely
  • 6,665
  • 4
  • 27
  • 53

3 Answers3

10

Most basic way:

Address can located by parsing System.map or /proc/kallsyms (you may need to be root to see addresses, a normal user may see zeros here).

Function prototype can be found by looking at Kernel source.

If we wanted to call

void __stack_chk_fail(void) 

Without using the exported symbol we would resolve an address and declare like:

void (*scf)(void) = (int (*)() ) 0xffffffff810519d0;

Then call with:

scf(); 

(__stack_chk_fail is actually exported but was the first function with no parameters I saw when answering the question).

JOgden
  • 316
  • 1
  • 7
3

Anyway, after some grepping and reading code I can give you my idea, though it might be not 100% correct.

As you said

Their configure script generated some header files that declare these functions as externs and then assign some pointer value to each of the called functions.

This can be done by simple investigating of System.map file. It's a text file that holds table with kernel symbols and their addresses. Having that file some script can look in System.map for needed symbols (function names), get address for that function and generate externs with found pointers. Nice hack.

Alexander Dzyoba
  • 4,009
  • 1
  • 24
  • 29
  • Yeah, sorry I did not update my questions, but I did some more investigation and found out the same thing. You can also get the kernel symbol table from /proc/kallsyms. However, in my machine it was showing all zeros for addresses from that proc entry. – feeling_lonely Mar 04 '14 at 07:49
  • The next thing to figure out though, now that we have an address what to do with it? Yeah, we have a pointer and from reading the source we have the signature. I want to go all the way to calling an in-kernel function that way. – feeling_lonely Mar 04 '14 at 07:51
  • @mjs what you are talking about? I love this. The map of the compiled kernel never changes. Well, unless you use something like Ksplice. – feeling_lonely Mar 04 '14 at 07:54
  • @hebbo, you declare function pointer with given address and function prototype from kernel sources and then invoke kernel function via function pointer. Just like in JOgden answer. – Alexander Dzyoba Mar 04 '14 at 13:50
0

Based on @JOgden's answer, using not-exported symbol need to consider ASLR (KASLR). If ASLR is enable, the address you get from system.map is wrong.

You need to find out the offset and add the absolute value from system.map.

Following is one of the way to get the offset:

offset = &system_wq - system_wq_addr;

system_wq is identifier and system_wq_addr is address of system_wq get from system.map

Steven
  • 811
  • 4
  • 23