Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I replace a Linux kernel function with a module?

Im getting into kernel work for a bit of my summer research. We are looking to make modifications to the TCP, in specific RTT calculations. What I would like to do is replace the resolution of one of the functions in tcp_input.c to a function provided by a dynamically loaded kernel module. I think this would improve the pace at which we can develop and distribute the modification.

The function I'm interested in was declared as static, however I've recompiled the kernel with the function non-static and exported by EXPORT_SYMBOL. This means the function is now accessible to other modules/parts of the kernel. I have verified this by "cat /proc/kallsyms".

Now I'd like to be able to load a module that can rewrite the symbol address from the initial to my dynamically loaded function. Similarly, when the module is to be unloaded, it would restore the original address. Is this a feasible approach? Do you all have suggestions how this might be better implemented?

Thanks!

Same as Overriding functionality with modules in Linux kernel

Edit:
This was my eventual approach.
Given the following function (which I wanted to override, and is not exported):

static void internal_function(void) 
{
  // do something interesting
  return;
}

modify like so:

static void internal_function_original(void)
{
  // do something interesting
  return;
}

static void (*internal_function)(void) = &internal_function_original;
EXPORT_SYMBOL(internal_function);

This redefines the expected function identifier instead as a function pointer (which can be called in a similar manner) pointing to the original implementation. EXPORT_SYMBOL() makes the address globally accessible, so we can modify it from a module (or other kernel location).

Now you can write a kernel module with the following form:

static void (*original_function_reference)(void);
extern void (*internal_function)(void);

static void new_function_implementation(void)
{
  // do something new and interesting
  // return
}

int init_module(void)
{
  original_function_reference = internal_function;
  internal_function           = &new_function_implementation;
  return 0;
}

void cleanup_module(void)
{
  internal_function = original_function_reference;
}

This module replaces the original implementation with a dynamically loaded version. Upon unloading, the original reference (and implementation) is restored. In my specific case, I provided a new estimator for the RTT in TCP. By using a module, I am able to make small tweaks and restart testing, all without having to recompile and reboot the kernel.

like image 634
Willi Ballenthin Avatar asked Jul 28 '09 21:07

Willi Ballenthin


People also ask

How a module can be used with a kernel?

Kernel modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system. A module can be configured as built-in or loadable.

Is kernel module necessary?

A kernel module (or loadable kernel mode) is an object file that contains code that can extend the kernel functionality at runtime (it is loaded as needed); When a kernel module is no longer needed, it can be unloaded. Most of the device drivers are used in the form of kernel modules.

What is a module in Linux?

Linux modules are lumps of code that can be dynamically linked into the kernel at any point after the system has booted. They can be unlinked from the kernel and removed when they are no longer needed. Mostly Linux kernel modules are device drivers, pseudo-device drivers such as network drivers, or file-systems.


1 Answers

I'm not sure that'll work - I believe the symbol resolution for the internal calls to the function you want to replace will have already been done by the time your module loads.

Instead, you could change the code by renaming the existing function, then creating a global function pointer with the original name of the function. Initialise the function pointer to the address of the internal function, so the existing code will work unmodified. Export the symbol of the global function pointer, then your module can just change its value by assignment at module load and unload time.

like image 53
caf Avatar answered Oct 13 '22 00:10

caf