Replacing static function in kernel module

4

Folks,

I'm trying to hack a kernel module by modifying its symbol. The basic idea is to replace the original function with new function by overwriting its address in the symtab. However, I found when declaring the function as static, the hacking fails. But it works with non-static function. My example code is below:

filename: orig.c

int fun(void) {
    printk(KERN_ALERT "calling fun!\n");
    return 0;
}
int evil(void) {
    printk(KERN_ALERT "===== EVIL ====\n");
    return 0;
}
static int init(void) {
    printk(KERN_ALERT "Init Original!");
    fun();
    return 0;
}
void clean(void) {
    printk(KERN_ALERT "Exit Original!");
    return;
}
module_init(init);
module_exit(clean);

Then I follow the styx's article to replace the original function "fun" in symtab to call function "evil", http://www.phrack.org/issues.html?issue=68&id=11

>objdump -t orig.ko
...
000000000000001b g     F .text  000000000000001b evil
0000000000000056 g     F .text  0000000000000019 cleanup_module
0000000000000036 g     F .text  0000000000000020 init_module
0000000000000000 g     F .text  000000000000001b fun
...

By executing the elfchger

>./elfchger -s fun -v 1b orig.ko
[+] Opening orig.ko file...
[+] Reading Elf header...
    >> Done!
[+] Finding ".symtab" section...
    >> Found at 0xc630
[+] Finding ".strtab" section...
    >> Found at 0xc670
[+] Getting symbol' infos:
>> Symbol found at 0x159f8
>> Index in symbol table: 0x1d
[+] Replacing 0x00000000 with 0x0000001b... done!

I can successfully change the fun's symbol table to be equal to evil and inserting the module see the effects:

000000000000001b g     F .text  000000000000001b evil
...
000000000000001b g     F .text  000000000000001b fun
> insmod ./orig.ko
> dmesg
[ 7687.797211] Init Original!
[ 7687.797215] ===== EVIL ====

While this works fine. When I change the declaration of fun to be "static int fun(void)" and follows the same steps as mentioned above, I found the evil does not get called. Could anyone give me some suggestion?

Thanks, William

static
kernel
static-methods
static-linking
asked on Stack Overflow Jun 6, 2013 by William Tu

1 Answer

4

Short version: Declaring a function as 'static' makes it local and prevents the symbol to be exported. Thus, the call is linked statically, and the dynamic linker does not effect the call in any way at load time.


Long Version

Declaring a symbol as 'static' prevents the compiler from exporting the symbol, making it local instead of global. You can verify this by looking for the (missing) 'g' in your objdump output, or at the lower-case 't' (instead of 'T') in the output of 'nm'. The compiler might also inline the local function, in which case the symbol table wouldn't contain it at all.

Local symbols have to be unique only for the translation unit in which they are defined. If your module consisted of multiple translation units, you could have a static fun() in each of them. An nm or objdump of the finished .ko may then contain multiple local symbols called fun.

This also implies that local symbols are valid only in their respective translation unit, and also can be referred (in your case: called) only from inside this unit. Otherwise, the linker just would not now, which one you mean. Thus, the call to static fun() is already linked at compile time, before the module is loaded.

At load time, the dynamic linker won't tamper with the local symbol fun or references (in particular: calls) to it, since:

  1. its local linkage already done
  2. there are potentially more symbols named 'fun' throughout and the dynamic linker would not be able to tell, which one you meant
answered on Stack Overflow Jun 12, 2013 by ovenror • edited Jun 14, 2013 by ovenror

User contributions licensed under CC BY-SA 3.0