一尘不染

我可以用模块替换Linux内核功能吗?

linux

我在暑期研究中从事内核工作。我们希望在特定的RTT计算中对TCP进行修改。我想做的是将tcp_input.c中的功能之一的分辨率替换为由动态加载的内核模块提供的功能。我认为这将改善我们开发和分发修改的速度。

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

现在,我希望能够加载一个模块,该模块可以将符号地址从初始重写为动态加载的函数。同样,当要卸载模块时,它将恢复原始地址。这是可行的方法吗?大家都有建议如何更好地实施吗?

谢谢!

Linux内核中的模块的覆盖功能 相同

编辑:
这是我最终的方法。
给定以下功能(我想覆盖它,但不导出):

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()使地址可全局访问,因此我们可以从模块(或其他内核位置)对其进行修改。

现在,您可以使用以下形式编写内核模块:

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提供了一个新的估算器。通过使用模块,我可以进行细微调整并重新开始测试,而无需重新编译和重新启动内核。


阅读 321

收藏
2020-06-07

共1个答案

一尘不染

我不确定是否可以正常工作-我相信要在模块加载时已经完成了对要替换的函数的内部调用的符号解析。

相反,您可以通过重命名现有函数,然后使用该函数的原始名称创建一个全局函数指针来更改代码。将函数指针初始化为内部函数的地址,因此现有代码将保持不变。导出全局函数指针的符号,然后您的模块就可以通过在模块加载和卸载时进行赋值来更改其值。

2020-06-07