我可以用模块替换 Linux 内核函数吗? [英] Can I replace a Linux kernel function with a module?

查看:30
本文介绍了我可以用模块替换 Linux 内核函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了我的一些暑期研究,我正在进入内核工作.我们希望在特定的 RTT 计算中对 TCP 进行修改.我想做的是将 tcp_input.c 中的一个函数的解析替换为动态加载的内核模块提供的函数.我认为这会加快我们开发和分发修改的速度.

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.

我感兴趣的函数被声明为静态函数,但是我已经使用非静态函数重新编译了内核并由 EXPORT_SYMBOL 导出.这意味着该函数现在可以被内核的其他模块/部分访问.我已经通过cat/proc/kallsyms"验证了这一点.

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?

谢谢!

在 Linux 内核中使用模块覆盖功能


这是我最终的方法.
给定以下函数(我想覆盖它,并且没有导出):


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;
}

像这样修改:

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

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

这将预期的函数标识符重新定义为指向原始实现的函数指针(可以以类似方式调用).EXPORT_SYMBOL() 使地址全局可访问,因此我们可以从模块(或其他内核位置)修改它.

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;
}

这个模块用动态加载的版本替换了原来的实现.卸载后,将恢复原始引用(和实现).在我的特定情况下,我为 TCP 中的 RTT 提供了一个新的估计器.通过使用模块,我可以进行小的调整并重新开始测试,而无需重新编译和重新启动内核.

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.

推荐答案

我不确定这是否可行 - 我相信对要替换的函数的内部调用的符号解析已经由加载模块的时间.

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.

这篇关于我可以用模块替换 Linux 内核函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆