在不知道返回类型的情况下将结构的成员初始化为函数指针

我有这个结构:

typedef struct xyz_data { void *myfa; <------- correct void *myfb; <------- incorrect } 

而这个function定义:

 asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count); asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count); 

(正如你可能猜测的那样,这将指向内核的__NR_read )。

*myfa;保存到*myfa; 就像xyz_data_something->myfa = hooked_sys_read一样简单,但myfb怎么样? 我不确定xyz_data_something->myfb = &real_sys_read是否有效。

我正在劫持一些系统调用(如果你对项目感兴趣,一切都在GitHub中可用),每个被劫持的系统调用都会使用该结构来调用它所属的真实系统调用(将通过*myfb访问),使用返回值。

请记住,每个系统调用都有自己的返回类型。

脚本

 typedef struct xyz_data { void *myfa; void *myfb; } xyz_data; // Type name assumed — not specified in question asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count); asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count); xyz_data *xyz_data_something = ...; xyz_data_something->myfa = hooked_sys_read; xyz_data_something->myfb = &real_sys_read; 

分析

你写的不是类型安全的(因此编译器对你没有多大帮助),但是你正在获取保存指向’real sys read’函数的变量的地址,而不是该指针的副本(因为的& )。 你可以毫不犹豫地将& (和* )应用于函数名称,它们最终都是一样的:

 reader->myfa = &hooked_sys_read; reader->myfa = hooked_sys_read; reader->myfa = *hooked_sys_read; reader->myfa = **hooked_sys_read; reader->myfa = ***hooked_sys_read; reader->myfa = ****hooked_sys_read; 

你不能用指向函数的指针来做到这一点。 请注意,当您执行以下操作时,编译器甚至无法诊断“分配给对象指针的函数指针”问题:

 xyz_data_something->myfb = &real_sys_read; 

您正在将(函数)指针变量的地址分配给void * ,因此您要将对象指针指定给void指针,这是合法的 – 但不正确。

合成

您应该具有以下两个函数类型typedef之一:

 typedef ssize_t ReadFunction(unsigned int fd, char __user *data, size_t size); typedef ssize_t (*ReadPointer)(unsigned int fd, char __user *data, size_t size); 

那么你的结构可以是:

 typedef struct xyz_data { ReadFunction *myfa; ReadFunction *myfb; } xyz_data; 

要么:

 typedef struct xyz_data { ReadPointer myfa; ReadPointer myfb; } xyz_data; 

给定一个结构指针:

 xyz_data *reader = ...; 

以下分配将干净地编译并正常工作(对于两种结构类型):

 reader->myfa = hooked_sys_read; reader->myfb = real_sys_read; 

概念certificate

 #include  #define asmlinkage #define __user asmlinkage ssize_t (*real_sys_read)(unsigned int fd, char __user *buf, size_t count); asmlinkage ssize_t hooked_sys_read(unsigned int fd, char __user *buf, size_t count); typedef ssize_t (*ReadPointer)(unsigned int fd, char __user *data, size_t size); typedef struct xyz_data { ReadPointer myfa; ReadPointer myfb; } xyz_data; extern xyz_data getter(void); xyz_data getter(void) { xyz_data data; xyz_data *reader = &data; reader->myfa = hooked_sys_read; reader->myfb = real_sys_read; // The next line fails to compile: assignment from incompatible pointer type // reader->myfb = &real_sys_read; reader->myfa = &hooked_sys_read; reader->myfa = hooked_sys_read; reader->myfa = *hooked_sys_read; reader->myfa = **hooked_sys_read; reader->myfa = ***hooked_sys_read; reader->myfa = ****hooked_sys_read; return *reader; } 

它编译得很干净。 然而,这不是一个好的代码 – 单独的重复分配就足以使它变坏。

您不应该将函数指针指定给void指针。

请参阅https://stackoverflow.com/a/5579907/1351983 。