初始化一个struct一个函数指针的成员不知道返回的类型 [英] Initializing a member of a struct to a function pointer without knowing the returned type

查看:121
本文介绍了初始化一个struct一个函数指针的成员不知道返回的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的结构:

  typedef结构xyz_data {
    无效* myfa; < -------正确
    无效* myfb; < -------不正确
}

和这个函数的定义:

  asmlinkage为ssize_t(* real_sys_read)(unsigned int类型FD,焦炭__user * buf中,为size_t计数);
asmlinkage ssize_t供hooked_sys_read(unsigned int类型FD,焦炭__user * buf中,为size_t计数);

(因为你可能会猜测,这将指向内核的 __ NR_read )。

保存 hooked_sys_read * myfa; xyz_data_something-&GT一样简单; myfa = hooked_sys_read ,但对于 myfb ?我不知道 xyz_data_something-> myfb =安培; real_sys_read 将工作

我劫持了一些系统调用(如果你有兴趣的项目,一切都在GitHub上可用),并且每个系统调用劫持将使用该结构来调用它属于(将要访问的系统调用真正通过 * myfb ),利用返回值的。

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


解决方案

场景

  typedef结构xyz_data {
    无效* myfa;
    无效* myfb;
} xyz_data; //类型名称假设 - 问题不指定asmlinkage为ssize_t(* real_sys_read)(unsigned int类型FD,焦炭__user * buf中,为size_t计数);
asmlinkage ssize_t供hooked_sys_read(unsigned int类型FD,焦炭__user * buf中,为size_t计数);xyz_data * xyz_data_something = ...;xyz_data_something-> myfa = hooked_sys_read;
xyz_data_something-> myfb =安培; real_sys_read;

分析

什么你写的是不是类型安全的(因此编译器能没有太大的帮助你),但你正在服用持有的指针变量的地址'真正SYS读功能,而不是一个的副本指针(因为&放大器; )。您可以将&安培; (和 * )函数名慎之又慎,他们都最终是相同的:

 阅读器> myfa =安培; hooked_sys_read;
阅读器 - > myfa = hooked_sys_read;
阅读器 - > myfa = * hooked_sys_read;
阅读器 - > myfa = ** hooked_sys_read;
阅读器 - > myfa = *** hooked_sys_read;
阅读器 - > myfa = **** hooked_sys_read;

您不能做到这一点与函数指针。注意,编译器甚至不能诊断当你做问题分配给对象的指针函数指针

  xyz_data_something-> myfb =安培; real_sys_read;

您正在分配(功能)指针变量的地址无效* ,所以你分配一个对象指针为void指针,它是合法的 - 但不正确。

合成

您应该有这两个函数类型的typedef之一:

 的typedef ssize_t供ReadFunction(unsigned int类型FD,焦炭__user *数据,为size_t大小);
类型定义为ssize_t(*读指针)(unsigned int类型FD,焦炭__user *数据,为size_t大小);

那么你的结构可以是:

  typedef结构xyz_data
{
    ReadFunction * myfa;
    ReadFunction * myfb;
} xyz_data;

或者

  typedef结构xyz_data
{
    读指针myfa;
    读指针myfb;
} xyz_data;

由于结构指针:

  xyz_data *读卡器= ...;

下面的分配将干净地编译和正常工作(用于结构类型):

 阅读器> myfa = hooked_sys_read;
阅读器 - > myfb = real_sys_read;

概念验证

 的#include< SYS / types.h中>
的#define asmlinkage
#定义__userasmlinkage为ssize_t(* real_sys_read)(unsigned int类型FD,焦炭__user * buf中,为size_t计数);
asmlinkage ssize_t供hooked_sys_read(unsigned int类型FD,焦炭__user * buf中,为size_t计数);类型定义为ssize_t(*读指针)(unsigned int类型FD,焦炭__user *数据,为size_t大小);typedef结构xyz_data
{
    读指针myfa;
    读指针myfb;
} xyz_data;EXTERN xyz_data吸气剂(无效);xyz_data吸气剂(无效)
{
    xyz_data数据;
    xyz_data *读卡器=放大器;数据;    阅读器 - > myfa = hooked_sys_read;
    阅读器 - > myfb = real_sys_read;
//下一行编译失败:从兼容的指针类型赋值
//阅读器 - > myfb =安培; real_sys_read;    阅读器 - > myfa =安培; hooked_sys_read;
    阅读器 - > myfa = hooked_sys_read;
    阅读器 - > myfa = * hooked_sys_read;
    阅读器 - > myfa = ** hooked_sys_read;
    阅读器 - > myfa = *** hooked_sys_read;
    阅读器 - > myfa = **** hooked_sys_read;
    返回*阅读器;
}

它编译干净。这是不好的code,虽然 - 仅在重复分配是足以令它坏

I have this struct:

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

and this function definition:

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

(as you might be guessing, this will point to the kernel's __NR_read).

Saving hooked_sys_read to *myfa; is as simple as xyz_data_something->myfa = hooked_sys_read, but what about myfb? I'm not sure xyz_data_something->myfb = &real_sys_read will work.

I'm hijacking some syscalls (If you're interested in the project, everything is available in GitHub) and each hijacked syscall will use that struct to call the real syscall it belongs to (which will be accessed via *myfb), making use of the returned value.

Keep in mind that each syscall has it's own return type.

解决方案

Scenario

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;

Analysis

What you wrote is not type-safe (so the compiler can't help you much), but you are taking the address of the variable that holds the pointer to the 'real sys read' function, not a copy of that pointer (because of the &). You can apply & (and *) to function names willy-nilly and they all end up the same:

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;

You can't do that with pointers to functions. Note that the compiler cannot even diagnose a 'function pointer assigned to object pointer' problem when you do:

xyz_data_something->myfb = &real_sys_read;

You are assigning the address of a (function) pointer variable to a void *, so you are assigning an object pointer to a void pointer, which is legitimate — but incorrect.

Synthesis

You should have one of these two function-type typedefs:

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

Then your structure can be either:

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

Or:

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

Given a structure pointer:

xyz_data *reader = ...;

The following assignments will compile cleanly and work correctly (for both structure types):

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

Proof of Concept

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

It compiles cleanly. It isn't good code, though — the repeated assignments alone are enough to make it bad.

这篇关于初始化一个struct一个函数指针的成员不知道返回的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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