如何访问内核模块中的任何内核符号?

时间:2016-11-04 20:26:20

标签: c linux linux-kernel kernel-module

我想在我的内核模块中使用函数getname。它不会导出。由于我现在遇到这个问题,我想知道如何访问和使用任何未导出的内核符号。我认为使用一个步骤所需的步骤将根据符号的不同而有所不同,所以我想看看如何对一个类型(例如,一个结构),一个变量,一个指针表(如系统调用表)和一个函数。如何在以下任何一种情况下完成这些工作:

  • 当我知道来自System.map/proc/kallsyms的符号地址时。
  • 当我知道符号的名称并希望使用kallsyms_lookup_name来检索它时。

我目前知道如何劫持系统调用,这需要声明类似

的内容
asmlinkage <return_type> (*<name_for_system_call>)(<the types of the its arguments separated by commas>);

是否会使用这样的东西?在http://stackoverflow.com/a/32968387/1953537回答另一个问题,海报提供的例子是

#include <linux/kallsyms.h>

static void (*machine_power_off_p)(void);
machine_power_off = (void*) kallsyms_lookup_name("machine_power_off");

但是如果符号返回指针怎么办?我会在(*machine_power_off_p)的左边放一个星号吗?

2 个答案:

答案 0 :(得分:1)

#include <linux/fs.h>声明extern struct filename *getname(const char __user *);。指向此函数的指针具有类型struct filename *(*)(const char __user *)。如果声明该类型的变量,则变量名称位于*中的(*)之后。因此,您可以声明该类型的变量,并将kallsyms_lookup_name("getname")的返回值分配给它,如下所示:

static struct filename *(*getname_p)(const char __user *);

getname_p = (struct filename *(*)(const char __user *))
            kallsyms_lookup_name("getname");

对于您想要使用数字地址的其他情况,只需将kallsyms_lookup_name函数调用替换为实际数字(kallsyms_lookup_name无论如何都将符号值作为数字返回)。

答案 1 :(得分:0)

访问未导出的功能与访问导出的功能并不相同,只是您无法在内核中解析其地址。你可以这样做:

static void (*your_func)(void);
your_func=0xhex_addr;

或结构

strucr your_struct{int i;double j} *stru;
stru=0xhex_addr;

指针的类型只定义从指针的地址读取或写入的字节数。

对于结构或变量十六进制地址,甚至可能驻留在内核代码段中,但如果您尝试将某些内容写入该结构或var,则会导致分段错误 - 读取将是合法的。还有一件事......当用结构做这个技巧时,不要忘记结构数据的对齐。