我有这个结构:
typedef struct xyz_data {
void *myfa; <------- correct
void *myfb; <------- incorrect
}
和这个函数定义:
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
)。
将hooked_sys_read
保存到*myfa;
就像xyz_data_something->myfa = hooked_sys_read
一样简单,但myfb
呢?我不确定xyz_data_something->myfb = &real_sys_read
是否可行。
我正在劫持一些系统调用(如果你对该项目感兴趣,一切都在GitHub中可用),每个被劫持的系统调用将使用该结构来调用它所属的真实系统调用(将通过{{1访问)使用返回的值。
请记住,每个系统调用都有自己的返回类型。
答案 0 :(得分:2)
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;
#include <sys/types.h>
#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;
}
它干净利落地编译。然而,这不是一个好的代码 - 单独的重复分配足以使它变坏。
答案 1 :(得分:1)
您不应该将函数指针指定给void指针。